@wairon/cli 5.1.1-dev.46 → 5.1.1-dev.48
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/README.md +6 -0
- package/dist/cli/index.js +24 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +26 -11
- package/dist/index.js.map +1 -1
- package/dist/templates/skills/sdd-delegate.md +32 -0
- package/dist/templates/skills/sdd-implement.md +57 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -212,6 +212,12 @@ validation), js-yaml, the MCP SDK, and Vitest. Bundled with tsup.
|
|
|
212
212
|
|
|
213
213
|
Actively developed. For bugs or questions, open an issue.
|
|
214
214
|
|
|
215
|
+
Working on this repo (or delegating work in it) — see
|
|
216
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for what this checkout does differently: line
|
|
217
|
+
endings, the gate commands and their baselines, and the stale-MCP-server tell.
|
|
218
|
+
The conventions that hold for *any* wairon project ship in the `sdd-implement`
|
|
219
|
+
and `sdd-delegate` skills.
|
|
220
|
+
|
|
215
221
|
## License
|
|
216
222
|
|
|
217
223
|
MIT
|
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.48";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -2671,7 +2671,10 @@ function importBindingOf(facts, name) {
|
|
|
2671
2671
|
return ownEntry(facts.importBindings, name);
|
|
2672
2672
|
}
|
|
2673
2673
|
function fieldTypesOf(facts, field) {
|
|
2674
|
-
return ownEntry(facts.fieldTypes, field) ??
|
|
2674
|
+
return ownEntry(facts.fieldTypes, field) ?? NO_DECLARED_TYPES;
|
|
2675
|
+
}
|
|
2676
|
+
function localTypesOf(facts, name) {
|
|
2677
|
+
return ownEntry(facts.localTypes, name) ?? NO_DECLARED_TYPES;
|
|
2675
2678
|
}
|
|
2676
2679
|
function typeBindingOf(facts, name) {
|
|
2677
2680
|
return ownEntry(facts.typeOnlyBindings, name) ?? ownEntry(facts.importBindings, name)?.from;
|
|
@@ -2700,12 +2703,12 @@ function resolveImport(fromFile, specifier, knownPaths) {
|
|
|
2700
2703
|
}
|
|
2701
2704
|
return void 0;
|
|
2702
2705
|
}
|
|
2703
|
-
var path6,
|
|
2706
|
+
var path6, NO_DECLARED_TYPES;
|
|
2704
2707
|
var init_code_model = __esm({
|
|
2705
2708
|
"src/models/code-model.ts"() {
|
|
2706
2709
|
"use strict";
|
|
2707
2710
|
path6 = __toESM(require("path"));
|
|
2708
|
-
|
|
2711
|
+
NO_DECLARED_TYPES = [];
|
|
2709
2712
|
}
|
|
2710
2713
|
});
|
|
2711
2714
|
|
|
@@ -9155,7 +9158,7 @@ function buildCodeIndex(model) {
|
|
|
9155
9158
|
};
|
|
9156
9159
|
const possibleOriginsOf = (site, from) => {
|
|
9157
9160
|
const proven = originOf(site, from);
|
|
9158
|
-
if (!site.field && !site.constructed) return proven;
|
|
9161
|
+
if (!site.field && !site.constructed && !site.via) return proven;
|
|
9159
9162
|
const resolved = scopeOf2(site, from);
|
|
9160
9163
|
if (!resolved) return proven;
|
|
9161
9164
|
const { path: scope, facts: f } = resolved;
|
|
@@ -9164,10 +9167,10 @@ function buildCodeIndex(model) {
|
|
|
9164
9167
|
const landings = specifier !== void 0 ? landingFrom(scope, specifier) : declarationsAt(scope).has(name) ? republishedFrom(scope) : NO_ORIGIN;
|
|
9165
9168
|
for (const candidate of landings) out.add(candidate);
|
|
9166
9169
|
};
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
}
|
|
9170
|
+
const widenThroughType = (typeName) => widenThrough(typeName, typeBindingOf(f, typeName));
|
|
9171
|
+
if (site.field) for (const typeName of fieldTypesOf(f, site.field)) widenThroughType(typeName);
|
|
9170
9172
|
if (site.constructed) widenThrough(site.constructed, importBindingOf(f, site.constructed)?.from);
|
|
9173
|
+
if (site.via) for (const typeName of localTypesOf(f, site.via)) widenThroughType(typeName);
|
|
9171
9174
|
return out;
|
|
9172
9175
|
};
|
|
9173
9176
|
const declarationsAt = (path70) => namesAt(declarations, pathKey(path70), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames]));
|
|
@@ -13652,7 +13655,7 @@ var init_call_conformance = __esm({
|
|
|
13652
13655
|
claimNoun = (implMethod) => implMethod.narrative.length ? "narrative call step(s)" : "declared call(s)";
|
|
13653
13656
|
callConformanceRule = {
|
|
13654
13657
|
name: "call-conformance",
|
|
13655
|
-
description: "Code\u2194spec Level 3: the CLAIMED call \u2194 realized call relation, judged both ways against the method's own source file (its sourcePath, else the implementation's), at exact analysis grade only. A method claims a call two ways and they face one check: a narrative `call` step, and an entry of the declared `calls` a narrative-less method reaches its collaborators through. They assert the same thing, and the step number is no part of the claim \u2014 this check never reads order, so it is only how a finding points at one. Forward: every claim must be realized by a call whose callee RESOLVES TO one of the target method's own source files \u2014 the target's contract name or a per-method `symbol` override, closed transitively over the named helpers the realized function calls, and resolved against every file the call CAN have reached: a `this.<field>.<method>()` receiver followed through the field's DECLARED TYPE, a `new Class(...).<method>()` receiver through the module its CLASS NAME came from. A matching call whose origin a pure model cannot resolve is reported apart as CALL_ORIGIN_UNRESOLVED, which NAMES the shape it could not follow and asks for nothing \u2014 a coverage hole in the reader, reported for the reason CONFORMANCE_DEGRADED is: a silently degraded gate is worse than a degraded one. A finding names a landing only from the PROVEN tier so that widening what a call reached can accept a claim but never accuse one, and a target that names no file of its own falls back to name membership. Converse: a call that resolves to a modelled method of ANOTHER component in the SAME file crosses a component boundary while looking local, so the method must claim it \u2014 in a step or in `calls` (UNDECLARED_COLOCATED_CALL) \u2014 judged on the proven tier alone, and a same-file private helper is no modelled method and is never reported. A method that claims nothing at all is judged in neither direction: what it leaves unsaid is UNUSED_*'s subject. Order, arguments and conditions stay unverified, dispatch steps (runtime-table routed) are no claim about a call site, a malformed declared reference is MALFORMED_DECLARED_CALL's finding and names no target here, the conformance dial (off) skips, and weaker analysis grades never guess.",
|
|
13658
|
+
description: "Code\u2194spec Level 3: the CLAIMED call \u2194 realized call relation, judged both ways against the method's own source file (its sourcePath, else the implementation's), at exact analysis grade only. A method claims a call two ways and they face one check: a narrative `call` step, and an entry of the declared `calls` a narrative-less method reaches its collaborators through. They assert the same thing, and the step number is no part of the claim \u2014 this check never reads order, so it is only how a finding points at one. Forward: every claim must be realized by a call whose callee RESOLVES TO one of the target method's own source files \u2014 the target's contract name or a per-method `symbol` override, closed transitively over the named helpers the realized function calls, and resolved against every file the call CAN have reached: a `this.<field>.<method>()` receiver followed through the field's DECLARED TYPE, a `new Class(...).<method>()` receiver through the module its CLASS NAME came from, and a plain `<name>.<method>()` receiver through the type the file ANNOTATES that name with \u2014 a parameter's, or an annotated variable's, which is how a module that wires its collaborators as closures writes every one of its calls. A matching call whose origin a pure model cannot resolve is reported apart as CALL_ORIGIN_UNRESOLVED, which NAMES the shape it could not follow and asks for nothing \u2014 a coverage hole in the reader, reported for the reason CONFORMANCE_DEGRADED is: a silently degraded gate is worse than a degraded one. A finding names a landing only from the PROVEN tier so that widening what a call reached can accept a claim but never accuse one, and a target that names no file of its own falls back to name membership. Converse: a call that resolves to a modelled method of ANOTHER component in the SAME file crosses a component boundary while looking local, so the method must claim it \u2014 in a step or in `calls` (UNDECLARED_COLOCATED_CALL) \u2014 judged on the proven tier alone, and a same-file private helper is no modelled method and is never reported. A method that claims nothing at all is judged in neither direction: what it leaves unsaid is UNUSED_*'s subject. Order, arguments and conditions stay unverified, dispatch steps (runtime-table routed) are no claim about a call site, a malformed declared reference is MALFORMED_DECLARED_CALL's finding and names no target here, the conformance dial (off) skips, and weaker analysis grades never guess.",
|
|
13656
13659
|
codes: [
|
|
13657
13660
|
{ code: "CALL_STEP_UNREALIZED", defaultSeverity: "warning", summary: "Narrative call step or declared call realized by no call that resolves to the target method's own source file \u2014 the call is absent, or it lands in another module", carryable: true },
|
|
13658
13661
|
{ code: "CALL_ORIGIN_UNRESOLVED", defaultSeverity: "warning", summary: "Narrative call step or declared call whose target name IS called, but only from call sites written in a shape this analysis cannot resolve to a file \u2014 the claim was not checked, and is neither proven realized nor accused", carryable: true },
|
|
@@ -13728,7 +13731,7 @@ var init_call_conformance = __esm({
|
|
|
13728
13731
|
ctx.addIssue(
|
|
13729
13732
|
"warning",
|
|
13730
13733
|
"CALL_ORIGIN_UNRESOLVED",
|
|
13731
|
-
`Method "${implMethod.name}" in implementation "${impl.id}": ${unresolved.length} ${claimNoun(implMethod)} ARE called by name inside the function "${fnSymbol}" in "${file}", but every site calling them is written in a shape this analysis cannot resolve to a file \u2014 ${unresolved.map(describeMiss).join("; ")}. What resolves is a name bound to a module of THIS project: a bare or namespaced call through such an import binding, a \`this.<field>\` receiver whose declared type names one, a \`new Class(\u2026)\` receiver whose class does. What does not: an import from a PACKAGE specifier, a receiver holding a value the module assembled, a receiver this model records no name for. This reports what was not checked, not what is wrong \u2014 the claim is neither proven realized nor accused of being missing, and no working call is asked to be rewritten to suit the reader.`,
|
|
13734
|
+
`Method "${implMethod.name}" in implementation "${impl.id}": ${unresolved.length} ${claimNoun(implMethod)} ARE called by name inside the function "${fnSymbol}" in "${file}", but every site calling them is written in a shape this analysis cannot resolve to a file \u2014 ${unresolved.map(describeMiss).join("; ")}. What resolves is a name bound to a module of THIS project: a bare or namespaced call through such an import binding, a \`this.<field>\` receiver whose declared type names one, a \`new Class(\u2026)\` receiver whose class does, and a receiver NAME the file annotates with a type that does. What does not: an import from a PACKAGE specifier, a receiver holding a value the module assembled, a receiver this model records no name for, and one the file annotates with nothing. This reports what was not checked, not what is wrong \u2014 the claim is neither proven realized nor accused of being missing, and no working call is asked to be rewritten to suit the reader.`,
|
|
13732
13735
|
impl.id,
|
|
13733
13736
|
entry.draftContext,
|
|
13734
13737
|
void 0,
|
|
@@ -15920,6 +15923,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
15920
15923
|
const importBindings = /* @__PURE__ */ new Map();
|
|
15921
15924
|
const typeOnlyBindings = /* @__PURE__ */ new Map();
|
|
15922
15925
|
const fieldTypes = /* @__PURE__ */ new Map();
|
|
15926
|
+
const localTypes = /* @__PURE__ */ new Map();
|
|
15923
15927
|
const mutableBindings = /* @__PURE__ */ new Set();
|
|
15924
15928
|
const receiverKey = (site) => site.via ?? (site.field ? `this.${site.field}` : site.constructed ? `new ${site.constructed}` : "");
|
|
15925
15929
|
const siteKey = (site) => `${site.member ? "m" : "b"}:${receiverKey(site)}:${site.name}`;
|
|
@@ -15947,6 +15951,13 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
15947
15951
|
named.add(typeName);
|
|
15948
15952
|
fieldTypes.set(field, named);
|
|
15949
15953
|
};
|
|
15954
|
+
const recordLocalType = (name, type) => {
|
|
15955
|
+
const typeName = typeReferenceName(type);
|
|
15956
|
+
if (!typeName || !ts.isIdentifier(name)) return;
|
|
15957
|
+
const named = localTypes.get(name.text) ?? /* @__PURE__ */ new Set();
|
|
15958
|
+
named.add(typeName);
|
|
15959
|
+
localTypes.set(name.text, named);
|
|
15960
|
+
};
|
|
15950
15961
|
const hasExportModifier = (node) => {
|
|
15951
15962
|
const mods = node.modifiers;
|
|
15952
15963
|
return !!mods?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
|
|
@@ -16014,6 +16025,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
16014
16025
|
else if (ts.isParameter(node) && node.parent && ts.isConstructorDeclaration(node.parent) && isParameterProperty(node)) {
|
|
16015
16026
|
recordFieldType(node.name, node.type);
|
|
16016
16027
|
}
|
|
16028
|
+
if (ts.isParameter(node) || ts.isVariableDeclaration(node)) recordLocalType(node.name, node.type);
|
|
16017
16029
|
if (ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node) || ts.isModuleDeclaration(node)) {
|
|
16018
16030
|
const name = node.name && ts.isIdentifier(node.name) ? node.name.text : void 0;
|
|
16019
16031
|
if (name) {
|
|
@@ -16090,7 +16102,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
16090
16102
|
};
|
|
16091
16103
|
visit(sf);
|
|
16092
16104
|
const reexportOnly = sf.statements.length > 0 && sf.statements.every((st) => ts.isExportDeclaration(st) && !!st.moduleSpecifier);
|
|
16093
|
-
return { declared, anchors, exported, imports, reexports, starExports, namedReexports, complexity, calls, importBindings, typeOnlyBindings, fieldTypes, mutableBindings, reexportOnly };
|
|
16105
|
+
return { declared, anchors, exported, imports, reexports, starExports, namedReexports, complexity, calls, importBindings, typeOnlyBindings, fieldTypes, localTypes, mutableBindings, reexportOnly };
|
|
16094
16106
|
}
|
|
16095
16107
|
function resolveRelativeModule(fromFile, specifier) {
|
|
16096
16108
|
if (!specifier.startsWith(".")) return null;
|
|
@@ -16271,6 +16283,7 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
|
|
|
16271
16283
|
importBindings: Object.fromEntries(facts.importBindings),
|
|
16272
16284
|
typeOnlyBindings: Object.fromEntries(facts.typeOnlyBindings),
|
|
16273
16285
|
fieldTypes: Object.fromEntries([...facts.fieldTypes].map(([k, v]) => [k, [...v]])),
|
|
16286
|
+
localTypes: Object.fromEntries([...facts.localTypes].map(([k, v]) => [k, [...v]])),
|
|
16274
16287
|
topLevelMutableBindings: [...facts.mutableBindings],
|
|
16275
16288
|
reexportOnly: facts.reexportOnly
|
|
16276
16289
|
};
|