Files
Jyotisha/frontend/tests/consultation-methodology.test.ts
T
Jesse_Chen 2bf7472645
Independent Staging Quality Gate / validate (push) Successful in 10m59s
Independent Staging Quality Gate / publish (push) Successful in 9m7s
fix(consult): run the local skill's full technique spectrum on the web path
Web answers were thinner than a local Agent calling yinduzhanxing-skill:
theme-subset vargas, no visible audit table, and a prompt that dropped the
invocation contract. Bind the commercial method, compute D1–D60 plus Western
layers, and deliver the same Full-Spectrum checklist.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 23:30:36 +08:00

128 lines
5.6 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import {
consultationMethodologyForDomains,
markdownSection,
METHODOLOGY_SECTION_MAX_CHARS,
METHODOLOGY_TOTAL_MAX_CHARS,
} from "../src/lib/consultation-methodology.ts";
import { consultationDomainIds } from "../src/lib/consultation-domain-registry.ts";
test("the route's own strict checklist reaches the answer, not just the package listing", () => {
const methodology = consultationMethodologyForDomains(["career"]);
assert.ok(methodology, "career must resolve a methodology");
const career = methodology.sections.find((section) => section.title.includes("career-timing-strict"));
assert.ok(career, "the career strict route must be delivered as its own section");
assert.match(career.source, /strict-workflow-router\.md$/);
// The checklist is only useful if the specific instructions arrive with it.
assert.match(career.text, /D10/);
assert.match(career.text, /Opportunity contact/);
assert.ok(
methodology.sections.some((section) => section.title.includes("Shared mandatory baseline")),
"every route is read against the shared baseline",
);
assert.ok(
methodology.sections.some((section) => /Full-Spectrum Invocation Contract/.test(section.text)),
"the skill's full-spectrum contract must reach the web model",
);
assert.deepEqual(methodology.domains_without_strict_checklist, []);
});
test("a route the skill declares no checklist for is reported, not filled in with another route's", () => {
const methodology = consultationMethodologyForDomains(["education"]);
assert.ok(methodology);
assert.deepEqual(methodology.domains_without_strict_checklist, ["education"]);
assert.ok(
!methodology.sections.some((section) => section.title.includes("timing-strict") || section.title.includes("verification-strict")),
"no strict section may be substituted for a route that has none",
);
assert.ok(
methodology.sections.some((section) => section.title.includes("Shared mandatory baseline")),
"the baseline still applies",
);
assert.ok(
methodology.sections.some((section) => section.title.includes("Full-spectrum")),
"full-spectrum invocation still applies when a domain has no named checklist",
);
});
test("health uses the skill's health-timing-strict checklist", () => {
const methodology = consultationMethodologyForDomains(["health"]);
assert.ok(methodology);
assert.deepEqual(methodology.domains_without_strict_checklist, []);
const health = methodology.sections.find((section) => section.title.includes("health-timing-strict"));
assert.ok(health);
assert.match(health.text, /D6/);
assert.match(health.text, /D30/);
});
test("a multi-domain plan carries every executed route's checklist once", () => {
const methodology = consultationMethodologyForDomains(["career", "timing", "career"]);
assert.ok(methodology);
const titles = methodology.sections.map((section) => section.title);
assert.equal(titles.filter((title) => title.includes("career-timing-strict")).length, 1);
assert.equal(titles.filter((title) => title.includes("event-timing-strict")).length, 1);
});
test("no plan can spend the answer's context on method", () => {
for (const domain of consultationDomainIds) {
const methodology = consultationMethodologyForDomains([domain]);
assert.ok(methodology, `${domain} must resolve`);
const total = methodology.sections.reduce((sum, section) => sum + section.text.length, 0);
assert.ok(
total <= METHODOLOGY_TOTAL_MAX_CHARS,
`${domain} delivered ${total} chars, over the ${METHODOLOGY_TOTAL_MAX_CHARS} budget`,
);
for (const section of methodology.sections) {
assert.ok(section.text.length <= METHODOLOGY_SECTION_MAX_CHARS);
}
}
});
test("the widest legal plan still fits the budget", () => {
const methodology = consultationMethodologyForDomains(["career", "marriage", "wealth", "timing"]);
assert.ok(methodology);
const total = methodology.sections.reduce((sum, section) => sum + section.text.length, 0);
assert.ok(total <= METHODOLOGY_TOTAL_MAX_CHARS, `delivered ${total} chars`);
});
test("further reading offers the references the skill names, and only ones that exist", () => {
const methodology = consultationMethodologyForDomains(["career"]);
assert.ok(methodology);
assert.ok(methodology.further_reading.length > 0, "the skill names references worth reading");
assert.ok(
methodology.further_reading.includes("references/strict-workflow-router.md"),
"the router the skill points at must be reachable on purpose",
);
for (const path of methodology.further_reading) {
assert.match(path, /^references\//);
assert.ok(!path.includes(".."), "no path may escape the package");
}
assert.ok(
methodology.further_reading.length < 100,
"the index exists to replace the package listing, not to reproduce it",
);
});
test("the delivered method is quoted from the pinned skill version", () => {
const methodology = consultationMethodologyForDomains(["career"]);
assert.ok(methodology);
assert.equal(methodology.skill, "jyotish-vedic-astrology");
assert.match(methodology.version, /^\d+\.\d+\.\d+$/);
});
test("a section is found by heading text so the router may be renumbered", () => {
const source = [
"# Doc",
"## 3. `career-timing-strict`",
"body one",
"## 4. next",
"body two",
].join("\n");
const section = markdownSection(source, "career-timing-strict");
assert.ok(section);
assert.match(section, /body one/);
assert.ok(!section.includes("body two"), "a section stops at the next heading");
assert.equal(markdownSection(source, "absent-route"), null);
});