d35828e76d
Manual SKILL.md updates were blocked by registry sha256 and a byte-equal versions/ gate. Consult now loads the operator-maintained tree; rectification and personal-report stay hashed. Co-authored-by: Cursor <cursoragent@cursor.com>
130 lines
5.7 KiB
TypeScript
130 lines
5.7 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";
|
|
import { resolveLiveJyotishSkill } from "../src/lib/skill-package-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 live skill tree", () => {
|
|
const methodology = consultationMethodologyForDomains(["career"]);
|
|
assert.ok(methodology);
|
|
assert.equal(methodology.skill, "jyotish-vedic-astrology");
|
|
assert.equal(methodology.version, resolveLiveJyotishSkill().version);
|
|
assert.equal(methodology.version.includes("/"), false);
|
|
});
|
|
|
|
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);
|
|
});
|