@wairon/cli 5.1.1-dev.37 → 5.1.1-dev.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +232 -82
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var init_defaults = __esm({
|
|
|
65
65
|
copilot: ".github/prompts",
|
|
66
66
|
codex: ".codex/agents"
|
|
67
67
|
};
|
|
68
|
-
WAIRON_VERSION = "5.1.1-dev.
|
|
68
|
+
WAIRON_VERSION = "5.1.1-dev.38";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -1536,7 +1536,13 @@ var init_specs = __esm({
|
|
|
1536
1536
|
GuaranteeSchema = import_zod7.z.string().min(1);
|
|
1537
1537
|
MethodParamSchema = import_zod7.z.object({
|
|
1538
1538
|
name: import_zod7.z.string(),
|
|
1539
|
-
/**
|
|
1539
|
+
/**
|
|
1540
|
+
* A primitive/builtin or a defined type id (qualified across subsystems, e.g.
|
|
1541
|
+
* "billing.Invoice"), on its own or inside a generic, an array or a UNION:
|
|
1542
|
+
* `Invoice | null`, `Promise<Invoice | null>`, `Invoice[] | null`. Every
|
|
1543
|
+
* identifier the string names has to resolve — see the grammar on
|
|
1544
|
+
* src/models/type-references.ts.
|
|
1545
|
+
*/
|
|
1540
1546
|
type: import_zod7.z.string(),
|
|
1541
1547
|
description: import_zod7.z.string().optional(),
|
|
1542
1548
|
optional: import_zod7.z.boolean().optional()
|
|
@@ -1554,8 +1560,9 @@ var init_specs = __esm({
|
|
|
1554
1560
|
description: import_zod7.z.string(),
|
|
1555
1561
|
signature: import_zod7.z.string(),
|
|
1556
1562
|
// e.g. "save(key: string, data: Buffer): Promise<void>"
|
|
1563
|
+
// e.g. "Promise<void>", or a union: "Invoice | null" — the commonest shape in
|
|
1564
|
+
// any real tree. See the grammar on src/models/type-references.ts.
|
|
1557
1565
|
returns: import_zod7.z.string(),
|
|
1558
|
-
// e.g. "Promise<void>"
|
|
1559
1566
|
/** Structured parameters (authoritative for type checking when present). */
|
|
1560
1567
|
params: import_zod7.z.array(MethodParamSchema).optional(),
|
|
1561
1568
|
/** Concrete wire binding for this method when its component is a Portal (set via sdd_set_endpoints). */
|
|
@@ -1824,8 +1831,10 @@ var init_specs = __esm({
|
|
|
1824
1831
|
TypeKindSchema = import_zod7.z.enum(["entity", "value-object"]);
|
|
1825
1832
|
TypeFieldSchema = import_zod7.z.object({
|
|
1826
1833
|
name: import_zod7.z.string(),
|
|
1834
|
+
// A primitive, or another type id (qualified across subsystems, e.g.
|
|
1835
|
+
// "billing.Invoice") — on its own or inside a generic, an array or a union
|
|
1836
|
+
// ("Invoice[] | null"). See the grammar on src/models/type-references.ts.
|
|
1827
1837
|
type: import_zod7.z.string(),
|
|
1828
|
-
// a primitive, or another type id (qualified across subsystems, e.g. "billing.Invoice")
|
|
1829
1838
|
description: import_zod7.z.string().optional(),
|
|
1830
1839
|
optional: import_zod7.z.boolean().default(false),
|
|
1831
1840
|
/**
|
|
@@ -26827,6 +26836,7 @@ __export(server_exports, {
|
|
|
26827
26836
|
captureBuildStamp: () => captureBuildStamp,
|
|
26828
26837
|
createMcpServer: () => createMcpServer,
|
|
26829
26838
|
isBuildStale: () => isBuildStale,
|
|
26839
|
+
markStale: () => markStale,
|
|
26830
26840
|
startMcpServer: () => startMcpServer,
|
|
26831
26841
|
statusFamilyContext: () => statusFamilyContext
|
|
26832
26842
|
});
|
|
@@ -26907,6 +26917,12 @@ function json(value) {
|
|
|
26907
26917
|
function errText(message) {
|
|
26908
26918
|
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
26909
26919
|
}
|
|
26920
|
+
function structured(content, data) {
|
|
26921
|
+
return { content: [{ type: "text", text: content }], structuredContent: data };
|
|
26922
|
+
}
|
|
26923
|
+
function jsonStructured(value) {
|
|
26924
|
+
return structured(JSON.stringify(value, null, 2), value);
|
|
26925
|
+
}
|
|
26910
26926
|
function renderChangeReport(report2) {
|
|
26911
26927
|
const lines = [report2.dryRun ? `DRY RUN \u2014 nothing was written. ${report2.summary}` : report2.summary];
|
|
26912
26928
|
for (const change of report2.changes) {
|
|
@@ -26920,6 +26936,13 @@ function renderChangeReport(report2) {
|
|
|
26920
26936
|
if (report2.notices.length) lines.push("", "NOTICE:", ...report2.notices.map((n) => `- ${n}`));
|
|
26921
26937
|
return lines.join("\n");
|
|
26922
26938
|
}
|
|
26939
|
+
function writeReceipt(sentence, receipt) {
|
|
26940
|
+
const noticeBlock = receipt.notices.length ? `
|
|
26941
|
+
|
|
26942
|
+
NOTICE:
|
|
26943
|
+
- ${receipt.notices.join("\n- ")}` : "";
|
|
26944
|
+
return structured(`${sentence}${noticeBlock}`, receipt);
|
|
26945
|
+
}
|
|
26923
26946
|
function captureBuildStamp(entryPath) {
|
|
26924
26947
|
try {
|
|
26925
26948
|
const s = fs20.statSync(entryPath);
|
|
@@ -26937,16 +26960,19 @@ function isBuildStale(stamp) {
|
|
|
26937
26960
|
return false;
|
|
26938
26961
|
}
|
|
26939
26962
|
}
|
|
26940
|
-
function
|
|
26941
|
-
|
|
26942
|
-
const first =
|
|
26963
|
+
function markStale(result) {
|
|
26964
|
+
const marked = result.structuredContent ? { ...result, structuredContent: { ...result.structuredContent, staleServer: true } } : result;
|
|
26965
|
+
const first = marked.content?.[0];
|
|
26943
26966
|
if (first && first.type === "text") {
|
|
26944
26967
|
return {
|
|
26945
|
-
...
|
|
26946
|
-
content: [{ ...first, text: `${first.text}${STALE_SERVER_WARNING}` }, ...
|
|
26968
|
+
...marked,
|
|
26969
|
+
content: [{ ...first, text: `${first.text}${STALE_SERVER_WARNING}` }, ...marked.content.slice(1)]
|
|
26947
26970
|
};
|
|
26948
26971
|
}
|
|
26949
|
-
return
|
|
26972
|
+
return marked;
|
|
26973
|
+
}
|
|
26974
|
+
function withStaleWarning(result) {
|
|
26975
|
+
return isBuildStale(SERVER_BUILD_STAMP) ? markStale(result) : result;
|
|
26950
26976
|
}
|
|
26951
26977
|
function reg(server, name, config, cb) {
|
|
26952
26978
|
const guarded = (args) => {
|
|
@@ -26958,8 +26984,9 @@ function reg(server, name, config, cb) {
|
|
|
26958
26984
|
server.registerTool(name, strictConfig, guarded);
|
|
26959
26985
|
}
|
|
26960
26986
|
function statusForCreate(label, stated, existing) {
|
|
26961
|
-
|
|
26962
|
-
const held =
|
|
26987
|
+
const stored = existing?.status;
|
|
26988
|
+
const held = stored !== void 0 && STATUS_ORDER.includes(stored) ? stored : void 0;
|
|
26989
|
+
if (stated === void 0) return { status: held ?? "draft" };
|
|
26963
26990
|
if (held === void 0) return { status: stated };
|
|
26964
26991
|
const rank = (s) => STATUS_ORDER.indexOf(s);
|
|
26965
26992
|
if (rank(stated) < rank(held)) {
|
|
@@ -27275,8 +27302,9 @@ function createMcpServer(options = {}) {
|
|
|
27275
27302
|
server,
|
|
27276
27303
|
"sdd_initialize_system",
|
|
27277
27304
|
{
|
|
27278
|
-
description: "Initialize the L0 System Specification (system.yaml). Re-running it on an existing system RE-AUTHORS it: the fields above are replaced, and everything this tool cannot express (databases, the project gateway publicInterfaces, diagram defaults) is carried forward.",
|
|
27279
|
-
inputSchema: systemInput
|
|
27305
|
+
description: "Initialize the L0 System Specification (system.yaml). Re-running it on an existing system RE-AUTHORS it: the fields above are replaced, and everything this tool cannot express (databases, the project gateway publicInterfaces, diagram defaults) is carried forward. The answer carries a write receipt as structured content beside the sentence \u2014 what was written, and whether a system spec already existed \u2014 so a caller never has to read English to find out.",
|
|
27306
|
+
inputSchema: systemInput,
|
|
27307
|
+
outputSchema: specWriteReceiptOutput
|
|
27280
27308
|
},
|
|
27281
27309
|
({ name, vision, boundaries, globalRequirements, targetLanguage }) => {
|
|
27282
27310
|
try {
|
|
@@ -27298,11 +27326,10 @@ function createMcpServer(options = {}) {
|
|
|
27298
27326
|
next.updatedAt = now;
|
|
27299
27327
|
saveSystemSpec2(next);
|
|
27300
27328
|
const notices = existing ? rewriteNotices({ label: `System spec "${existing.name}"`, carried, cleared, removed: [] }) : [];
|
|
27301
|
-
|
|
27302
|
-
|
|
27303
|
-
|
|
27304
|
-
|
|
27305
|
-
return text(`Successfully ${existing ? "re-authored" : "initialized"} L0 System Spec for "${name}".${noticeBlock}`);
|
|
27329
|
+
return writeReceipt(
|
|
27330
|
+
`Successfully ${existing ? "re-authored" : "initialized"} L0 System Spec for "${name}".`,
|
|
27331
|
+
{ kind: "system", id: "system", name, replacedExisting: Boolean(existing), notices }
|
|
27332
|
+
);
|
|
27306
27333
|
} catch (e) {
|
|
27307
27334
|
return errText(String(e));
|
|
27308
27335
|
}
|
|
@@ -27339,8 +27366,9 @@ NOTICE:
|
|
|
27339
27366
|
server,
|
|
27340
27367
|
"sdd_add_subsystem",
|
|
27341
27368
|
{
|
|
27342
|
-
description: "Add an L1 Subsystem / Service under the system boundary. publicInterfaces should bind each entry to the component that realizes it (the subsystem's published surface); if components do not exist yet, add them later with sdd_set_public_interfaces. Re-running it on an existing id RE-AUTHORS it: the fields above are replaced, lint/ext are carried forward, and the stored status is kept unless this input states a higher one.",
|
|
27343
|
-
inputSchema: subsystemInput
|
|
27369
|
+
description: "Add an L1 Subsystem / Service under the system boundary. publicInterfaces should bind each entry to the component that realizes it (the subsystem's published surface); if components do not exist yet, add them later with sdd_set_public_interfaces. Re-running it on an existing id RE-AUTHORS it: the fields above are replaced, lint/ext are carried forward, and the stored status is kept unless this input states a higher one. The answer carries a write receipt as structured content beside the sentence \u2014 the status written, whether a spec already held the id, and the child project directory a chained subsystem scaffolded.",
|
|
27370
|
+
inputSchema: subsystemInput,
|
|
27371
|
+
outputSchema: specWriteReceiptOutput
|
|
27344
27372
|
},
|
|
27345
27373
|
({ id, name, description, publicInterfaces, projectPath, targetLanguage, profile, designDepth, trustedLinks, lifecycle, status: status2 }) => {
|
|
27346
27374
|
try {
|
|
@@ -27371,17 +27399,24 @@ NOTICE:
|
|
|
27371
27399
|
const cleared = clearedByOmission(existing, spec, subsystemInputFields);
|
|
27372
27400
|
if (existing) spec.createdAt = existing.createdAt;
|
|
27373
27401
|
const notices = existing ? rewriteNotices({ label: `Subsystem "${id}"`, carried: ["createdAt", ...carried], cleared, removed: [] }) : [];
|
|
27374
|
-
const
|
|
27375
|
-
|
|
27376
|
-
|
|
27377
|
-
|
|
27402
|
+
const receipt = {
|
|
27403
|
+
kind: "subsystem",
|
|
27404
|
+
id,
|
|
27405
|
+
name,
|
|
27406
|
+
replacedExisting: Boolean(existing),
|
|
27407
|
+
status: resolved.status,
|
|
27408
|
+
notices
|
|
27409
|
+
};
|
|
27378
27410
|
if (projectPath && projectPath.trim() !== "") {
|
|
27379
27411
|
const { createChainedSubsystem: createChainedSubsystem3 } = requireProvision();
|
|
27380
27412
|
createChainedSubsystem3(spec, name);
|
|
27381
|
-
return
|
|
27413
|
+
return writeReceipt(
|
|
27414
|
+
`Successfully added external subsystem "${name}" (${id}) and scaffolded its child project at ${projectPath}.`,
|
|
27415
|
+
{ ...receipt, scaffoldedProjectPath: projectPath }
|
|
27416
|
+
);
|
|
27382
27417
|
}
|
|
27383
27418
|
saveSubsystemSpec2(spec);
|
|
27384
|
-
return
|
|
27419
|
+
return writeReceipt(`Successfully added L1 Subsystem Spec "${name}" (${id}).`, receipt);
|
|
27385
27420
|
} catch (e) {
|
|
27386
27421
|
return errText(String(e));
|
|
27387
27422
|
}
|
|
@@ -27577,8 +27612,9 @@ NOTICE:
|
|
|
27577
27612
|
server,
|
|
27578
27613
|
"sdd_add_component",
|
|
27579
27614
|
{
|
|
27580
|
-
description: `Add an L2 Component under a subsystem. componentType is a building block (Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer) or the pattern Repository. Specialist and Gateway are retired (STEREOTYPE_RETIRED) and cannot be authored: logic is an Orchestrator with a dependencyClass (pure | read; unset = a workflow), and a gateway is a Portal with the gateway variant (set variant with sdd_update_spec). Patterns set "owns" (their private member blocks); all components set "dependsOn" (collaborators \u2014 facades or standalone blocks). Held/persisted state (configs, permissions, sessions, caches): model the Repository recipe \u2014 a Store + Registry (write) + Index (read), plus a Query for computed reads over the Store, owned by a Repository facade consumers depend on; a deliberately standalone Store is the sanctioned lightweight form (workflow-layer consumers + lint.allow on UNOWNED_STORE). Never hold state as fields inside an Orchestrator because a Store link was refused. Re-running it on an existing id RE-AUTHORS it: the fields above are replaced (an omitted array is CLEARED), while lint.allow, a Portal's auth, variant, patterns and externalLinks are carried forward \u2014 edit those with sdd_update_spec. The stored status is kept unless this input states a higher one.`,
|
|
27581
|
-
inputSchema: componentInput
|
|
27615
|
+
description: `Add an L2 Component under a subsystem. componentType is a building block (Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer) or the pattern Repository. Specialist and Gateway are retired (STEREOTYPE_RETIRED) and cannot be authored: logic is an Orchestrator with a dependencyClass (pure | read; unset = a workflow), and a gateway is a Portal with the gateway variant (set variant with sdd_update_spec). Patterns set "owns" (their private member blocks); all components set "dependsOn" (collaborators \u2014 facades or standalone blocks). Held/persisted state (configs, permissions, sessions, caches): model the Repository recipe \u2014 a Store + Registry (write) + Index (read), plus a Query for computed reads over the Store, owned by a Repository facade consumers depend on; a deliberately standalone Store is the sanctioned lightweight form (workflow-layer consumers + lint.allow on UNOWNED_STORE). Never hold state as fields inside an Orchestrator because a Store link was refused. Re-running it on an existing id RE-AUTHORS it: the fields above are replaced (an omitted array is CLEARED), while lint.allow, a Portal's auth, variant, patterns and externalLinks are carried forward \u2014 edit those with sdd_update_spec. The stored status is kept unless this input states a higher one. The answer carries a write receipt as structured content beside the sentence \u2014 the status written, whether a spec already held the id, and every gate notice the write raised, each as its own entry.`,
|
|
27616
|
+
inputSchema: componentInput,
|
|
27617
|
+
outputSchema: specWriteReceiptOutput
|
|
27582
27618
|
},
|
|
27583
27619
|
({ id, name, description, subsystem, componentType, owns, dependsOn, portalType, basePath, dispatch, durability, dependencyClass, emits, subscribesTo, ext, status: status2 }) => {
|
|
27584
27620
|
try {
|
|
@@ -27621,11 +27657,10 @@ NOTICE:
|
|
|
27621
27657
|
removed: []
|
|
27622
27658
|
}));
|
|
27623
27659
|
}
|
|
27624
|
-
|
|
27625
|
-
|
|
27626
|
-
|
|
27627
|
-
|
|
27628
|
-
return text(`Successfully ${existing ? "re-authored" : "added"} L2 Component Spec "${name}" (${id}, ${componentType}).${noticeBlock}`);
|
|
27660
|
+
return writeReceipt(
|
|
27661
|
+
`Successfully ${existing ? "re-authored" : "added"} L2 Component Spec "${name}" (${id}, ${componentType}).`,
|
|
27662
|
+
{ kind: "component", id, name, replacedExisting: Boolean(existing), status: resolved.status, notices }
|
|
27663
|
+
);
|
|
27629
27664
|
} catch (e) {
|
|
27630
27665
|
return errText(String(e));
|
|
27631
27666
|
}
|
|
@@ -27635,12 +27670,14 @@ NOTICE:
|
|
|
27635
27670
|
name: import_zod11.z.string(),
|
|
27636
27671
|
description: import_zod11.z.string(),
|
|
27637
27672
|
signature: import_zod11.z.string(),
|
|
27638
|
-
returns: import_zod11.z.string(),
|
|
27673
|
+
returns: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The type the method answers with")),
|
|
27639
27674
|
params: import_zod11.z.array(import_zod11.z.object({
|
|
27640
27675
|
name: import_zod11.z.string(),
|
|
27641
|
-
type: import_zod11.z.string().describe('
|
|
27676
|
+
type: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The parameter's type")),
|
|
27642
27677
|
description: import_zod11.z.string().optional(),
|
|
27643
|
-
optional: import_zod11.z.boolean().optional()
|
|
27678
|
+
optional: import_zod11.z.boolean().optional().describe(
|
|
27679
|
+
'Whether the parameter may be OMITTED by a caller. It is not nullability: a parameter that must be passed but may be passed as nothing is a required parameter whose type is a union \u2014 "ProjectConfig | null". Say whichever is true; they are different contracts.'
|
|
27680
|
+
)
|
|
27644
27681
|
}).strict()).optional().describe("Structured parameters \u2014 authoritative for type checking (the prose signature becomes display-only). Strongly preferred."),
|
|
27645
27682
|
guarantees: import_zod11.z.array(import_zod11.z.string().min(1)).optional().describe("Semantic guarantees the method promises (combinable); any guarantee a narrative step asserts must be declared here. Builtin tokens: idempotent | atomic | transactional | exactly-once; extension packs may declare more (any other token is UNKNOWN_GUARANTEE)"),
|
|
27646
27683
|
effect: import_zod11.z.enum(["read", "write"]).optional().describe("State-effect direction on the component's held state \u2014 required on a durable Store's contract methods so the durability round-trip rule can pair writes with hydration read-backs"),
|
|
@@ -27669,8 +27706,9 @@ NOTICE:
|
|
|
27669
27706
|
server,
|
|
27670
27707
|
"sdd_define_interface",
|
|
27671
27708
|
{
|
|
27672
|
-
description: "Define an L3 Contract / Interface with method signatures for a component. Prefer supplying structured `params` per method \u2014 they are the authoritative source for type checking (the free-form signature string then becomes display-only and is never heuristically parsed). A method declares the finding codes it reports in `findings` ({code, severity, summary}); each code must be anchored in the method's source file, as a string literal or a property-access name (UNREALIZED_FINDING). Re-defining an existing id REPLACES the method list: a method left out of the input is REMOVED (and reported); spec-level lint/ext and each method's endpoint binding are carried forward, and the stored status is kept unless this input states a higher one.",
|
|
27673
|
-
inputSchema: interfaceInput
|
|
27709
|
+
description: "Define an L3 Contract / Interface with method signatures for a component. Prefer supplying structured `params` per method \u2014 they are the authoritative source for type checking (the free-form signature string then becomes display-only and is never heuristically parsed). A method declares the finding codes it reports in `findings` ({code, severity, summary}); each code must be anchored in the method's source file, as a string literal or a property-access name (UNREALIZED_FINDING). Re-defining an existing id REPLACES the method list: a method left out of the input is REMOVED (and reported); spec-level lint/ext and each method's endpoint binding are carried forward, and the stored status is kept unless this input states a higher one. The answer carries a write receipt as structured content beside the sentence \u2014 the status written, whether a spec already held the id, and the notices a restatement raised, each as its own entry.",
|
|
27710
|
+
inputSchema: interfaceInput,
|
|
27711
|
+
outputSchema: specWriteReceiptOutput
|
|
27674
27712
|
},
|
|
27675
27713
|
({ id, name, description, component, methods, status: status2 }) => {
|
|
27676
27714
|
try {
|
|
@@ -27713,11 +27751,10 @@ NOTICE:
|
|
|
27713
27751
|
removedSuffix: " (endpoint bindings included)"
|
|
27714
27752
|
}));
|
|
27715
27753
|
}
|
|
27716
|
-
|
|
27717
|
-
|
|
27718
|
-
|
|
27719
|
-
|
|
27720
|
-
return text(`Successfully ${existing ? "re-authored" : "defined"} L3 Interface Contract "${name}" (${id}).${noticeBlock}`);
|
|
27754
|
+
return writeReceipt(
|
|
27755
|
+
`Successfully ${existing ? "re-authored" : "defined"} L3 Interface Contract "${name}" (${id}).`,
|
|
27756
|
+
{ kind: "interface", id, name, replacedExisting: Boolean(existing), status: resolved.status, notices }
|
|
27757
|
+
);
|
|
27721
27758
|
} catch (e) {
|
|
27722
27759
|
return errText(String(e));
|
|
27723
27760
|
}
|
|
@@ -27862,8 +27899,9 @@ NOTICE:
|
|
|
27862
27899
|
server,
|
|
27863
27900
|
"sdd_write_narrative",
|
|
27864
27901
|
{
|
|
27865
|
-
description: "Write L4 Concrete Implementation spec containing L5 method narratives. Narratives are a FLAT ordered step list; flow steps (branch/switch/loop/try/parallel/jump/return/throw) jump by step number \u2014 blocks are just skipped regions. Steps may declare a `label` anchor, and every jump field has a *Label twin (toLabel, onTrueLabel, endLabel, \u2026) resolved to step numbers at write time \u2014 prefer labels over hand-counted numbers; an unresolvable label rejects the write. Detail dial per method: full (narrative required) | calls-only (call choreography suffices) | intent (prose instead of steps); omitted = stereotype default (Portal/Observer/Adapter: calls-only, Store/Index/Registry: intent, else full). Conformance dial per method or spec: declared | anchored | off \u2014 how strictly structural conformance requires contract methods to be realized in their source file (omitted = Portal: anchored, else declared). A method whose body lives in its own file names it in the method's sourcePath; the implementation's sourcePath is the default for every method that names none. Re-authoring an existing id REPLACES the method list: a method left out of the input is REMOVED together with its narrative (and reported); spec-level lint/ext are carried forward, and the stored status is kept unless this input states a higher one.",
|
|
27866
|
-
inputSchema: implInput
|
|
27902
|
+
description: "Write L4 Concrete Implementation spec containing L5 method narratives. Narratives are a FLAT ordered step list; flow steps (branch/switch/loop/try/parallel/jump/return/throw) jump by step number \u2014 blocks are just skipped regions. Steps may declare a `label` anchor, and every jump field has a *Label twin (toLabel, onTrueLabel, endLabel, \u2026) resolved to step numbers at write time \u2014 prefer labels over hand-counted numbers; an unresolvable label rejects the write. Detail dial per method: full (narrative required) | calls-only (call choreography suffices) | intent (prose instead of steps); omitted = stereotype default (Portal/Observer/Adapter: calls-only, Store/Index/Registry: intent, else full). Conformance dial per method or spec: declared | anchored | off \u2014 how strictly structural conformance requires contract methods to be realized in their source file (omitted = Portal: anchored, else declared). A method whose body lives in its own file names it in the method's sourcePath; the implementation's sourcePath is the default for every method that names none. Re-authoring an existing id REPLACES the method list: a method left out of the input is REMOVED together with its narrative (and reported); spec-level lint/ext are carried forward, and the stored status is kept unless this input states a higher one. The answer carries a write receipt as structured content beside the sentence \u2014 the status written, whether a spec already held the id, and the notices a restatement raised, each as its own entry.",
|
|
27903
|
+
inputSchema: implInput,
|
|
27904
|
+
outputSchema: specWriteReceiptOutput
|
|
27867
27905
|
},
|
|
27868
27906
|
({ id, name, description, contract, sourcePath, simPath, technologies, detail, conformance, methods, status: status2 }) => {
|
|
27869
27907
|
try {
|
|
@@ -27919,11 +27957,10 @@ NOTICE:
|
|
|
27919
27957
|
removedSuffix: " (L5 narratives included)"
|
|
27920
27958
|
}));
|
|
27921
27959
|
}
|
|
27922
|
-
|
|
27923
|
-
|
|
27924
|
-
|
|
27925
|
-
|
|
27926
|
-
return text(`Successfully saved L4 Implementation Spec "${name}" (${id}) with method narratives.${noticeBlock}`);
|
|
27960
|
+
return writeReceipt(
|
|
27961
|
+
`Successfully saved L4 Implementation Spec "${name}" (${id}) with method narratives.`,
|
|
27962
|
+
{ kind: "implementation", id, name, replacedExisting: Boolean(existing), status: resolved.status, notices }
|
|
27963
|
+
);
|
|
27927
27964
|
} catch (e) {
|
|
27928
27965
|
return errText(String(e));
|
|
27929
27966
|
}
|
|
@@ -27938,13 +27975,18 @@ NOTICE:
|
|
|
27938
27975
|
group: import_zod11.z.string().optional().describe("Optional logical group ID to organize this type in subfolders"),
|
|
27939
27976
|
fields: import_zod11.z.array(import_zod11.z.object({
|
|
27940
27977
|
name: import_zod11.z.string(),
|
|
27941
|
-
type: import_zod11.z.string(),
|
|
27978
|
+
type: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The field's type")),
|
|
27942
27979
|
description: import_zod11.z.string().optional(),
|
|
27943
27980
|
optional: import_zod11.z.boolean().optional(),
|
|
27944
27981
|
key: import_zod11.z.enum(["primary", "unique", "foreign"]).optional().describe("Identity marker (PK/unique/FK) for ERD and database schema derivation"),
|
|
27945
27982
|
references: import_zod11.z.string().optional().describe('For foreign keys, the referenced type/table id and optional field, e.g. "invoice.id"')
|
|
27946
27983
|
}).strict()).optional().describe('Data fields (type is a primitive or a qualified type id, e.g. "billing.Invoice")'),
|
|
27947
|
-
methods: import_zod11.z.array(import_zod11.z.object({
|
|
27984
|
+
methods: import_zod11.z.array(import_zod11.z.object({
|
|
27985
|
+
name: import_zod11.z.string(),
|
|
27986
|
+
signature: import_zod11.z.string(),
|
|
27987
|
+
returns: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The type the method answers with")),
|
|
27988
|
+
description: import_zod11.z.string().optional()
|
|
27989
|
+
}).strict()).optional().describe("Pure intrinsic methods only"),
|
|
27948
27990
|
componentClass: import_zod11.z.string().optional().describe("Optional component id that implements or owns this logical entity"),
|
|
27949
27991
|
invariants: import_zod11.z.array(import_zod11.z.object({
|
|
27950
27992
|
id: import_zod11.z.string().describe("Stable invariant id, unique within the entity"),
|
|
@@ -27959,8 +28001,9 @@ NOTICE:
|
|
|
27959
28001
|
server,
|
|
27960
28002
|
"sdd_add_type",
|
|
27961
28003
|
{
|
|
27962
|
-
description: "Define an entity or value-object type (the data components operate on). Entities are owned by a subsystem; shared value objects omit subsystem (system-level). Fields are data; methods are PURE intrinsic behaviour only \u2014 anything needing a collaborator belongs on a component, taking the entity as an argument. Re-defining an existing id REPLACES fields/methods/invariants (an omitted list is CLEARED, and a dropped member is reported); lint/ext are carried forward.",
|
|
27963
|
-
inputSchema: typeInput
|
|
28004
|
+
description: "Define an entity or value-object type (the data components operate on). Entities are owned by a subsystem; shared value objects omit subsystem (system-level). Fields are data; methods are PURE intrinsic behaviour only \u2014 anything needing a collaborator belongs on a component, taking the entity as an argument. Re-defining an existing id REPLACES fields/methods/invariants (an omitted list is CLEARED, and a dropped member is reported); lint/ext are carried forward. The answer carries a write receipt as structured content beside the sentence \u2014 whether a spec already held the id, and the notices a restatement raised, each as its own entry. A type carries no lifecycle status, so the receipt states none.",
|
|
28005
|
+
inputSchema: typeInput,
|
|
28006
|
+
outputSchema: specWriteReceiptOutput
|
|
27964
28007
|
},
|
|
27965
28008
|
({ kind, id, name, description, subsystem, group, fields, methods, componentClass, invariants, database, table, linkedEntity }) => {
|
|
27966
28009
|
try {
|
|
@@ -28007,11 +28050,10 @@ NOTICE:
|
|
|
28007
28050
|
removedNoun: "member"
|
|
28008
28051
|
}));
|
|
28009
28052
|
}
|
|
28010
|
-
|
|
28011
|
-
|
|
28012
|
-
|
|
28013
|
-
|
|
28014
|
-
return text(`Successfully ${existing ? "re-authored" : "defined"} ${kind} type "${name}" (${id}).${noticeBlock}`);
|
|
28053
|
+
return writeReceipt(
|
|
28054
|
+
`Successfully ${existing ? "re-authored" : "defined"} ${kind} type "${name}" (${id}).`,
|
|
28055
|
+
{ kind: "type", id, name, replacedExisting: Boolean(existing), notices }
|
|
28056
|
+
);
|
|
28015
28057
|
} catch (e) {
|
|
28016
28058
|
return errText(String(e));
|
|
28017
28059
|
}
|
|
@@ -28021,11 +28063,12 @@ NOTICE:
|
|
|
28021
28063
|
server,
|
|
28022
28064
|
"sdd_validate_tree",
|
|
28023
28065
|
{
|
|
28024
|
-
description: "Validate the SDD spec tree, checking parent references, contract compatibility, narratives, and component type boundaries. Supports scoping and recursion controls.",
|
|
28066
|
+
description: "Validate the SDD spec tree, checking parent references, contract compatibility, narratives, and component type boundaries. Supports scoping and recursion controls. Findings come back as structured content too, under the schema this tool declares \u2014 errors and warnings already split, each with its code, severity, message and the spec it concerns \u2014 so a caller filters them as objects instead of parsing the JSON text block and hoping its shape holds.",
|
|
28025
28067
|
inputSchema: {
|
|
28026
28068
|
subsystem: import_zod11.z.string().optional().describe("Only validate the specified subsystem (granular)"),
|
|
28027
28069
|
recursive: import_zod11.z.boolean().optional().describe("Whether to recursively validate subprojects (default: true)")
|
|
28028
|
-
}
|
|
28070
|
+
},
|
|
28071
|
+
outputSchema: validateTreeOutput
|
|
28029
28072
|
},
|
|
28030
28073
|
({ subsystem, recursive }) => {
|
|
28031
28074
|
try {
|
|
@@ -28038,7 +28081,7 @@ NOTICE:
|
|
|
28038
28081
|
scopeSubsystem: subsystem,
|
|
28039
28082
|
recursive: recursive ?? true
|
|
28040
28083
|
});
|
|
28041
|
-
return
|
|
28084
|
+
return jsonStructured({
|
|
28042
28085
|
valid: result.valid,
|
|
28043
28086
|
errors: result.issues.filter((i) => i.severity === "error"),
|
|
28044
28087
|
warnings: result.issues.filter((i) => i.severity === "warning"),
|
|
@@ -28053,17 +28096,19 @@ NOTICE:
|
|
|
28053
28096
|
server,
|
|
28054
28097
|
"sdd_get_spec",
|
|
28055
28098
|
{
|
|
28056
|
-
description: `Get/read the parsed JSON contents of a specific spec from the spec tree. Returns structural contents without file system path searching. Pass "methods" to read only the named methods of a contract, an implementation or a type \u2014 a 45-method spec fetched whole to look at one of them is the read side of the same waste a restatement is on the write side; the answer then carries a "partialResult" marker naming what was left out, and must never be re-authored from. For a variant-tagged COMPONENT the result also carries a derived, read-only "variantGuidance" (the variant's base, its implementation guidance, and the same-variant sibling components to implement alike) \u2014 it is resolved from the variant registry, not part of the spec, so never write it back.`,
|
|
28099
|
+
description: `Get/read the parsed JSON contents of a specific spec from the spec tree. Returns structural contents without file system path searching. Pass "methods" to read only the named methods of a contract, an implementation or a type \u2014 a 45-method spec fetched whole to look at one of them is the read side of the same waste a restatement is on the write side; the answer then carries a "partialResult" marker naming what was left out, and must never be re-authored from. For a variant-tagged COMPONENT the result also carries a derived, read-only "variantGuidance" (the variant's base, its implementation guidance, and the same-variant sibling components to implement alike) \u2014 it is resolved from the variant registry, not part of the spec, so never write it back. The structured content carries the same answer with the two derived markers KEPT SEPARATE from the stored spec ({kind, id, spec, partialResult?, variantGuidance?}), so nothing derived can be mistaken for something stored; the text block folds them in as it always has.`,
|
|
28057
28100
|
inputSchema: {
|
|
28058
28101
|
kind: import_zod11.z.enum(["system", "subsystem", "component", "interface", "implementation", "type"]).describe("The kind of specification"),
|
|
28059
28102
|
id: import_zod11.z.string().describe('The identifier of the spec to fetch (the L0 system spec is a singleton \u2014 pass the system name or "system")'),
|
|
28060
28103
|
methods: import_zod11.z.array(import_zod11.z.string().min(1)).optional().describe("Return only these methods by name; every other field of the spec comes back unchanged. Only an interface, an implementation or a type declares methods \u2014 asking for one elsewhere is refused, as is a name the spec does not declare (the answer names the ones it does). Omit it for the whole spec.")
|
|
28061
|
-
}
|
|
28104
|
+
},
|
|
28105
|
+
outputSchema: getSpecOutput
|
|
28062
28106
|
},
|
|
28063
28107
|
({ kind, id, methods }) => {
|
|
28064
28108
|
try {
|
|
28065
28109
|
const specs = requireSpecs();
|
|
28066
28110
|
let result = null;
|
|
28111
|
+
let partial = null;
|
|
28067
28112
|
switch (kind) {
|
|
28068
28113
|
case "system":
|
|
28069
28114
|
result = specs.loadSystemSpec();
|
|
@@ -28100,21 +28145,26 @@ NOTICE:
|
|
|
28100
28145
|
);
|
|
28101
28146
|
}
|
|
28102
28147
|
const kept = declared.filter((m) => methods.includes(String(m?.name)));
|
|
28103
|
-
|
|
28104
|
-
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
shown: kept.map((m) => String(m?.name)),
|
|
28108
|
-
omitted: names.length - kept.length,
|
|
28109
|
-
warning: `PARTIAL: ${names.length - kept.length} of this spec's ${names.length} methods are not in this answer. Never re-author from it \u2014 sdd_define_interface and sdd_write_narrative REPLACE the method list, so every method missing here would be removed from the spec.`
|
|
28110
|
-
}
|
|
28148
|
+
partial = {
|
|
28149
|
+
shown: kept.map((m) => String(m?.name)),
|
|
28150
|
+
omitted: names.length - kept.length,
|
|
28151
|
+
warning: `PARTIAL: ${names.length - kept.length} of this spec's ${names.length} methods are not in this answer. Never re-author from it \u2014 sdd_define_interface and sdd_write_narrative REPLACE the method list, so every method missing here would be removed from the spec.`
|
|
28111
28152
|
};
|
|
28153
|
+
result = { ...result, methods: kept };
|
|
28112
28154
|
}
|
|
28113
|
-
|
|
28114
|
-
|
|
28115
|
-
|
|
28116
|
-
|
|
28117
|
-
|
|
28155
|
+
const guidance = kind === "component" ? resolveComponentVariantGuidance(result) : null;
|
|
28156
|
+
const folded = {
|
|
28157
|
+
...result,
|
|
28158
|
+
...partial ? { partialResult: partial } : {},
|
|
28159
|
+
...guidance ? { variantGuidance: guidance } : {}
|
|
28160
|
+
};
|
|
28161
|
+
return structured(JSON.stringify(folded, null, 2), {
|
|
28162
|
+
kind,
|
|
28163
|
+
id,
|
|
28164
|
+
spec: result,
|
|
28165
|
+
...partial ? { partialResult: partial } : {},
|
|
28166
|
+
...guidance ? { variantGuidance: guidance } : {}
|
|
28167
|
+
});
|
|
28118
28168
|
} catch (e) {
|
|
28119
28169
|
return errText(String(e));
|
|
28120
28170
|
}
|
|
@@ -28168,11 +28218,13 @@ NOTICE:
|
|
|
28168
28218
|
id: import_zod11.z.string().describe("The ID of the spec to update (namespaced if needed)"),
|
|
28169
28219
|
delta: import_zod11.z.record(import_zod11.z.any()).describe(`The partial fields to merge into the spec. ARRAYS UPSERT, they do not replace: an array whose elements carry an identity is merged element-by-element, so a delta naming ONE element leaves the others intact. Identity is "name" or "id" by default, and per field: dispatch by "capability", lifecycle by phase+component+method, emits/subscribesTo by topic+event, trustedLinks by "subsystem", invariants and patterns by "id", lint.allow by "code", an interface method's findings by "code", boundaries by "name", globalRequirements by "description", switch cases by "value", try catches by "error". Identity merging applies at EVERY depth, including an array INSIDE an element (a method's params, a step's catches). Add "action: 'delete'" (or "remove: true") alongside that identity to REMOVE an element \u2014 including a stale lint allow. Arrays of plain STRINGS (owns, dependsOn, guarantees) carry no per-element identity and are replaced wholesale; pass [] to clear any array outright. To REMOVE an optional field entirely, list it in "unset": e.g. {"unset": ["basePath", "variant"]} \u2014 passing null/undefined means "no change" (they are skipped), and writing "" would leave the field present but empty, which is a different and usually wrong spec. Unsetting a required field is refused by schema validation, which names it. For narrative steps, match by "stepNumber" and use "action: 'insert'" (shifts subsequent steps up) or "action: 'delete'" (shifts subsequent steps down and removes it). Step entries apply in ASCENDING stepNumber order, each against the numbering the earlier entries of the SAME delta left behind \u2014 delete step 3 and step 7 becomes step 6 \u2014 so prefer labels, and restate the step's "label" or "description" on a delete to have it checked against the step actually addressed. Renumbering RELOCATES every flow jump field (onTrueStep/onFalseStep/cases.step/defaultStep/endStep/catches.step/finallyStep/toStep) in the same narrative. A delete is REJECTED when the narrative has no such step, when a jump still targets it (retarget the referrers first), when a restated label/description does not match, or when it is a loop/try/parallel header whose body would be left standing (retype the header first to dissolve the region, then delete it). Changing a step's "type" REBUILDS it for the new type: its description and label are kept and every field the new type cannot carry is dropped (returned as a NOTICE); a delta that retypes AND sets such a field is refused. A step delta is also refused when it carries a marker the merge does not recognise: a non-boolean "remove", an "action" that is neither "insert" nor "delete", a "captureJumps" outside an insert, or no "stepNumber" to address. Inserting AT a jump target relocates those jumps past the inserted step by default (a NOTICE is returned) \u2014 add "captureJumps": true on the inserted step to retarget entry jumps onto it (loop/try endStep region tails always relocate with the body and are never captured). Every jump field has a "*Label" twin (toLabel, onFalseLabel, endLabel, \u2026, and "label" on a cases/catches entry) resolved against step labels AFTER the merge, so a delta may anchor on a label only pre-existing steps carry; a label the delta supplies REPLACES the stored number it twins, while setting the number and its label together in one delta is refused as a contradiction. Reference ids in deltas may use LOCAL names \u2014 they are qualified against the spec's namespace exactly as the loader would. Per-spec lint suppression: set "lint: { allow: [{ code, reason }] }" to silence a WARNING code on this spec only (errors always surface; stale allows are flagged). This delta is deliberately OPEN below its top level \u2014 the shapes nest further than a schema here should restate \u2014 so a key that is not a field at its depth is not refused, it is NAMED BACK under NO EFFECT in the answer, together with any value the spec already held and any "unset" that removed nothing. Read that list: it is where a nested typo shows up.`),
|
|
28170
28220
|
dryRun: import_zod11.z.boolean().optional().describe("Ask what this delta WOULD do instead of doing it. The whole write runs, the candidate gate included, and the answer is the change report it would have produced \u2014 marked DRY RUN, with nothing stamped and not one byte of the stored file moved. Use it before a delta that renumbers a long narrative.")
|
|
28171
|
-
}
|
|
28221
|
+
},
|
|
28222
|
+
outputSchema: specChangeReportOutput
|
|
28172
28223
|
},
|
|
28173
28224
|
({ kind, id, delta, dryRun }) => {
|
|
28174
28225
|
try {
|
|
28175
|
-
|
|
28226
|
+
const report2 = updateSpecGated(kind, id, delta, dryRun);
|
|
28227
|
+
return structured(renderChangeReport(report2), report2);
|
|
28176
28228
|
} catch (e) {
|
|
28177
28229
|
return errText(String(e));
|
|
28178
28230
|
}
|
|
@@ -28376,7 +28428,7 @@ async function startMcpServer() {
|
|
|
28376
28428
|
} catch {
|
|
28377
28429
|
}
|
|
28378
28430
|
}
|
|
28379
|
-
var import_mcp, import_stdio, import_zod11, import_types3, fs20, path27, import_url, SERVER_BUILD_STAMP, STALE_SERVER_WARNING, SPEC_WRITE_TOOLS, listChangedEmitters, STORE_MANAGED_FIELDS,
|
|
28431
|
+
var import_mcp, import_stdio, import_zod11, import_types3, fs20, path27, import_url, TYPE_REF_GRAMMAR, staleServerOutput, SPEC_KINDS, STATUS_ORDER, specWriteReceiptOutput, specChangeOutput, specChangeReportOutput, validationIssueOutput, validateTreeOutput, getSpecOutput, SERVER_BUILD_STAMP, STALE_SERVER_WARNING, SPEC_WRITE_TOOLS, listChangedEmitters, STORE_MANAGED_FIELDS, statusInput, ALWAYS_CARRIED_FIELDS, SKILL_RESOURCE_MIME, AGENT_BRIEF_SCHEME;
|
|
28380
28432
|
var init_server = __esm({
|
|
28381
28433
|
"src/mcp/server.ts"() {
|
|
28382
28434
|
"use strict";
|
|
@@ -28407,6 +28459,105 @@ var init_server = __esm({
|
|
|
28407
28459
|
init_agent_resolver();
|
|
28408
28460
|
init_budget_policy();
|
|
28409
28461
|
init_surfaces();
|
|
28462
|
+
TYPE_REF_GRAMMAR = (what) => `${what}: a primitive/builtin or a defined type id (qualified across subsystems, e.g. "billing.Invoice" or "billing::Invoice"). Generics, arrays and UNIONS are all read, at any depth: "Invoice | null" (the commonest shape there is), "Invoice | undefined", "Invoice | Receipt", "Promise<Invoice | null>", "Map<string, Invoice | null>", "Invoice[] | null", "(Invoice | null)[]". Every identifier the string names must resolve \u2014 a union of two defined types means BOTH must exist. A union of string literals ("read" | "write") names no type and resolves to nothing.`;
|
|
28463
|
+
staleServerOutput = {
|
|
28464
|
+
staleServer: import_zod11.z.boolean().optional().describe(
|
|
28465
|
+
"True when the wairon build on disk changed after this server started \u2014 the structured twin of the text answer's STALE SERVER banner. Writes through a stale process can silently drop fields a newer schema introduced: restart the MCP session before editing further."
|
|
28466
|
+
)
|
|
28467
|
+
};
|
|
28468
|
+
SPEC_KINDS = ["system", "subsystem", "component", "interface", "implementation", "type"];
|
|
28469
|
+
STATUS_ORDER = ["draft", "design", "complete"];
|
|
28470
|
+
specWriteReceiptOutput = {
|
|
28471
|
+
kind: import_zod11.z.enum(SPEC_KINDS).describe("The spec kind written."),
|
|
28472
|
+
id: import_zod11.z.string().describe('The id the spec is stored under; "system" for the L0 singleton.'),
|
|
28473
|
+
name: import_zod11.z.string().describe("The spec's display name as written."),
|
|
28474
|
+
replacedExisting: import_zod11.z.boolean().describe(
|
|
28475
|
+
"True when a spec already held this id and the call re-authored it in place rather than adding one. The notices then say what was carried forward, removed or cleared by the restatement."
|
|
28476
|
+
),
|
|
28477
|
+
status: import_zod11.z.enum(STATUS_ORDER).optional().describe(
|
|
28478
|
+
"The lifecycle status written. Absent for a type, which carries none."
|
|
28479
|
+
),
|
|
28480
|
+
notices: import_zod11.z.array(import_zod11.z.string()).describe(
|
|
28481
|
+
"The notice lines the text answer lists, one per entry: what was carried forward, what a restatement removed, what an omission cleared, and every gate warning the write raised. Empty for a clean create."
|
|
28482
|
+
),
|
|
28483
|
+
scaffoldedProjectPath: import_zod11.z.string().optional().describe(
|
|
28484
|
+
"The child project directory a chained subsystem's create scaffolded; absent for every other write."
|
|
28485
|
+
),
|
|
28486
|
+
...staleServerOutput
|
|
28487
|
+
};
|
|
28488
|
+
specChangeOutput = {
|
|
28489
|
+
path: import_zod11.z.string().describe("The dotted path the change addresses, with names and indexes."),
|
|
28490
|
+
change: import_zod11.z.enum(["set", "added", "removed", "cleared"]).describe("What happened at that path."),
|
|
28491
|
+
before: import_zod11.z.string().optional().describe("The previous value, summarized; absent when there was none."),
|
|
28492
|
+
after: import_zod11.z.string().optional().describe("The new value, summarized; absent when there is none.")
|
|
28493
|
+
};
|
|
28494
|
+
specChangeReportOutput = {
|
|
28495
|
+
kind: import_zod11.z.enum(SPEC_KINDS).describe("The spec kind written."),
|
|
28496
|
+
id: import_zod11.z.string().describe("The stored spec's id."),
|
|
28497
|
+
written: import_zod11.z.boolean().describe("False when the merged spec equals what is stored: nothing reached disk."),
|
|
28498
|
+
dryRun: import_zod11.z.boolean().describe(
|
|
28499
|
+
"True when the caller asked what the delta WOULD do. `written` is false for a dry run exactly as it is for a delta that changed nothing, and only this field tells the two apart."
|
|
28500
|
+
),
|
|
28501
|
+
changes: import_zod11.z.array(import_zod11.z.object(specChangeOutput)).describe(
|
|
28502
|
+
"Every change the write made; empty exactly when `written` is false."
|
|
28503
|
+
),
|
|
28504
|
+
ineffective: import_zod11.z.array(import_zod11.z.string()).describe(
|
|
28505
|
+
"Every path the delta named that the write did not act on, each with why. Read it: a nested typo the permissive delta cannot refuse shows up here and nowhere else."
|
|
28506
|
+
),
|
|
28507
|
+
notices: import_zod11.z.array(import_zod11.z.string()).describe("Store placement notices, gate warnings and delta notices."),
|
|
28508
|
+
summary: import_zod11.z.string().describe("One line for people."),
|
|
28509
|
+
...staleServerOutput
|
|
28510
|
+
};
|
|
28511
|
+
validationIssueOutput = {
|
|
28512
|
+
severity: import_zod11.z.enum(["error", "warning"]).describe("The finding's severity after project overrides."),
|
|
28513
|
+
code: import_zod11.z.string().describe("The rule code, UPPER_SNAKE \u2014 the stable handle to filter and suppress by."),
|
|
28514
|
+
message: import_zod11.z.string().describe("What is wrong, named."),
|
|
28515
|
+
agentId: import_zod11.z.string().optional().describe("The agent the finding concerns, when it concerns one."),
|
|
28516
|
+
specId: import_zod11.z.string().optional().describe("The spec the finding concerns, when it concerns one."),
|
|
28517
|
+
draftContext: import_zod11.z.boolean().optional().describe(
|
|
28518
|
+
"True when the finding was raised against a draft/design spec \u2014 what the --ci gate waives."
|
|
28519
|
+
),
|
|
28520
|
+
surfaceResolved: import_zod11.z.boolean().optional().describe(
|
|
28521
|
+
"True when the finding was verified against a vendored surface snapshot, so it is a contract verdict rather than a resolution failure."
|
|
28522
|
+
)
|
|
28523
|
+
};
|
|
28524
|
+
validateTreeOutput = {
|
|
28525
|
+
valid: import_zod11.z.boolean().describe("False when the tree holds at least one error."),
|
|
28526
|
+
errors: import_zod11.z.array(import_zod11.z.object(validationIssueOutput)).describe("Every finding of severity error."),
|
|
28527
|
+
warnings: import_zod11.z.array(import_zod11.z.object(validationIssueOutput)).describe("Every finding of severity warning."),
|
|
28528
|
+
resolvedThrough: import_zod11.z.object({
|
|
28529
|
+
root: import_zod11.z.string().describe("The top root that was validated."),
|
|
28530
|
+
scope: import_zod11.z.string().describe("The mount chain the verdict was scoped to.")
|
|
28531
|
+
}).optional().describe(
|
|
28532
|
+
"Present when a chained subproject's verdict was resolved through its parent; absent when the tree was validated on its own."
|
|
28533
|
+
),
|
|
28534
|
+
...staleServerOutput
|
|
28535
|
+
};
|
|
28536
|
+
getSpecOutput = {
|
|
28537
|
+
kind: import_zod11.z.enum(SPEC_KINDS).describe("The kind of spec read."),
|
|
28538
|
+
id: import_zod11.z.string().describe("The id it was read by."),
|
|
28539
|
+
spec: import_zod11.z.record(import_zod11.z.unknown()).describe(
|
|
28540
|
+
"The stored spec, exactly as the text block renders it \u2014 minus the two derived markers below, which the text folds in and this answer keeps separate so nothing derived can be mistaken for stored."
|
|
28541
|
+
),
|
|
28542
|
+
partialResult: import_zod11.z.object({
|
|
28543
|
+
shown: import_zod11.z.array(import_zod11.z.string()).describe("The method names this answer carries."),
|
|
28544
|
+
omitted: import_zod11.z.number().describe("How many of the spec's methods are NOT in it."),
|
|
28545
|
+
warning: import_zod11.z.string().describe("Why it must never be re-authored from.")
|
|
28546
|
+
}).optional().describe(
|
|
28547
|
+
"Present only when `methods` filtered the read. A filtered spec is a partial one: sdd_define_interface and sdd_write_narrative REPLACE the method list, so re-authoring from it would delete every method left out."
|
|
28548
|
+
),
|
|
28549
|
+
variantGuidance: import_zod11.z.object({
|
|
28550
|
+
variant: import_zod11.z.string().describe("The variant id the component declares."),
|
|
28551
|
+
base: import_zod11.z.string().describe("The core stereotype it specializes."),
|
|
28552
|
+
guidance: import_zod11.z.string().describe("How to implement a component of this variant."),
|
|
28553
|
+
siblings: import_zod11.z.array(import_zod11.z.string()).describe("Other components of the same variant, to implement alike."),
|
|
28554
|
+
target: import_zod11.z.string().optional().describe("The target language the variant scopes itself to, if any."),
|
|
28555
|
+
profile: import_zod11.z.string().optional().describe("The architectural profile it scopes itself to, if any.")
|
|
28556
|
+
}).optional().describe(
|
|
28557
|
+
"Derived, read-only guidance for a variant-tagged component \u2014 resolved from the variant registry, not part of the spec. Never write it back."
|
|
28558
|
+
),
|
|
28559
|
+
...staleServerOutput
|
|
28560
|
+
};
|
|
28410
28561
|
SERVER_BUILD_STAMP = captureBuildStamp(__filename);
|
|
28411
28562
|
STALE_SERVER_WARNING = "\n\n\u26A0 STALE SERVER: the wairon build on disk changed after this MCP server started. Restart the MCP session (e.g. /mcp reconnect) before further spec edits \u2014 writes through a stale server can silently drop fields introduced by newer schemas.";
|
|
28412
28563
|
SPEC_WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -28429,7 +28580,6 @@ var init_server = __esm({
|
|
|
28429
28580
|
]);
|
|
28430
28581
|
listChangedEmitters = /* @__PURE__ */ new WeakMap();
|
|
28431
28582
|
STORE_MANAGED_FIELDS = /* @__PURE__ */ new Set(["status", "updatedAt"]);
|
|
28432
|
-
STATUS_ORDER = ["draft", "design", "complete"];
|
|
28433
28583
|
statusInput = import_zod11.z.enum(STATUS_ORDER).optional().describe(
|
|
28434
28584
|
"The spec's lifecycle status. Omitted means draft for a NEW spec and the status already stored for a re-authoring, so a restatement never reopens a frozen spec. State it to author straight at design or complete instead of promoting afterwards. A status that would LOWER the stored one is refused \u2014 reopening a spec for revision is sdd_update_spec's job, which sets the demotion deliberately."
|
|
28435
28585
|
);
|