@wairon/cli 5.1.1-dev.93 → 5.1.1-dev.95
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 +2838 -1729
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1053 -423
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3484,6 +3484,10 @@ __export(src_exports, {
|
|
|
3484
3484
|
RETIRED_STEREOTYPES: () => RETIRED_STEREOTYPES,
|
|
3485
3485
|
RegistrySchema: () => RegistrySchema,
|
|
3486
3486
|
RequirementItemSchema: () => RequirementItemSchema,
|
|
3487
|
+
ResolvedInterfaceSpecSchema: () => ResolvedInterfaceSpecSchema,
|
|
3488
|
+
ResolvedMethodSignatureSchema: () => ResolvedMethodSignatureSchema,
|
|
3489
|
+
ResolvedTypeMethodSchema: () => ResolvedTypeMethodSchema,
|
|
3490
|
+
ResolvedTypeSpecSchema: () => ResolvedTypeSpecSchema,
|
|
3487
3491
|
RulesConfigSchema: () => RulesConfigSchema,
|
|
3488
3492
|
SCAN_EXCLUDE_DIRS: () => SCAN_EXCLUDE_DIRS,
|
|
3489
3493
|
SDD_RULES: () => SDD_RULES,
|
|
@@ -3495,6 +3499,8 @@ __export(src_exports, {
|
|
|
3495
3499
|
SURFACE_AUDIENCES: () => SURFACE_AUDIENCES,
|
|
3496
3500
|
SpecIdSchema: () => SpecIdSchema,
|
|
3497
3501
|
SpecStatusSchema: () => SpecStatusSchema,
|
|
3502
|
+
StoredMethodSignatureSchema: () => StoredMethodSignatureSchema,
|
|
3503
|
+
StoredTypeMethodSchema: () => StoredTypeMethodSchema,
|
|
3498
3504
|
SubsystemSpecSchema: () => SubsystemSpecSchema,
|
|
3499
3505
|
SurfaceAudienceSchema: () => SurfaceAudienceSchema,
|
|
3500
3506
|
SurfaceContractEntrySchema: () => SurfaceContractEntrySchema,
|
|
@@ -3579,7 +3585,10 @@ __export(src_exports, {
|
|
|
3579
3585
|
dependencyCycles: () => dependencyCycles,
|
|
3580
3586
|
deregisterPackRef: () => deregisterPackRef,
|
|
3581
3587
|
deriveExecutionProfile: () => deriveExecutionProfile,
|
|
3588
|
+
deriveMethodSignature: () => deriveMethodSignature,
|
|
3589
|
+
deriveTypeSignature: () => deriveTypeSignature,
|
|
3582
3590
|
derivedDocPaths: () => derivedDocPaths,
|
|
3591
|
+
describeProject: () => describeProject,
|
|
3583
3592
|
detectDomainCandidates: () => detectDomainCandidates,
|
|
3584
3593
|
diagnoseProjectPacks: () => diagnoseProjectPacks,
|
|
3585
3594
|
diagramSetIndex: () => diagramSetIndex,
|
|
@@ -3737,6 +3746,7 @@ __export(src_exports, {
|
|
|
3737
3746
|
renameMethod: () => renameMethod,
|
|
3738
3747
|
renderDiagram: () => renderDiagram,
|
|
3739
3748
|
repairForeignStepFields: () => repairForeignStepFields,
|
|
3749
|
+
repairSignatures: () => repairSignatures,
|
|
3740
3750
|
repointExternal: () => repointExternal,
|
|
3741
3751
|
requiredPolicies: () => requiredPolicies,
|
|
3742
3752
|
resolveAgentTopology: () => resolveAgentTopology,
|
|
@@ -3748,6 +3758,7 @@ __export(src_exports, {
|
|
|
3748
3758
|
resolveImport: () => resolveImport,
|
|
3749
3759
|
resolveInstalledPack: () => resolveInstalledPack,
|
|
3750
3760
|
resolveProjectExports: () => resolveProjectExports,
|
|
3761
|
+
resolveSignatures: () => resolveTree,
|
|
3751
3762
|
resolveSubprojectForNamespace: () => resolveSubprojectForNamespace,
|
|
3752
3763
|
resolveSubsystemExports: () => resolveSubsystemExports,
|
|
3753
3764
|
resolveVariantGuidance: () => resolveVariantGuidance,
|
|
@@ -3769,11 +3780,15 @@ __export(src_exports, {
|
|
|
3769
3780
|
setProjectRoot: () => setProjectRoot,
|
|
3770
3781
|
setProjectType: () => setProjectType,
|
|
3771
3782
|
settledSpecPaths: () => settledSpecPaths,
|
|
3783
|
+
signatureFacts: () => signatureFacts,
|
|
3784
|
+
signatureTypeRefs: () => signatureTypeRefs,
|
|
3772
3785
|
specPathsInScope: () => specPathsInScope,
|
|
3773
3786
|
splitNamespace: () => splitNamespace,
|
|
3774
3787
|
stepConfigVerdict: () => stepConfigVerdict,
|
|
3775
3788
|
stepFieldsFor: () => stepFieldsFor,
|
|
3776
3789
|
stepGraph: () => stepGraph,
|
|
3790
|
+
storedMethodSignature: () => storedMethodSignature,
|
|
3791
|
+
storedTypeMethod: () => storedTypeMethod,
|
|
3777
3792
|
syncContextFiles: () => syncContextFiles,
|
|
3778
3793
|
technologyName: () => technologyName,
|
|
3779
3794
|
technologyTokens: () => technologyTokens,
|
|
@@ -4149,21 +4164,6 @@ var ExecutionBudgetSchema = import_zod.z.object({
|
|
|
4149
4164
|
allowNestedDelegation: import_zod.z.boolean(),
|
|
4150
4165
|
mcp: McpAccessSchema
|
|
4151
4166
|
});
|
|
4152
|
-
function summarize(budget, profile) {
|
|
4153
|
-
const lines = [
|
|
4154
|
-
`- **Work shape**: ${profile.breadth} breadth, ${profile.reasoningDepth} reasoning${profile.writes ? "" : ", read-only"}${profile.delegates ? ", delegating" : ""}`,
|
|
4155
|
-
`- **Why**: ${profile.rationale}`
|
|
4156
|
-
];
|
|
4157
|
-
if (budget.modelTier) lines.push(`- **Capability tier**: ${budget.modelTier}`);
|
|
4158
|
-
if (budget.effort) lines.push(`- **Effort**: ${budget.effort}`);
|
|
4159
|
-
if (budget.maxTurns !== void 0) {
|
|
4160
|
-
lines.push(`- **Turn ceiling**: ${budget.maxTurns} (a circuit breaker \u2014 hitting it should read as a scoping error, not a limit to work up to)`);
|
|
4161
|
-
}
|
|
4162
|
-
lines.push(`- **Tool grant**: ${budget.toolClass}`);
|
|
4163
|
-
lines.push(`- **May delegate further**: ${budget.allowNestedDelegation ? "yes" : "no"}`);
|
|
4164
|
-
lines.push(`- **MCP access**: ${budget.mcp}`);
|
|
4165
|
-
return lines;
|
|
4166
|
-
}
|
|
4167
4167
|
var BudgetTierSchema = import_zod.z.enum(["off", "free", "default", "trade", "aggressive"]);
|
|
4168
4168
|
var ExecutionConfigSchema = import_zod.z.object({
|
|
4169
4169
|
/**
|
|
@@ -4841,16 +4841,6 @@ var ProjectConfigSchema = import_zod3.z.object({
|
|
|
4841
4841
|
* Can also be set via WAIRON_TEMPLATES_DIR environment variable.
|
|
4842
4842
|
*/
|
|
4843
4843
|
globalTemplatesDir: import_zod3.z.string().optional(),
|
|
4844
|
-
/**
|
|
4845
|
-
* Tracks whether the wairon usage guide has been injected into each target's
|
|
4846
|
-
* AI tool configuration files so the tool knows how to use wairon.
|
|
4847
|
-
*/
|
|
4848
|
-
aiGuide: import_zod3.z.object({
|
|
4849
|
-
claudeGlobal: import_zod3.z.boolean().default(false),
|
|
4850
|
-
claudeLocal: import_zod3.z.boolean().default(false),
|
|
4851
|
-
geminiGlobal: import_zod3.z.boolean().default(false),
|
|
4852
|
-
geminiLocal: import_zod3.z.boolean().default(false)
|
|
4853
|
-
}).optional(),
|
|
4854
4844
|
/** Created by wairon at init time */
|
|
4855
4845
|
createdAt: import_zod3.z.string().datetime(),
|
|
4856
4846
|
updatedAt: import_zod3.z.string().datetime()
|
|
@@ -5714,6 +5704,9 @@ function registryOver(store, root) {
|
|
|
5714
5704
|
setProjectType(projectType) {
|
|
5715
5705
|
save({ ...current2(), projectType });
|
|
5716
5706
|
},
|
|
5707
|
+
describeProject(name, description) {
|
|
5708
|
+
save({ ...current2(), name, ...description !== void 0 ? { description } : {} });
|
|
5709
|
+
},
|
|
5717
5710
|
recordProfileSelection(selection) {
|
|
5718
5711
|
save({ ...current2(), profileSelection: selection });
|
|
5719
5712
|
},
|
|
@@ -6079,6 +6072,9 @@ function projectConfigRepositoryOver(adapter, rootDir) {
|
|
|
6079
6072
|
setProjectType(projectType) {
|
|
6080
6073
|
registry.setProjectType(projectType);
|
|
6081
6074
|
},
|
|
6075
|
+
describeProject(name, description) {
|
|
6076
|
+
registry.describeProject(name, description);
|
|
6077
|
+
},
|
|
6082
6078
|
recordProfileSelection(selection) {
|
|
6083
6079
|
registry.recordProfileSelection(selection);
|
|
6084
6080
|
},
|
|
@@ -6141,7 +6137,10 @@ function projectConfigRepositoryOver(adapter, rootDir) {
|
|
|
6141
6137
|
function projectConfigRepositoryAt(rootDir) {
|
|
6142
6138
|
return projectConfigRepositoryOver(projectConfigFsAdapterAt(rootDir), rootDir);
|
|
6143
6139
|
}
|
|
6144
|
-
var bound = () =>
|
|
6140
|
+
var bound = () => {
|
|
6141
|
+
const rootDir = getProjectRoot();
|
|
6142
|
+
return projectConfigRepositoryOver(projectConfigFsAdapterAt(rootDir), rootDir);
|
|
6143
|
+
};
|
|
6145
6144
|
var projectConfigRepository = {
|
|
6146
6145
|
load() {
|
|
6147
6146
|
return bound().load();
|
|
@@ -6167,6 +6166,9 @@ var projectConfigRepository = {
|
|
|
6167
6166
|
setProjectType(projectType) {
|
|
6168
6167
|
bound().setProjectType(projectType);
|
|
6169
6168
|
},
|
|
6169
|
+
describeProject(name, description) {
|
|
6170
|
+
bound().describeProject(name, description);
|
|
6171
|
+
},
|
|
6170
6172
|
recordProfileSelection(selection) {
|
|
6171
6173
|
bound().recordProfileSelection(selection);
|
|
6172
6174
|
},
|
|
@@ -6434,19 +6436,19 @@ function withSortedMaps(record) {
|
|
|
6434
6436
|
var fs5 = __toESM(require("fs"));
|
|
6435
6437
|
var path7 = __toESM(require("path"));
|
|
6436
6438
|
var SPEC_FILE_EXTENSION = ".yaml";
|
|
6437
|
-
function readSpecFile(
|
|
6438
|
-
return readYamlFile(
|
|
6439
|
+
function readSpecFile(specPath) {
|
|
6440
|
+
return readYamlFile(specPath);
|
|
6439
6441
|
}
|
|
6440
|
-
function writeSpecFile(
|
|
6441
|
-
writeYamlFile(
|
|
6442
|
+
function writeSpecFile(specPath, document) {
|
|
6443
|
+
writeYamlFile(specPath, document);
|
|
6442
6444
|
}
|
|
6443
6445
|
function listSpecFiles(specsDir) {
|
|
6444
6446
|
return listFilesRecursive(specsDir, SPEC_FILE_EXTENSION);
|
|
6445
6447
|
}
|
|
6446
|
-
function removeSpecFile(
|
|
6447
|
-
if (!fs5.existsSync(
|
|
6448
|
-
fs5.unlinkSync(
|
|
6449
|
-
pruneEmptyDirs(path7.dirname(
|
|
6448
|
+
function removeSpecFile(specPath, specsRoot) {
|
|
6449
|
+
if (!fs5.existsSync(specPath)) return false;
|
|
6450
|
+
fs5.unlinkSync(specPath);
|
|
6451
|
+
pruneEmptyDirs(path7.dirname(specPath), path7.resolve(specsRoot));
|
|
6450
6452
|
return true;
|
|
6451
6453
|
}
|
|
6452
6454
|
function pruneEmptyDirs(dir, specsRoot) {
|
|
@@ -7106,13 +7108,21 @@ var FindingDeclarationSchema = import_zod8.z.object({
|
|
|
7106
7108
|
var MethodSignatureSchema = import_zod8.z.object({
|
|
7107
7109
|
name: import_zod8.z.string().regex(/^[a-zA-Z0-9_]+$/, "Method name must be alphanumeric"),
|
|
7108
7110
|
description: import_zod8.z.string(),
|
|
7109
|
-
signature: import_zod8.z.string(),
|
|
7111
|
+
signature: import_zod8.z.string().optional(),
|
|
7110
7112
|
// e.g. "save(key: string, data: Buffer): Promise<void>"
|
|
7111
7113
|
// e.g. "Promise<void>", or a union: "Invoice | null" — the commonest shape in
|
|
7112
7114
|
// any real tree. See the grammar on src/models/type-references.ts.
|
|
7113
|
-
returns: import_zod8.z.string(),
|
|
7115
|
+
returns: import_zod8.z.string().optional(),
|
|
7114
7116
|
/** Structured parameters (authoritative for type checking when present). */
|
|
7115
7117
|
params: import_zod8.z.array(MethodParamSchema).optional(),
|
|
7118
|
+
/**
|
|
7119
|
+
* Where this method takes its params and returns from instead of stating
|
|
7120
|
+
* them: a signature type (`billing.change_listener`, `alias::name`), or a
|
|
7121
|
+
* contract method `component.method` its component reaches along a
|
|
7122
|
+
* dependsOn/owns edge. Resolved both ways by the loader (signature_resolver);
|
|
7123
|
+
* the writer stores a sourced method with only its source.
|
|
7124
|
+
*/
|
|
7125
|
+
signatureFrom: import_zod8.z.string().min(1).optional(),
|
|
7116
7126
|
/** Concrete wire binding for this method when its component is a Portal (set via sdd_set_endpoints). */
|
|
7117
7127
|
endpoint: EndpointSchema.optional(),
|
|
7118
7128
|
/**
|
|
@@ -7165,6 +7175,54 @@ var MethodSignatureSchema = import_zod8.z.object({
|
|
|
7165
7175
|
/** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
|
|
7166
7176
|
ext: ExtDataSchema.optional()
|
|
7167
7177
|
});
|
|
7178
|
+
function requireStoredSignature(method, ctx) {
|
|
7179
|
+
if (method.signatureFrom !== void 0) return;
|
|
7180
|
+
if (method.returns === void 0) {
|
|
7181
|
+
ctx.addIssue({ code: import_zod8.z.ZodIssueCode.custom, path: ["returns"], message: "Required: a method without a signatureFrom states its returns" });
|
|
7182
|
+
}
|
|
7183
|
+
if (method.params === void 0 && method.signature === void 0) {
|
|
7184
|
+
ctx.addIssue({ code: import_zod8.z.ZodIssueCode.custom, path: ["signature"], message: "Required: a method without params or a signatureFrom states a prose signature" });
|
|
7185
|
+
}
|
|
7186
|
+
}
|
|
7187
|
+
var StoredMethodSignatureSchema = MethodSignatureSchema.superRefine(requireStoredSignature);
|
|
7188
|
+
var ResolvedMethodSignatureSchema = MethodSignatureSchema.extend({
|
|
7189
|
+
signature: import_zod8.z.string(),
|
|
7190
|
+
returns: import_zod8.z.string()
|
|
7191
|
+
});
|
|
7192
|
+
function paramText(p) {
|
|
7193
|
+
return `${p.name}${p.optional ? "?" : ""}: ${p.type}`;
|
|
7194
|
+
}
|
|
7195
|
+
function leadingGenericList(name, stored) {
|
|
7196
|
+
if (!stored) return "";
|
|
7197
|
+
const text3 = stored.trimStart();
|
|
7198
|
+
if (!text3.startsWith(name)) return "";
|
|
7199
|
+
let i = name.length;
|
|
7200
|
+
while (text3[i] === " ") i++;
|
|
7201
|
+
if (text3[i] !== "<") return "";
|
|
7202
|
+
let depth = 0;
|
|
7203
|
+
for (let j = i; j < text3.length; j++) {
|
|
7204
|
+
if (text3[j] === "<") depth++;
|
|
7205
|
+
else if (text3[j] === ">") depth--;
|
|
7206
|
+
if (depth === 0) {
|
|
7207
|
+
const rest = text3.slice(j + 1).trimStart();
|
|
7208
|
+
return rest.startsWith("(") ? text3.slice(i, j + 1) : "";
|
|
7209
|
+
}
|
|
7210
|
+
}
|
|
7211
|
+
return "";
|
|
7212
|
+
}
|
|
7213
|
+
function deriveMethodSignature(method) {
|
|
7214
|
+
if (!method.params) return void 0;
|
|
7215
|
+
const generics = leadingGenericList(method.name, method.signature);
|
|
7216
|
+
return `${method.name}${generics}(${method.params.map(paramText).join(", ")}): ${method.returns ?? "unknown"}`;
|
|
7217
|
+
}
|
|
7218
|
+
function storedMethodSignature(method) {
|
|
7219
|
+
if (method.signatureFrom !== void 0) {
|
|
7220
|
+
const { params: _params, returns: _returns, signature: _signature, ...rest } = method;
|
|
7221
|
+
return rest;
|
|
7222
|
+
}
|
|
7223
|
+
const derived = deriveMethodSignature(method);
|
|
7224
|
+
return derived === void 0 ? method : { ...method, signature: derived };
|
|
7225
|
+
}
|
|
7168
7226
|
var INTENT_FLOOR_MIN_CHARS = 40;
|
|
7169
7227
|
function passesIntentFloor(text3, methodName) {
|
|
7170
7228
|
if (!text3) return false;
|
|
@@ -7180,7 +7238,7 @@ var InterfaceSpecSchema = import_zod8.z.object({
|
|
|
7180
7238
|
description: import_zod8.z.string(),
|
|
7181
7239
|
component: import_zod8.z.string(),
|
|
7182
7240
|
// References L2 Component id
|
|
7183
|
-
methods: import_zod8.z.array(
|
|
7241
|
+
methods: import_zod8.z.array(StoredMethodSignatureSchema).default([]),
|
|
7184
7242
|
/** Per-spec lint suppressions (see LintConfigSchema). */
|
|
7185
7243
|
lint: LintConfigSchema.optional(),
|
|
7186
7244
|
/** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
|
|
@@ -7189,6 +7247,9 @@ var InterfaceSpecSchema = import_zod8.z.object({
|
|
|
7189
7247
|
createdAt: import_zod8.z.string().datetime(),
|
|
7190
7248
|
updatedAt: import_zod8.z.string().datetime()
|
|
7191
7249
|
});
|
|
7250
|
+
var ResolvedInterfaceSpecSchema = InterfaceSpecSchema.extend({
|
|
7251
|
+
methods: import_zod8.z.array(ResolvedMethodSignatureSchema).default([])
|
|
7252
|
+
});
|
|
7192
7253
|
var NarrativeStepTypeSchema = import_zod8.z.enum([
|
|
7193
7254
|
"local",
|
|
7194
7255
|
// in-component work
|
|
@@ -7526,7 +7587,7 @@ function implementationSourceFiles(impl) {
|
|
|
7526
7587
|
for (const method of impl.methods ?? []) add2(method.sourcePath);
|
|
7527
7588
|
return files;
|
|
7528
7589
|
}
|
|
7529
|
-
var TypeKindSchema = import_zod8.z.enum(["entity", "value-object"]);
|
|
7590
|
+
var TypeKindSchema = import_zod8.z.enum(["entity", "value-object", "signature"]);
|
|
7530
7591
|
var TypeFieldSchema = import_zod8.z.object({
|
|
7531
7592
|
name: import_zod8.z.string(),
|
|
7532
7593
|
// A primitive, or another type id (qualified across subsystems, e.g.
|
|
@@ -7550,7 +7611,9 @@ var TypeFieldSchema = import_zod8.z.object({
|
|
|
7550
7611
|
});
|
|
7551
7612
|
var TypeMethodSchema = import_zod8.z.object({
|
|
7552
7613
|
name: import_zod8.z.string(),
|
|
7553
|
-
signature: import_zod8.z.string(),
|
|
7614
|
+
signature: import_zod8.z.string().optional(),
|
|
7615
|
+
/** Structured parameters in the contract method's param shape — authoritative for type checking when present. */
|
|
7616
|
+
params: import_zod8.z.array(MethodParamSchema).optional(),
|
|
7554
7617
|
returns: import_zod8.z.string(),
|
|
7555
7618
|
description: import_zod8.z.string().optional(),
|
|
7556
7619
|
/**
|
|
@@ -7569,6 +7632,14 @@ var TypeMethodSchema = import_zod8.z.object({
|
|
|
7569
7632
|
*/
|
|
7570
7633
|
symbol: import_zod8.z.string().optional()
|
|
7571
7634
|
});
|
|
7635
|
+
var ResolvedTypeMethodSchema = TypeMethodSchema.extend({
|
|
7636
|
+
signature: import_zod8.z.string()
|
|
7637
|
+
});
|
|
7638
|
+
var StoredTypeMethodSchema = TypeMethodSchema.superRefine((method, ctx) => {
|
|
7639
|
+
if (method.params === void 0 && method.signature === void 0) {
|
|
7640
|
+
ctx.addIssue({ code: import_zod8.z.ZodIssueCode.custom, path: ["signature"], message: "Required: a type method without params states a prose signature" });
|
|
7641
|
+
}
|
|
7642
|
+
});
|
|
7572
7643
|
var InvariantSchema = import_zod8.z.object({
|
|
7573
7644
|
/** Stable invariant id, unique within the entity (referenced as "<type-id>.<invariant-id>"). */
|
|
7574
7645
|
id: SpecIdSchema,
|
|
@@ -7577,7 +7648,7 @@ var InvariantSchema = import_zod8.z.object({
|
|
|
7577
7648
|
});
|
|
7578
7649
|
var TypeSpecSchema = import_zod8.z.object({
|
|
7579
7650
|
kind: TypeKindSchema,
|
|
7580
|
-
// discriminator — entity | value-object
|
|
7651
|
+
// discriminator — entity | value-object | signature
|
|
7581
7652
|
id: SpecIdSchema,
|
|
7582
7653
|
name: import_zod8.z.string(),
|
|
7583
7654
|
description: import_zod8.z.string().optional(),
|
|
@@ -7587,7 +7658,7 @@ var TypeSpecSchema = import_zod8.z.object({
|
|
|
7587
7658
|
group: import_zod8.z.string().optional(),
|
|
7588
7659
|
fields: import_zod8.z.array(TypeFieldSchema).default([]),
|
|
7589
7660
|
/** Pure intrinsic behaviour only — anything needing a collaborator belongs on a component. */
|
|
7590
|
-
methods: import_zod8.z.array(
|
|
7661
|
+
methods: import_zod8.z.array(StoredTypeMethodSchema).default([]),
|
|
7591
7662
|
/**
|
|
7592
7663
|
* Linked Component ID if this system entity is implemented as a class Component
|
|
7593
7664
|
* (e.g., a Store or Registry that owns this entity's lifecycle and methods).
|
|
@@ -7633,9 +7704,27 @@ var TypeSpecSchema = import_zod8.z.object({
|
|
|
7633
7704
|
lint: LintConfigSchema.optional(),
|
|
7634
7705
|
/** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
|
|
7635
7706
|
ext: ExtDataSchema.optional(),
|
|
7707
|
+
/**
|
|
7708
|
+
* A signature's parameters, in the contract method's param shape; only on
|
|
7709
|
+
* kind signature (SIGNATURE_TYPE_MEMBERS otherwise).
|
|
7710
|
+
*/
|
|
7711
|
+
params: import_zod8.z.array(MethodParamSchema).optional(),
|
|
7712
|
+
/** A signature's one output type; required on kind signature and only there (SIGNATURE_TYPE_MEMBERS). */
|
|
7713
|
+
returns: import_zod8.z.string().optional(),
|
|
7636
7714
|
createdAt: import_zod8.z.string().datetime(),
|
|
7637
7715
|
updatedAt: import_zod8.z.string().datetime()
|
|
7638
7716
|
});
|
|
7717
|
+
var ResolvedTypeSpecSchema = TypeSpecSchema.extend({
|
|
7718
|
+
methods: import_zod8.z.array(ResolvedTypeMethodSchema).default([])
|
|
7719
|
+
});
|
|
7720
|
+
function deriveTypeSignature(type) {
|
|
7721
|
+
if (type.kind !== "signature") return void 0;
|
|
7722
|
+
return `(${(type.params ?? []).map(paramText).join(", ")}): ${type.returns ?? "unknown"}`;
|
|
7723
|
+
}
|
|
7724
|
+
function storedTypeMethod(method) {
|
|
7725
|
+
const derived = deriveMethodSignature(method);
|
|
7726
|
+
return derived === void 0 ? method : { ...method, signature: derived };
|
|
7727
|
+
}
|
|
7639
7728
|
function typeSourceFiles(type) {
|
|
7640
7729
|
const files = [];
|
|
7641
7730
|
const add2 = (file) => {
|
|
@@ -7655,7 +7744,16 @@ var SurfaceTypeDefSchema = import_zod8.z.object({
|
|
|
7655
7744
|
type: import_zod8.z.string(),
|
|
7656
7745
|
description: import_zod8.z.string().optional(),
|
|
7657
7746
|
optional: import_zod8.z.boolean().optional()
|
|
7658
|
-
})).default([])
|
|
7747
|
+
})).default([]),
|
|
7748
|
+
/** A signature's parameters (name, type, optional, description) in declared order; only on kind signature. */
|
|
7749
|
+
params: import_zod8.z.array(import_zod8.z.object({
|
|
7750
|
+
name: import_zod8.z.string(),
|
|
7751
|
+
type: import_zod8.z.string(),
|
|
7752
|
+
description: import_zod8.z.string().optional(),
|
|
7753
|
+
optional: import_zod8.z.boolean().optional()
|
|
7754
|
+
})).optional(),
|
|
7755
|
+
/** A signature's one output type; only on kind signature. */
|
|
7756
|
+
returns: import_zod8.z.string().optional()
|
|
7659
7757
|
});
|
|
7660
7758
|
var SurfaceTypeExportSchema = import_zod8.z.object({
|
|
7661
7759
|
/** The type's public name in the producer's export table. */
|
|
@@ -7674,8 +7772,8 @@ var SurfaceContractEntrySchema = import_zod8.z.object({
|
|
|
7674
7772
|
type: import_zod8.z.string().default("Custom"),
|
|
7675
7773
|
/** Local name of the backing Portal in the producing project. */
|
|
7676
7774
|
component: import_zod8.z.string(),
|
|
7677
|
-
/** Full contract methods (params, returns, guarantees, effect, endpoint). */
|
|
7678
|
-
methods: import_zod8.z.array(
|
|
7775
|
+
/** Full contract methods (params, returns, guarantees, effect, endpoint), resolved: a snapshot names no producer-internal source. */
|
|
7776
|
+
methods: import_zod8.z.array(ResolvedMethodSignatureSchema).default([]),
|
|
7679
7777
|
/** The backing portal's capability dispatch table, when generic-dispatch. */
|
|
7680
7778
|
dispatch: import_zod8.z.array(DispatchBindingSchema).optional(),
|
|
7681
7779
|
details: import_zod8.z.string().default(""),
|
|
@@ -7925,13 +8023,18 @@ function methodTypeRefs(m) {
|
|
|
7925
8023
|
for (const p of m.params) {
|
|
7926
8024
|
refs.push(...extractTypeIdentifiers(p.type));
|
|
7927
8025
|
}
|
|
7928
|
-
refs.push(...extractTypeIdentifiers(m.returns));
|
|
8026
|
+
refs.push(...extractTypeIdentifiers(m.returns ?? ""));
|
|
7929
8027
|
return Array.from(new Set(refs));
|
|
7930
8028
|
}
|
|
7931
|
-
return extractTypesFromSignature(m.signature, m.returns);
|
|
8029
|
+
return extractTypesFromSignature(m.signature ?? "", m.returns ?? "");
|
|
8030
|
+
}
|
|
8031
|
+
function signatureTypeRefs(type) {
|
|
8032
|
+
if (type.kind !== "signature") return [];
|
|
8033
|
+
const refs = [...(type.params ?? []).flatMap((p) => extractTypeIdentifiers(p.type)), ...extractTypeIdentifiers(type.returns ?? "")];
|
|
8034
|
+
return Array.from(new Set(refs));
|
|
7932
8035
|
}
|
|
7933
8036
|
function methodGenericParameters(method) {
|
|
7934
|
-
return extractGenericTypeVariables(method.signature);
|
|
8037
|
+
return extractGenericTypeVariables(method.signature ?? "");
|
|
7935
8038
|
}
|
|
7936
8039
|
function normalizePart(part) {
|
|
7937
8040
|
return part.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -8318,9 +8421,21 @@ function typeShape(snapshot, def) {
|
|
|
8318
8421
|
return {
|
|
8319
8422
|
id: def.id,
|
|
8320
8423
|
kind: def.kind,
|
|
8321
|
-
fields: sortedBy(def.fields, (f) => f.name).map((f) => ({ name: f.name, type: canonicalTypeRef(snapshot, f.type), optional: f.optional === true }))
|
|
8424
|
+
fields: sortedBy(def.fields, (f) => f.name).map((f) => ({ name: f.name, type: canonicalTypeRef(snapshot, f.type), optional: f.optional === true })),
|
|
8425
|
+
// A signature's shape: its params' types and optionality in order (never their names, as a method's), and its returns.
|
|
8426
|
+
...def.kind === "signature" ? {
|
|
8427
|
+
params: (def.params ?? []).map((p) => ({ type: canonicalTypeRef(snapshot, p.type), optional: p.optional === true })),
|
|
8428
|
+
returns: canonicalTypeRef(snapshot, def.returns ?? "unknown")
|
|
8429
|
+
} : {}
|
|
8322
8430
|
};
|
|
8323
8431
|
}
|
|
8432
|
+
function typeDefExprs(def) {
|
|
8433
|
+
return [
|
|
8434
|
+
...def.fields.map((f) => f.type),
|
|
8435
|
+
...(def.params ?? []).map((p) => p.type),
|
|
8436
|
+
...def.returns !== void 0 ? [def.returns] : []
|
|
8437
|
+
];
|
|
8438
|
+
}
|
|
8324
8439
|
function closureShapes(snapshot, exprs) {
|
|
8325
8440
|
const byId = new Map(snapshot.types.map((def) => [def.id, def]));
|
|
8326
8441
|
const seen = /* @__PURE__ */ new Map();
|
|
@@ -8329,7 +8444,7 @@ function closureShapes(snapshot, exprs) {
|
|
|
8329
8444
|
const def = byId.get(queue.shift());
|
|
8330
8445
|
if (!def || seen.has(def.id)) continue;
|
|
8331
8446
|
seen.set(def.id, def);
|
|
8332
|
-
for (const
|
|
8447
|
+
for (const expr of typeDefExprs(def)) queue.push(...extractTypeIdentifiers(canonicalTypeRef(snapshot, expr)));
|
|
8333
8448
|
}
|
|
8334
8449
|
return [...seen.keys()].sort().map((id) => typeShape(snapshot, seen.get(id)));
|
|
8335
8450
|
}
|
|
@@ -9241,6 +9356,7 @@ function buildCanvasModel(issues = [], relations) {
|
|
|
9241
9356
|
signature: m.signature,
|
|
9242
9357
|
returns: m.returns,
|
|
9243
9358
|
...m.params && m.params.length ? { params: m.params } : {},
|
|
9359
|
+
...m.signatureFrom ? { signatureFrom: m.signatureFrom } : {},
|
|
9244
9360
|
...m.endpoint ? { endpoint: m.endpoint } : {},
|
|
9245
9361
|
...m.guarantees && m.guarantees.length ? { guarantees: m.guarantees } : {}
|
|
9246
9362
|
}))
|
|
@@ -9306,6 +9422,7 @@ function buildCanvasModel(issues = [], relations) {
|
|
|
9306
9422
|
...f.references ? { references: f.references } : {}
|
|
9307
9423
|
})),
|
|
9308
9424
|
methods: t.methods.map((m) => ({ name: m.name, signature: m.signature, returns: m.returns, ...m.description ? { description: m.description } : {} })),
|
|
9425
|
+
...t.kind === "signature" ? { signature: deriveTypeSignature(t) } : {},
|
|
9309
9426
|
usedBy: usedByFor(t),
|
|
9310
9427
|
...t.componentClass ? { componentClass: t.componentClass } : {},
|
|
9311
9428
|
...t.database ? { database: t.database } : {},
|
|
@@ -11040,15 +11157,17 @@ var MODEL = __MODEL_JSON__;
|
|
|
11040
11157
|
function tableShape(t) {
|
|
11041
11158
|
var fields = visibleFields(t);
|
|
11042
11159
|
var meths = det === 'full' ? t.methods : [];
|
|
11160
|
+
// A signature type is drawn with its derived text in place of a field list.
|
|
11161
|
+
var sig = t.signature && det !== 'names' ? t.signature : '';
|
|
11043
11162
|
var head = t.name + ' \\u00AB' + t.kind + '\\u00BB';
|
|
11044
|
-
var rows = fields.map(function (f) { return rowText(t, f); })
|
|
11163
|
+
var rows = (sig ? [sig] : []).concat(fields.map(function (f) { return rowText(t, f); }))
|
|
11045
11164
|
.concat(meths.map(function (m) { return '\\u0192 ' + m.name + '(): ' + m.returns; }));
|
|
11046
11165
|
var longest = head.length + 4;
|
|
11047
11166
|
rows.forEach(function (r) { if (r.length > longest) longest = r.length; });
|
|
11048
11167
|
var plain = rows.length === 0;
|
|
11049
11168
|
var pw = Math.max(170, head.length * 6.8 + 26);
|
|
11050
11169
|
var W = Math.max(210, Math.min(400, longest * 6.6 + 30));
|
|
11051
|
-
return { fields: fields, meths: meths, head: head, plain: plain, w: plain ? pw : W, h: plain ? 40 : TH_H + fields.length * ROW_H + meths.length * ROW_H };
|
|
11170
|
+
return { fields: fields, meths: meths, sig: sig, head: head, plain: plain, w: plain ? pw : W, h: plain ? 40 : TH_H + (sig ? ROW_H : 0) + fields.length * ROW_H + meths.length * ROW_H };
|
|
11052
11171
|
}
|
|
11053
11172
|
|
|
11054
11173
|
// Emit one type table with its top-left at (ax, ay); returns its size.
|
|
@@ -11072,6 +11191,13 @@ var MODEL = __MODEL_JSON__;
|
|
|
11072
11191
|
position: { x: ax + sh.w / 2, y: ay + TH_H / 2 }, classes: 'typeHead ' + kindCls + (dim ? ' dimmed' : ''), grabbable: false,
|
|
11073
11192
|
});
|
|
11074
11193
|
var ry = ay + TH_H;
|
|
11194
|
+
if (sh.sig) {
|
|
11195
|
+
eles.push({
|
|
11196
|
+
data: { id: 'TS~' + t.id, parent: 'T~' + t.id, label: sh.sig, w: sh.w, h: ROW_H, tw: sh.w - 14 },
|
|
11197
|
+
position: { x: ax + sh.w / 2, y: ry + ROW_H / 2 }, classes: 'typeRow methRow' + (dim ? ' dimmed' : ''), grabbable: false,
|
|
11198
|
+
});
|
|
11199
|
+
ry += ROW_H;
|
|
11200
|
+
}
|
|
11075
11201
|
sh.fields.forEach(function (f) {
|
|
11076
11202
|
var rid = 'TF~' + t.id + '~' + f.name;
|
|
11077
11203
|
rowIds[rid] = 1;
|
|
@@ -13158,7 +13284,7 @@ var MODEL = __MODEL_JSON__;
|
|
|
13158
13284
|
var mi = methodInfo(top.comp, top.method);
|
|
13159
13285
|
var parts = ['<div class="fstep" style="opacity:.7">No step-by-step narrative \\u2014 showing intent / contract:</div>'];
|
|
13160
13286
|
if (mi) {
|
|
13161
|
-
parts.push('<div class="fstep"><code>' + escText(mi.m.signature) + '</code
|
|
13287
|
+
parts.push('<div class="fstep"><code>' + escText(mi.m.signature) + '</code>' + (mi.m.signatureFrom ? ' from <code>' + escText(mi.m.signatureFrom) + '</code>' : '') + '</div>');
|
|
13162
13288
|
parts.push('<div class="fstep">' + escText(mi.m.description) + (mi.m.returns ? ' \\u2014 returns ' + escText(mi.m.returns) : '') + '</div>');
|
|
13163
13289
|
}
|
|
13164
13290
|
if (intent) parts.push('<div class="fstep" style="font-style:italic">' + escText(intent) + '</div>');
|
|
@@ -13499,6 +13625,7 @@ var MODEL = __MODEL_JSON__;
|
|
|
13499
13625
|
: '<span class="chip" style="opacity:.6">no narrative</span>')
|
|
13500
13626
|
+ '</div>'
|
|
13501
13627
|
+ '<code>' + esc(m.signature) + '</code>'
|
|
13628
|
+
+ (m.signatureFrom ? '<div class="mdesc">signature from <code style="display:inline">' + esc(m.signatureFrom) + '</code></div>' : '')
|
|
13502
13629
|
+ '<div class="mdesc">' + esc(m.description) + ' \\u2014 returns ' + typeRefHtml(m.returns) + '</div>'
|
|
13503
13630
|
+ (mIntent && !hasNarr ? '<div class="mdesc" style="font-style:italic">' + esc(mIntent) + '</div>' : '')
|
|
13504
13631
|
+ (m.params ? '<div class="mdesc">params: ' + m.params.map(function (p) { return esc(p.name) + ': ' + typeRefHtml(p.type); }).join(', ') + '</div>' : '')
|
|
@@ -13602,7 +13729,11 @@ var MODEL = __MODEL_JSON__;
|
|
|
13602
13729
|
+ '</div>';
|
|
13603
13730
|
}).join('')
|
|
13604
13731
|
: '<span class="desc">no fields</span>';
|
|
13605
|
-
|
|
13732
|
+
if (ty.signature) {
|
|
13733
|
+
body += section('Signature', 1, '<div class="method"><code>' + esc(ty.signature) + '</code></div>', true);
|
|
13734
|
+
} else {
|
|
13735
|
+
body += section('Fields', ty.fields.length, fieldsInner, true);
|
|
13736
|
+
}
|
|
13606
13737
|
if (ty.usedBy && ty.usedBy.length) {
|
|
13607
13738
|
body += section('Used by methods', ty.usedBy.length, ty.usedBy.map(function (u) {
|
|
13608
13739
|
return chip(u.component + '.' + u.method + '()', 'component', u.component);
|
|
@@ -13941,21 +14072,30 @@ function computeTypeClosure(entries, types, exported = []) {
|
|
|
13941
14072
|
for (const field of spec.fields) {
|
|
13942
14073
|
for (const ref of extractTypeIdentifiers(field.type)) enqueueRef(ref);
|
|
13943
14074
|
}
|
|
14075
|
+
for (const param of spec.params ?? []) {
|
|
14076
|
+
for (const ref of extractTypeIdentifiers(param.type)) enqueueRef(ref);
|
|
14077
|
+
}
|
|
14078
|
+
if (spec.returns) {
|
|
14079
|
+
for (const ref of extractTypeIdentifiers(spec.returns)) enqueueRef(ref);
|
|
14080
|
+
}
|
|
13944
14081
|
}
|
|
13945
14082
|
const usedIds = /* @__PURE__ */ new Set();
|
|
13946
14083
|
return [...included.entries()].map(([qualified, t]) => {
|
|
13947
14084
|
const id = usedIds.has(t.id) ? qualified : t.id;
|
|
13948
14085
|
usedIds.add(id);
|
|
14086
|
+
const describe2 = (v) => ({
|
|
14087
|
+
name: v.name,
|
|
14088
|
+
type: v.type,
|
|
14089
|
+
...v.description ? { description: v.description } : {},
|
|
14090
|
+
...v.optional ? { optional: true } : {}
|
|
14091
|
+
});
|
|
13949
14092
|
return {
|
|
13950
14093
|
id,
|
|
13951
14094
|
name: t.name,
|
|
13952
14095
|
kind: t.kind,
|
|
13953
|
-
fields: t.fields.map(
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
...f.description ? { description: f.description } : {},
|
|
13957
|
-
...f.optional ? { optional: true } : {}
|
|
13958
|
-
}))
|
|
14096
|
+
fields: t.fields.map(describe2),
|
|
14097
|
+
// A signature type travels complete: its params and returns with it.
|
|
14098
|
+
...t.kind === "signature" ? { params: (t.params ?? []).map(describe2), returns: t.returns ?? "unknown" } : {}
|
|
13959
14099
|
};
|
|
13960
14100
|
});
|
|
13961
14101
|
}
|
|
@@ -13968,7 +14108,7 @@ function boundProjectId() {
|
|
|
13968
14108
|
}
|
|
13969
14109
|
}
|
|
13970
14110
|
function contractEntry(entry, comp, interfaces) {
|
|
13971
|
-
const methods = interfaces.filter((i) => i.component === comp.id && (!entry.interface || i.id === entry.interface)).flatMap((i) => i.methods);
|
|
14111
|
+
const methods = interfaces.filter((i) => i.component === comp.id && (!entry.interface || i.id === entry.interface)).flatMap((i) => i.methods).map(({ signatureFrom: _source, ...method }) => method);
|
|
13972
14112
|
return {
|
|
13973
14113
|
id: entry.publicName,
|
|
13974
14114
|
name: entry.name ?? comp.name,
|
|
@@ -14038,11 +14178,16 @@ function canonicalReferences(snapshot) {
|
|
|
14038
14178
|
...m.params ? { params: m.params.map((p) => ({ ...p, type: canon(p.type) })) } : {}
|
|
14039
14179
|
}))
|
|
14040
14180
|
})),
|
|
14041
|
-
types: snapshot.types.map((def) => ({
|
|
14181
|
+
types: snapshot.types.map((def) => ({
|
|
14182
|
+
...def,
|
|
14183
|
+
fields: def.fields.map((f) => ({ ...f, type: canon(f.type) })),
|
|
14184
|
+
...def.params ? { params: def.params.map((p) => ({ ...p, type: canon(p.type) })) } : {},
|
|
14185
|
+
...def.returns !== void 0 ? { returns: canon(def.returns) } : {}
|
|
14186
|
+
}))
|
|
14042
14187
|
};
|
|
14043
14188
|
}
|
|
14044
|
-
function listSnapshots(
|
|
14045
|
-
const dir = surfacesDir(
|
|
14189
|
+
function listSnapshots() {
|
|
14190
|
+
const dir = surfacesDir(getProjectRoot());
|
|
14046
14191
|
if (!fs9.existsSync(dir)) return [];
|
|
14047
14192
|
const out = [];
|
|
14048
14193
|
for (const file of fs9.readdirSync(dir)) {
|
|
@@ -14057,8 +14202,8 @@ function listSnapshots(rootDir = getProjectRoot()) {
|
|
|
14057
14202
|
function snapshotFilename(projectName) {
|
|
14058
14203
|
return `${safeFilenamePart(projectName)}.yaml`;
|
|
14059
14204
|
}
|
|
14060
|
-
function removeSnapshot(projectName
|
|
14061
|
-
const dir = surfacesDir(
|
|
14205
|
+
function removeSnapshot(projectName) {
|
|
14206
|
+
const dir = surfacesDir(getProjectRoot());
|
|
14062
14207
|
const direct = path13.join(dir, snapshotFilename(projectName));
|
|
14063
14208
|
if (fs9.existsSync(direct)) {
|
|
14064
14209
|
fs9.unlinkSync(direct);
|
|
@@ -14378,11 +14523,11 @@ function listExternals() {
|
|
|
14378
14523
|
}
|
|
14379
14524
|
|
|
14380
14525
|
// src/core/surface-portal.ts
|
|
14381
|
-
function listSnapshots2(
|
|
14382
|
-
return listSnapshots(
|
|
14526
|
+
function listSnapshots2() {
|
|
14527
|
+
return listSnapshots();
|
|
14383
14528
|
}
|
|
14384
|
-
function removeSnapshot2(projectName
|
|
14385
|
-
return removeSnapshot(projectName
|
|
14529
|
+
function removeSnapshot2(projectName) {
|
|
14530
|
+
return removeSnapshot(projectName);
|
|
14386
14531
|
}
|
|
14387
14532
|
function listFamilyPins2() {
|
|
14388
14533
|
return listFamilyPins();
|
|
@@ -15097,7 +15242,7 @@ function defaultTargetConfig(type) {
|
|
|
15097
15242
|
enabled: true
|
|
15098
15243
|
};
|
|
15099
15244
|
}
|
|
15100
|
-
var WAIRON_VERSION = "5.1.1-dev.
|
|
15245
|
+
var WAIRON_VERSION = "5.1.1-dev.95";
|
|
15101
15246
|
var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
15102
15247
|
var ARCHITECT_AGENT_ID = "agent-architect";
|
|
15103
15248
|
var ARCHITECT_TEMPLATE_ID = "architect";
|
|
@@ -15544,13 +15689,13 @@ function resolvePackRef(ref, projectRoot) {
|
|
|
15544
15689
|
}
|
|
15545
15690
|
return resolved;
|
|
15546
15691
|
}
|
|
15547
|
-
function readManifest(target,
|
|
15692
|
+
function readManifest(target, resolveFrom) {
|
|
15548
15693
|
if (isYamlPath(target)) {
|
|
15549
15694
|
const raw = readYamlFile(target);
|
|
15550
15695
|
if (raw == null) throw new Error("file not found or empty");
|
|
15551
15696
|
return { ...DeclarativePackSchema.parse(raw), rules: [] };
|
|
15552
15697
|
}
|
|
15553
|
-
const req = (0, import_module.createRequire)(path17.join(
|
|
15698
|
+
const req = (0, import_module.createRequire)(path17.join(resolveFrom, "package.json"));
|
|
15554
15699
|
const modRaw = req(target);
|
|
15555
15700
|
const mod = modRaw?.default ?? modRaw;
|
|
15556
15701
|
const parsed = DeclarativePackSchema.parse({
|
|
@@ -16130,7 +16275,7 @@ function buildImplementationMethods(ctx) {
|
|
|
16130
16275
|
const component = ctx.componentMap.get(contract.component);
|
|
16131
16276
|
if (!component) continue;
|
|
16132
16277
|
if (ctx.isInChainedSubproject(component.subsystem)) continue;
|
|
16133
|
-
const
|
|
16278
|
+
const draftContext3 = ctx.isImplementationDraft(impl);
|
|
16134
16279
|
for (const method of impl.methods) {
|
|
16135
16280
|
const sourceFile = methodSourceFile(method, impl.sourcePath);
|
|
16136
16281
|
out.push({
|
|
@@ -16138,7 +16283,7 @@ function buildImplementationMethods(ctx) {
|
|
|
16138
16283
|
method,
|
|
16139
16284
|
component,
|
|
16140
16285
|
...sourceFile !== void 0 ? { sourceFile } : {},
|
|
16141
|
-
draftContext
|
|
16286
|
+
draftContext: draftContext3
|
|
16142
16287
|
});
|
|
16143
16288
|
}
|
|
16144
16289
|
}
|
|
@@ -16443,7 +16588,7 @@ var fieldTypeReferencesRule = {
|
|
|
16443
16588
|
var signatureTypeReferencesRule = {
|
|
16444
16589
|
name: "signature-type-references",
|
|
16445
16590
|
judges: "design",
|
|
16446
|
-
description: "Every type identifier
|
|
16591
|
+
description: "Every type identifier a method signature names must resolve to a builtin, a generic parameter in scope on the interface or the method, or a defined type: an interface method's params and returns, a type method's params when it has them, and a signature type's params and returns. A method that takes its signature from a source is skipped \u2014 its params are its source's, judged once where the source declares them.",
|
|
16447
16592
|
codes: [
|
|
16448
16593
|
{ code: "UNDEFINED_TYPE_REFERENCE", defaultSeverity: "error", summary: "Reference to a type that is not defined anywhere" }
|
|
16449
16594
|
],
|
|
@@ -16454,6 +16599,7 @@ var signatureTypeReferencesRule = {
|
|
|
16454
16599
|
Array.from(interfaceGenericParameters(intf)).map((g) => g.toLowerCase())
|
|
16455
16600
|
);
|
|
16456
16601
|
for (const m of intf.methods) {
|
|
16602
|
+
if (m.signatureFrom !== void 0) continue;
|
|
16457
16603
|
const methodGenerics = new Set(
|
|
16458
16604
|
Array.from(methodGenericParameters(m)).map((g) => g.toLowerCase())
|
|
16459
16605
|
);
|
|
@@ -16473,6 +16619,206 @@ var signatureTypeReferencesRule = {
|
|
|
16473
16619
|
}
|
|
16474
16620
|
}
|
|
16475
16621
|
}
|
|
16622
|
+
for (const t of ctx.types) {
|
|
16623
|
+
const sub = t.subsystem ? ctx.subsystems.find((s) => s.id === t.subsystem) : void 0;
|
|
16624
|
+
const isDraftCtx = !!sub && (sub.status === "draft" || sub.status === "design");
|
|
16625
|
+
const typeGenerics = new Set(Array.from(typeGenericParameters(t)).map((g) => g.toLowerCase()));
|
|
16626
|
+
const named2 = [
|
|
16627
|
+
...t.methods.filter((m) => m.params !== void 0).flatMap((m) => methodTypeRefs(m).map((ref) => ({ ref, by: `Method "${m.name}" on type "${t.id}"` }))),
|
|
16628
|
+
...signatureTypeRefs(t).map((ref) => ({ ref, by: `Signature type "${t.id}"` }))
|
|
16629
|
+
];
|
|
16630
|
+
for (const { ref, by } of named2) {
|
|
16631
|
+
if (ctx.isTypeResolved(ref, typeGenerics)) continue;
|
|
16632
|
+
const hint = ctx.importHint(ref);
|
|
16633
|
+
ctx.addIssue(
|
|
16634
|
+
"error",
|
|
16635
|
+
"UNDEFINED_TYPE_REFERENCE",
|
|
16636
|
+
`${by} references undefined type "${ref}" in signature.${hint ? ` A declared dependency exports it without this project importing it \u2014 add \`${hint}\`.` : ""}`,
|
|
16637
|
+
t.id,
|
|
16638
|
+
isDraftCtx
|
|
16639
|
+
);
|
|
16640
|
+
}
|
|
16641
|
+
}
|
|
16642
|
+
}
|
|
16643
|
+
};
|
|
16644
|
+
|
|
16645
|
+
// src/core/rules/integrity/signature-sources.ts
|
|
16646
|
+
function draftContext(ctx, interfaceId, component) {
|
|
16647
|
+
const intf = ctx.interfaceMap.get(interfaceId);
|
|
16648
|
+
return ctx.isComponentDraft(component) || intf?.status === "draft" || intf?.status === "design";
|
|
16649
|
+
}
|
|
16650
|
+
function targetComponent(target) {
|
|
16651
|
+
return target.slice(0, target.lastIndexOf("."));
|
|
16652
|
+
}
|
|
16653
|
+
var signatureSourcesRule = {
|
|
16654
|
+
name: "signature-sources",
|
|
16655
|
+
judges: "design",
|
|
16656
|
+
description: "Judges every signatureFrom the loader met, from ctx.signatureFacts (the loaded specs are already resolved). The value is read both ways, as a contract method and as a signature type: neither resolving \u2014 or only a type that is an entity or value-object \u2014 is unresolved; both resolving is ambiguous, and the finding names both candidates and asks the author to qualify the reference; a source that itself names a signatureFrom is a chain, which is never followed (when that source's own source is a signature type, the finding names it as the one to take directly); a method source whose component the method's component does not name in dependsOn or owns is off the design's edges; a stored method that names a source and also states params or returns that differ from the source's restates it, and the source's are in force. Every finding sits at the method.",
|
|
16657
|
+
codes: [
|
|
16658
|
+
{ code: "SIGNATURE_SOURCE_UNRESOLVED", defaultSeverity: "error", summary: "A method's signatureFrom names no contract method and no signature type" },
|
|
16659
|
+
{ code: "SIGNATURE_SOURCE_AMBIGUOUS", defaultSeverity: "error", summary: "A method's signatureFrom resolves both as a contract method and as a signature type; qualify it" },
|
|
16660
|
+
{ code: "SIGNATURE_SOURCE_CHAINED", defaultSeverity: "error", summary: "A method's signature source takes its own signature from a source; sources do not chain" },
|
|
16661
|
+
{ code: "SIGNATURE_SOURCE_OFF_EDGE", defaultSeverity: "error", summary: "A method takes its signature from a method of a component its own component neither dependsOn nor owns" },
|
|
16662
|
+
{ code: "SIGNATURE_SOURCE_RESTATED", defaultSeverity: "error", summary: "A method names a signature source and also states params or returns that differ from the source's" }
|
|
16663
|
+
],
|
|
16664
|
+
check(ctx) {
|
|
16665
|
+
for (const fact of ctx.signatureFacts?.sources ?? []) {
|
|
16666
|
+
if (!ctx.isSpecInScope(fact.interfaceId)) continue;
|
|
16667
|
+
const isDraft = draftContext(ctx, fact.interfaceId, fact.component);
|
|
16668
|
+
const where = `Method "${fact.method}" on interface "${fact.interfaceId}"`;
|
|
16669
|
+
const at = { at: fact.method };
|
|
16670
|
+
switch (fact.outcome) {
|
|
16671
|
+
case "unresolved":
|
|
16672
|
+
ctx.addIssue(
|
|
16673
|
+
"error",
|
|
16674
|
+
"SIGNATURE_SOURCE_UNRESOLVED",
|
|
16675
|
+
`${where} takes its signature from "${fact.source}", which names ${fact.detail ? `no contract method, and ${fact.detail}` : "no contract method and no signature type"}. A source is a \`component.method\` the component reaches, or a type of kind signature.`,
|
|
16676
|
+
fact.interfaceId,
|
|
16677
|
+
isDraft,
|
|
16678
|
+
void 0,
|
|
16679
|
+
at
|
|
16680
|
+
);
|
|
16681
|
+
continue;
|
|
16682
|
+
case "ambiguous":
|
|
16683
|
+
ctx.addIssue(
|
|
16684
|
+
"error",
|
|
16685
|
+
"SIGNATURE_SOURCE_AMBIGUOUS",
|
|
16686
|
+
`${where} takes its signature from "${fact.source}", which names both the contract method "${fact.candidates?.[0] ?? "?"}" and the signature type "${fact.candidates?.[1] ?? "?"}". Qualify the reference so only one reading matches.`,
|
|
16687
|
+
fact.interfaceId,
|
|
16688
|
+
isDraft,
|
|
16689
|
+
void 0,
|
|
16690
|
+
at
|
|
16691
|
+
);
|
|
16692
|
+
continue;
|
|
16693
|
+
case "chained": {
|
|
16694
|
+
const own = fact.detail ?? "";
|
|
16695
|
+
const direct = ctx.types.some((t) => t.kind === "signature" && (t.id === own || typeMatchesRef(t, own)));
|
|
16696
|
+
ctx.addIssue(
|
|
16697
|
+
"error",
|
|
16698
|
+
"SIGNATURE_SOURCE_CHAINED",
|
|
16699
|
+
`${where} takes its signature from "${fact.target ?? fact.source}", which takes its own from "${own}"; sources do not chain.${direct ? ` "${own}" is a signature type: name it directly as this method's signatureFrom.` : " State this method's params, or name a source that declares its own."}`,
|
|
16700
|
+
fact.interfaceId,
|
|
16701
|
+
isDraft,
|
|
16702
|
+
void 0,
|
|
16703
|
+
at
|
|
16704
|
+
);
|
|
16705
|
+
continue;
|
|
16706
|
+
}
|
|
16707
|
+
case "restated":
|
|
16708
|
+
if (fact.differs) {
|
|
16709
|
+
ctx.addIssue(
|
|
16710
|
+
"error",
|
|
16711
|
+
"SIGNATURE_SOURCE_RESTATED",
|
|
16712
|
+
`${where} takes its signature from "${fact.source}" and also states its own: ${fact.detail ?? "they differ from the source's"}. The source's are in force \u2014 drop the stated params and returns, or drop the signatureFrom.`,
|
|
16713
|
+
fact.interfaceId,
|
|
16714
|
+
isDraft,
|
|
16715
|
+
void 0,
|
|
16716
|
+
at
|
|
16717
|
+
);
|
|
16718
|
+
}
|
|
16719
|
+
continue;
|
|
16720
|
+
default:
|
|
16721
|
+
break;
|
|
16722
|
+
}
|
|
16723
|
+
if (fact.form !== "method" || !fact.target) continue;
|
|
16724
|
+
const source = targetComponent(fact.target);
|
|
16725
|
+
const owner = ctx.componentMap.get(fact.component);
|
|
16726
|
+
const reached = /* @__PURE__ */ new Set([...owner?.dependsOn ?? [], ...owner?.owns ?? []]);
|
|
16727
|
+
if (reached.has(source)) continue;
|
|
16728
|
+
ctx.addIssue(
|
|
16729
|
+
"error",
|
|
16730
|
+
"SIGNATURE_SOURCE_OFF_EDGE",
|
|
16731
|
+
`${where} takes its signature from "${fact.target}", but "${fact.component}" neither dependsOn nor owns "${source}". Add "${source}" to its dependsOn (or owns, for a member), or name a source it reaches.`,
|
|
16732
|
+
fact.interfaceId,
|
|
16733
|
+
isDraft,
|
|
16734
|
+
void 0,
|
|
16735
|
+
at
|
|
16736
|
+
);
|
|
16737
|
+
}
|
|
16738
|
+
}
|
|
16739
|
+
};
|
|
16740
|
+
|
|
16741
|
+
// src/core/rules/integrity/signature-types.ts
|
|
16742
|
+
var signatureTypesRule = {
|
|
16743
|
+
name: "signature-types",
|
|
16744
|
+
judges: "design",
|
|
16745
|
+
description: "A type of kind signature is a named function type and carries params and one returns, nothing else: fields, methods, invariants, componentClass, database, table or linkedEntity on it \u2014 or a returns missing from it \u2014 are reported; so are params or returns on an entity or a value-object, where they mean nothing.",
|
|
16746
|
+
codes: [
|
|
16747
|
+
{ code: "SIGNATURE_TYPE_MEMBERS", defaultSeverity: "error", summary: "A signature type carries a member other than params and returns, or lacks returns; or a data type carries params or returns" }
|
|
16748
|
+
],
|
|
16749
|
+
check(ctx) {
|
|
16750
|
+
for (const t of ctx.types) {
|
|
16751
|
+
if (!ctx.isSpecInScope(t.id)) continue;
|
|
16752
|
+
const sub = t.subsystem ? ctx.subsystems.find((s) => s.id === t.subsystem) : void 0;
|
|
16753
|
+
const isDraft = !!sub && (sub.status === "draft" || sub.status === "design");
|
|
16754
|
+
if (t.kind === "signature") {
|
|
16755
|
+
const members = [
|
|
16756
|
+
...t.fields.length > 0 ? ["fields"] : [],
|
|
16757
|
+
...t.methods.length > 0 ? ["methods"] : [],
|
|
16758
|
+
...(t.invariants?.length ?? 0) > 0 ? ["invariants"] : [],
|
|
16759
|
+
...t.componentClass !== void 0 ? ["componentClass"] : [],
|
|
16760
|
+
...t.database !== void 0 ? ["database"] : [],
|
|
16761
|
+
...t.table !== void 0 ? ["table"] : [],
|
|
16762
|
+
...t.linkedEntity !== void 0 ? ["linkedEntity"] : []
|
|
16763
|
+
];
|
|
16764
|
+
const missingReturns = t.returns === void 0;
|
|
16765
|
+
if (members.length === 0 && !missingReturns) continue;
|
|
16766
|
+
const problems = [
|
|
16767
|
+
...members.length > 0 ? [`carries ${members.join(", ")}`] : [],
|
|
16768
|
+
...missingReturns ? ["states no returns"] : []
|
|
16769
|
+
];
|
|
16770
|
+
ctx.addIssue(
|
|
16771
|
+
"error",
|
|
16772
|
+
"SIGNATURE_TYPE_MEMBERS",
|
|
16773
|
+
`Signature type "${t.id}" ${problems.join(" and ")}. A signature is a named function type: params and one returns, nothing else.`,
|
|
16774
|
+
t.id,
|
|
16775
|
+
isDraft
|
|
16776
|
+
);
|
|
16777
|
+
continue;
|
|
16778
|
+
}
|
|
16779
|
+
const stated = [...t.params !== void 0 ? ["params"] : [], ...t.returns !== void 0 ? ["returns"] : []];
|
|
16780
|
+
if (stated.length === 0) continue;
|
|
16781
|
+
ctx.addIssue(
|
|
16782
|
+
"error",
|
|
16783
|
+
"SIGNATURE_TYPE_MEMBERS",
|
|
16784
|
+
`Type "${t.id}" is ${t.kind === "entity" ? "an entity" : `a ${t.kind}`} and carries ${stated.join(" and ")}, which only a signature type has. Make it kind signature, or drop them.`,
|
|
16785
|
+
t.id,
|
|
16786
|
+
isDraft
|
|
16787
|
+
);
|
|
16788
|
+
}
|
|
16789
|
+
}
|
|
16790
|
+
};
|
|
16791
|
+
|
|
16792
|
+
// src/core/rules/integrity/signature-text.ts
|
|
16793
|
+
function draftContext2(ctx, specId, kind) {
|
|
16794
|
+
if (kind === "interface") {
|
|
16795
|
+
const intf = ctx.interfaceMap.get(specId);
|
|
16796
|
+
return !!intf && (ctx.isComponentDraft(intf.component) || intf.status === "draft" || intf.status === "design");
|
|
16797
|
+
}
|
|
16798
|
+
const type = ctx.types.find((t) => t.id === specId);
|
|
16799
|
+
const sub = type?.subsystem ? ctx.subsystems.find((s) => s.id === type.subsystem) : void 0;
|
|
16800
|
+
return !!sub && (sub.status === "draft" || sub.status === "design");
|
|
16801
|
+
}
|
|
16802
|
+
var signatureTextRule = {
|
|
16803
|
+
name: "signature-text",
|
|
16804
|
+
judges: "design",
|
|
16805
|
+
description: "A stored signature text that differs from the text its method's params derive is stale: every reader is shown the derived text, but the file says something else, and a file read on its own (a diff, a review, a lock approval) is misled. Reported per method, from ctx.signatureFacts, for contract and type methods alike; `wairon doctor --fix` regenerates the stored text, and any save of the spec writes the derived text too.",
|
|
16806
|
+
codes: [
|
|
16807
|
+
{ code: "SIGNATURE_TEXT_STALE", defaultSeverity: "warning", summary: "A stored signature text differs from the text its params derive; doctor --fix regenerates it" }
|
|
16808
|
+
],
|
|
16809
|
+
check(ctx) {
|
|
16810
|
+
for (const stale of ctx.signatureFacts?.staleTexts ?? []) {
|
|
16811
|
+
if (!ctx.isSpecInScope(stale.specId)) continue;
|
|
16812
|
+
ctx.addIssue(
|
|
16813
|
+
"warning",
|
|
16814
|
+
"SIGNATURE_TEXT_STALE",
|
|
16815
|
+
`Method "${stale.method}" on ${stale.kind} "${stale.specId}" stores the signature "${stale.stored}", but its params derive "${stale.derived}" \u2014 which is what every reader is shown. Run \`wairon doctor --fix\` to regenerate the stored text (any save of the spec writes it too).`,
|
|
16816
|
+
stale.specId,
|
|
16817
|
+
draftContext2(ctx, stale.specId, stale.kind),
|
|
16818
|
+
void 0,
|
|
16819
|
+
{ at: stale.method }
|
|
16820
|
+
);
|
|
16821
|
+
}
|
|
16476
16822
|
}
|
|
16477
16823
|
};
|
|
16478
16824
|
|
|
@@ -17904,11 +18250,11 @@ var detailSufficiencyRule = {
|
|
|
17904
18250
|
const contract = ctx.interfaceMap.get(impl.contract);
|
|
17905
18251
|
if (!contract) continue;
|
|
17906
18252
|
const component = ctx.componentMap.get(contract.component);
|
|
17907
|
-
const
|
|
18253
|
+
const draftContext3 = ctx.isImplementationDraft(impl);
|
|
17908
18254
|
for (const method of impl.methods) {
|
|
17909
18255
|
const detail = effectiveDetail(method, impl, component);
|
|
17910
18256
|
if (contract.methods.some((m) => m.name === method.name) && method.narrative.length === 0 && detail.level !== "full") {
|
|
17911
|
-
dialedDown.push({ implementation: impl, method, component, detail, draftContext });
|
|
18257
|
+
dialedDown.push({ implementation: impl, method, component, detail, draftContext: draftContext3 });
|
|
17912
18258
|
}
|
|
17913
18259
|
}
|
|
17914
18260
|
}
|
|
@@ -18870,7 +19216,9 @@ var facadeForwardingRule = {
|
|
|
18870
19216
|
"FACADE_FORWARDING",
|
|
18871
19217
|
`Facade method "${method.name}" of ${comp.componentType} "${comp.id}" (implementation "${impl.id}") must be pure 1:1 forwarding \u2014 exactly one call step to an owned member (${comp.owns.join(", ") || "none declared"}) \u2014 but its narrative ${problem}. Move the logic into a member block, or lint.allow a deliberate exception.`,
|
|
18872
19218
|
impl.id,
|
|
18873
|
-
isDraftCtx
|
|
19219
|
+
isDraftCtx,
|
|
19220
|
+
void 0,
|
|
19221
|
+
{ at: method.name }
|
|
18874
19222
|
);
|
|
18875
19223
|
}
|
|
18876
19224
|
}
|
|
@@ -19873,7 +20221,7 @@ var unusedTypesRule = {
|
|
|
19873
20221
|
// Stage 8: its verdict needs the whole system's specs, so a part judged alone skips it.
|
|
19874
20222
|
needsWholeTree: true,
|
|
19875
20223
|
judges: "design",
|
|
19876
|
-
description: "Flags types no field of any type, no interface method signature and no other type's method signature references. References are matched through the type-reference grammar (generic arguments, collections, qualified ids), and the declaring type's own generic parameters are left out \u2014 a type parameter is not a reference to a type. A type named only by its OWN methods stays unused, the way a function that only calls itself is.",
|
|
20224
|
+
description: "Flags types no field of any type, no interface method signature, no contract method's signatureFrom and no other type's method signature references. References are matched through the type-reference grammar (generic arguments, collections, qualified ids), and the declaring type's own generic parameters are left out \u2014 a type parameter is not a reference to a type. A signature type is used when a method names it as its signatureFrom or a param is typed by it. A type named only by its OWN methods stays unused, the way a function that only calls itself is.",
|
|
19877
20225
|
codes: [
|
|
19878
20226
|
{ code: "UNUSED_TYPE", defaultSeverity: "warning", summary: "Type never referenced by fields, signatures or type methods" }
|
|
19879
20227
|
],
|
|
@@ -19895,6 +20243,7 @@ var unusedTypesRule = {
|
|
|
19895
20243
|
markTypeReferenced(ref);
|
|
19896
20244
|
}
|
|
19897
20245
|
}
|
|
20246
|
+
for (const ref of signatureTypeRefs(t)) markTypeReferenced(ref, t.id);
|
|
19898
20247
|
}
|
|
19899
20248
|
for (const intf of ctx.interfaces) {
|
|
19900
20249
|
for (const m of intf.methods) {
|
|
@@ -19904,6 +20253,13 @@ var unusedTypesRule = {
|
|
|
19904
20253
|
}
|
|
19905
20254
|
}
|
|
19906
20255
|
}
|
|
20256
|
+
for (const fact of ctx.signatureFacts?.sources ?? []) {
|
|
20257
|
+
const named2 = fact.form === "signature" && fact.target ? fact.target : fact.outcome === "ambiguous" ? fact.candidates?.[1] : void 0;
|
|
20258
|
+
if (!named2) continue;
|
|
20259
|
+
for (const spec of ctx.types) {
|
|
20260
|
+
if (spec.id === named2 || typeMatchesRef(spec, named2)) referencedTypes.add(spec.id);
|
|
20261
|
+
}
|
|
20262
|
+
}
|
|
19907
20263
|
for (const t of ctx.types) {
|
|
19908
20264
|
for (const m of t.methods) {
|
|
19909
20265
|
const refs = methodTypeRefs(m);
|
|
@@ -21263,7 +21619,7 @@ function absence(optional) {
|
|
|
21263
21619
|
var typeShapeRule = {
|
|
21264
21620
|
name: "type-shape",
|
|
21265
21621
|
judges: "code",
|
|
21266
|
-
description: "Code-to-contract for the DATA: a type spec's `fields` are compared, name by name, against the shape its `sourcePath` actually declares. `typeRealization` asks whether a type EXISTS in code; nothing asked whether it is the shape the spec claims, so a type spec could describe two fields of a six-field record \u2014 and call the two that are optional required \u2014 straight through a lock and a CI gate, while the ERD, the agent briefs and every implementer read it as truth. That is the worst of the code-to-spec gaps, because a wrong signature eventually breaks at a call site and a type spec that lies is only ever read by humans and agents. Two origins answer at exact grade: a DECLARED shape, whose members the file lists, and a DERIVED one, an alias followed one hop to the object literal its schema is built from, where the keys are the members. A shape that extends another is judged on what it shows and never on what it omits, since its inherited members are not in this file to count.",
|
|
21622
|
+
description: "Code-to-contract for the DATA: a type spec's `fields` are compared, name by name, against the shape its `sourcePath` actually declares. `typeRealization` asks whether a type EXISTS in code; nothing asked whether it is the shape the spec claims, so a type spec could describe two fields of a six-field record \u2014 and call the two that are optional required \u2014 straight through a lock and a CI gate, while the ERD, the agent briefs and every implementer read it as truth. That is the worst of the code-to-spec gaps, because a wrong signature eventually breaks at a call site and a type spec that lies is only ever read by humans and agents. Two origins answer at exact grade: a DECLARED shape, whose members the file lists, and a DERIVED one, an alias followed one hop to the object literal its schema is built from, where the keys are the members \u2014 and on through a composition the same file writes out (`Base.extend({\u2026})` on a schema constant it declares), the extension's keys laid over the base's. A shape that extends another is judged on what it shows and never on what it omits, since its inherited members are not in this file to count.",
|
|
21267
21623
|
codes: [
|
|
21268
21624
|
{
|
|
21269
21625
|
code: "UNREALIZED_TYPE_FIELD",
|
|
@@ -21440,7 +21796,7 @@ var paramConformanceRule = {
|
|
|
21440
21796
|
const stated = normalize3(declared.type);
|
|
21441
21797
|
return stated === realized.type || codeNameOf.get(stated) === realized.type;
|
|
21442
21798
|
};
|
|
21443
|
-
for (const { implementation, method, sourceFile, draftContext } of ctx.implementationMethods()) {
|
|
21799
|
+
for (const { implementation, method, sourceFile, draftContext: draftContext3 } of ctx.implementationMethods()) {
|
|
21444
21800
|
const contract = ctx.interfaceMap.get(implementation.contract);
|
|
21445
21801
|
const declared = contract?.methods.find((m) => m.name === method.name)?.params ?? [];
|
|
21446
21802
|
if (declared.length === 0 || !sourceFile) continue;
|
|
@@ -21463,7 +21819,7 @@ var paramConformanceRule = {
|
|
|
21463
21819
|
"UNREALIZED_PARAM",
|
|
21464
21820
|
`Method "${method.name}" of contract "${implementation.contract}" declares ${unrealized.length} parameter(s) ${subject} does not take \u2014 ${unrealized.map((found) => found.told).join(", ")}. The contract is promising an argument that would go nowhere, and nothing breaks at a call site to correct it: every brief and every caller built from the contract passes one. Take the parameter in the code, or drop it from the contract.`,
|
|
21465
21821
|
implementation.id,
|
|
21466
|
-
|
|
21822
|
+
draftContext3,
|
|
21467
21823
|
void 0,
|
|
21468
21824
|
{ at: method.name, covers: unrealized.map((found) => found.unit) }
|
|
21469
21825
|
);
|
|
@@ -21475,7 +21831,7 @@ var paramConformanceRule = {
|
|
|
21475
21831
|
"UNDECLARED_PARAM",
|
|
21476
21832
|
`${opening} realizing method "${method.name}" of contract "${implementation.contract}" takes ${undeclared.length} parameter(s) the contract does not declare and no declared injection accounts for \u2014 ${undeclared.map((found) => found.told).join(", ")}. An argument a caller must supply that the design never mentions is how a credential ends up in a signature nobody has read against its contract. Declare it on the contract, name it in the implementation's \`injectedParams\` when whatever wires this component up supplies it (a LEADING run only), or take it out of the signature.`,
|
|
21477
21833
|
implementation.id,
|
|
21478
|
-
|
|
21834
|
+
draftContext3,
|
|
21479
21835
|
void 0,
|
|
21480
21836
|
{ at: method.name, covers: undeclared.map((found) => found.unit) }
|
|
21481
21837
|
);
|
|
@@ -21487,7 +21843,7 @@ var paramConformanceRule = {
|
|
|
21487
21843
|
"PARAM_NAME_MISMATCH",
|
|
21488
21844
|
`Method "${method.name}" of contract "${implementation.contract}" and ${subject} agree on position and type but not on name for ${renamed.length} parameter(s) \u2014 ${renamed.map((f) => f.told).join("; ")}. The contract, the ERD and every brief carry one word and the code answers to another, which is a rename nobody recorded rather than a different argument \u2014 the declared type agreeing is what says so. Rename one side to the other.`,
|
|
21489
21845
|
implementation.id,
|
|
21490
|
-
|
|
21846
|
+
draftContext3,
|
|
21491
21847
|
void 0,
|
|
21492
21848
|
{ at: method.name, covers: renamed.map((found) => found.unit) }
|
|
21493
21849
|
);
|
|
@@ -21499,7 +21855,7 @@ var paramConformanceRule = {
|
|
|
21499
21855
|
"PARAM_OPTIONALITY",
|
|
21500
21856
|
`Method "${method.name}" of contract "${implementation.contract}" and ${subject} disagree about whether ${disagreed.length} parameter(s) may be left out \u2014 ${disagreed.map((f) => f.told).join("; ")}. One of them is telling a caller an argument is required when it is not, or the reverse. Omittable is the code's word for it: a default value and a rest parameter make an argument omittable exactly as a question mark does.`,
|
|
21501
21857
|
implementation.id,
|
|
21502
|
-
|
|
21858
|
+
draftContext3,
|
|
21503
21859
|
void 0,
|
|
21504
21860
|
{ at: method.name, covers: disagreed.map((found) => found.unit) }
|
|
21505
21861
|
);
|
|
@@ -21576,7 +21932,7 @@ var routeCoverageRule = {
|
|
|
21576
21932
|
const routes = code.factsAt(file).functionRoutes;
|
|
21577
21933
|
return routes && Object.prototype.hasOwnProperty.call(routes, via) ? routes[via] : [];
|
|
21578
21934
|
});
|
|
21579
|
-
const
|
|
21935
|
+
const draftContext3 = ctx.isComponentDraft(listener.id) || ctx.isComponentDraft(portal.id);
|
|
21580
21936
|
const where = holders.map((file) => `"${file}"`).join(", ");
|
|
21581
21937
|
if (read2.length === 0) {
|
|
21582
21938
|
ctx.addIssue(
|
|
@@ -21584,7 +21940,7 @@ var routeCoverageRule = {
|
|
|
21584
21940
|
"UNREADABLE_ROUTER",
|
|
21585
21941
|
`Listener "${listener.id}" mounts portal "${portal.id}" through "${via}" in ${where}, but no branch of "${via}" reads as a route \u2014 so none of its routes were checked against the contract at all. Only one idiom is read: an \`if\` whose conditions, together with those of every enclosing \`if\`, compare \`<request>.method\` with a string and \`parts[i]\` / \`parts.length\` with literals. Silence here would read as a clean router; it is only one this analysis cannot see. Write the router in that idiom, or carry this finding with the reason it cannot be.`,
|
|
21586
21942
|
anchor,
|
|
21587
|
-
|
|
21943
|
+
draftContext3,
|
|
21588
21944
|
void 0,
|
|
21589
21945
|
{ at: via }
|
|
21590
21946
|
);
|
|
@@ -21609,7 +21965,7 @@ var routeCoverageRule = {
|
|
|
21609
21965
|
"UNDECLARED_ROUTE",
|
|
21610
21966
|
`Portal "${portal.id}"'s router "${via}" (${where}), mounted by listener "${listener.id}", answers ${undeclared.length} route(s) no contract endpoint of "${portal.id}" declares \u2014 ${undeclared.map((key) => `"${key}"`).join(", ")}. A surface the code serves and the design never promised is how a write runs with no contract: no brief, no auth review, no rule reading it. Declare each as a contract method with its endpoint, or take the route out of the router.`,
|
|
21611
21967
|
anchor,
|
|
21612
|
-
|
|
21968
|
+
draftContext3,
|
|
21613
21969
|
void 0,
|
|
21614
21970
|
{ at: via, covers: undeclared }
|
|
21615
21971
|
);
|
|
@@ -21621,7 +21977,7 @@ var routeCoverageRule = {
|
|
|
21621
21977
|
"UNROUTED_ENDPOINT",
|
|
21622
21978
|
`Portal "${portal.id}" binds ${unrouted.length} HTTP endpoint(s) under listener "${listener.id}"'s mount that no route of its router "${via}" (${where}) answers \u2014 ${unrouted.map((key) => `"${key}"`).join(", ")}. The contract promises a route no request can reach. Route it in the router, or drop the endpoint from the contract.`,
|
|
21623
21979
|
anchor,
|
|
21624
|
-
|
|
21980
|
+
draftContext3,
|
|
21625
21981
|
void 0,
|
|
21626
21982
|
{ at: via, covers: unrouted }
|
|
21627
21983
|
);
|
|
@@ -21724,7 +22080,7 @@ var exportConformanceRule = {
|
|
|
21724
22080
|
}
|
|
21725
22081
|
}
|
|
21726
22082
|
}
|
|
21727
|
-
for (const { implementation, method, sourceFile, draftContext } of ctx.implementationMethods()) {
|
|
22083
|
+
for (const { implementation, method, sourceFile, draftContext: draftContext3 } of ctx.implementationMethods()) {
|
|
21728
22084
|
const handle = method.exportedVia;
|
|
21729
22085
|
if (!handle || !sourceFile) continue;
|
|
21730
22086
|
const file = pathKey(sourceFile);
|
|
@@ -21739,7 +22095,7 @@ var exportConformanceRule = {
|
|
|
21739
22095
|
"UNREALIZED_EXPORT_HANDLE",
|
|
21740
22096
|
`Method "${method.name}" in implementation "${implementation.id}" declares exportedVia "${handle}", but "${file}" exports no such name. A handle names the export a consumer imports to REACH the method \u2014 the value that composes it, which \`symbol\` cannot name because \`symbol\` names the function inside \u2014 so one the file does not publish promises a route nobody can import. It allows nothing either: every export of this file is still read against the contracts. Name the binding the file actually exports, export it, or drop the handle.`,
|
|
21741
22097
|
implementation.id,
|
|
21742
|
-
|
|
22098
|
+
draftContext3
|
|
21743
22099
|
);
|
|
21744
22100
|
}
|
|
21745
22101
|
for (const listener of ctx.components) {
|
|
@@ -21766,11 +22122,31 @@ var exportConformanceRule = {
|
|
|
21766
22122
|
);
|
|
21767
22123
|
}
|
|
21768
22124
|
}
|
|
22125
|
+
const typeMethodsAt = /* @__PURE__ */ new Map();
|
|
21769
22126
|
for (const type of ctx.types) {
|
|
21770
22127
|
if (!type.sourcePath) continue;
|
|
21771
22128
|
promise(type.sourcePath, type.symbol ?? type.name);
|
|
21772
22129
|
for (const method of type.methods ?? []) {
|
|
21773
|
-
|
|
22130
|
+
const at = pathKey(method.sourcePath ?? type.sourcePath);
|
|
22131
|
+
const name = method.symbol ?? method.name;
|
|
22132
|
+
promise(at, name);
|
|
22133
|
+
let names = typeMethodsAt.get(at);
|
|
22134
|
+
if (!names) typeMethodsAt.set(at, names = /* @__PURE__ */ new Set());
|
|
22135
|
+
names.add(name);
|
|
22136
|
+
}
|
|
22137
|
+
}
|
|
22138
|
+
for (const file of realization.paths) {
|
|
22139
|
+
const facts = code.factsAt(file);
|
|
22140
|
+
if (!facts || facts.status !== "analyzed" || facts.analysisGrade !== "exact") continue;
|
|
22141
|
+
for (const binding of facts.reexportBindings ?? []) {
|
|
22142
|
+
const target = resolveImport(file, binding.from, code.paths);
|
|
22143
|
+
const methods = target ? typeMethodsAt.get(target) : void 0;
|
|
22144
|
+
if (!methods) continue;
|
|
22145
|
+
if (binding.local === "*") {
|
|
22146
|
+
for (const name of methods) promise(file, name);
|
|
22147
|
+
} else if (methods.has(binding.local)) {
|
|
22148
|
+
promise(file, binding.exported);
|
|
22149
|
+
}
|
|
21774
22150
|
}
|
|
21775
22151
|
}
|
|
21776
22152
|
const takenFrom = /* @__PURE__ */ new Map();
|
|
@@ -23009,6 +23385,68 @@ var namingDisciplineRule = {
|
|
|
23009
23385
|
}
|
|
23010
23386
|
};
|
|
23011
23387
|
|
|
23388
|
+
// src/core/rules/heuristic/signature-source-suggestions.ts
|
|
23389
|
+
function sameParams(a, b) {
|
|
23390
|
+
if (!b || a.length !== b.length) return false;
|
|
23391
|
+
return a.every((p, i) => p.name === b[i].name && p.type === b[i].type && !!p.optional === !!b[i].optional);
|
|
23392
|
+
}
|
|
23393
|
+
function localName(id) {
|
|
23394
|
+
return id.split("::").pop();
|
|
23395
|
+
}
|
|
23396
|
+
var signatureSourceSuggestionsRule = {
|
|
23397
|
+
name: "signature-source-suggestions",
|
|
23398
|
+
judges: "design",
|
|
23399
|
+
description: "A Repository facade method is pure 1:1 forwarding to an owned member by doctrine (facade-forwarding), so its signature IS the member's: where its params (name, type, optional marker, order) and returns equal the owned member method it forwards to, it could name that method as its signatureFrom, and the reference can never be wrong. Suggested only where the adoption would be legal: the member method names no source of its own (no chain). Nothing else is suggested: another forwarder \u2014 a Portal restating an Orchestrator, a client Adapter restating a remote Portal \u2014 is often a public surface that should stay deliberately decoupled from an internal signature, so wairon does not suggest coupling them. Adoption is opt-in, so this is a notice, and ONE per facade contract, the restating methods being the units it covers.",
|
|
23400
|
+
codes: [
|
|
23401
|
+
{ code: "SIGNATURE_SOURCE_AVAILABLE", defaultSeverity: "notice", summary: "A Repository facade's methods restate exactly the owned member methods they forward to and could name them as their signatureFrom" }
|
|
23402
|
+
],
|
|
23403
|
+
check(ctx) {
|
|
23404
|
+
for (const impl of ctx.implementations) {
|
|
23405
|
+
const contract = ctx.interfaceMap.get(impl.contract);
|
|
23406
|
+
if (!contract || !ctx.isSpecInScope(contract.id)) continue;
|
|
23407
|
+
const repository = ctx.componentMap.get(contract.component);
|
|
23408
|
+
if (!repository || repository.componentType !== "Repository") continue;
|
|
23409
|
+
const owned = new Set(repository.owns);
|
|
23410
|
+
const restating = [];
|
|
23411
|
+
for (const realized of impl.methods) {
|
|
23412
|
+
const steps = realized.narrative ?? [];
|
|
23413
|
+
let member;
|
|
23414
|
+
let memberMethod;
|
|
23415
|
+
if (steps.length === 1 && steps[0].type === "call") {
|
|
23416
|
+
member = steps[0].targetComponent;
|
|
23417
|
+
memberMethod = steps[0].targetMethod;
|
|
23418
|
+
} else if (steps.length === 0 && realized.calls?.length === 1) {
|
|
23419
|
+
const entry = realized.calls[0];
|
|
23420
|
+
const dot = entry.lastIndexOf(".");
|
|
23421
|
+
if (dot > 0) {
|
|
23422
|
+
member = entry.slice(0, dot);
|
|
23423
|
+
memberMethod = entry.slice(dot + 1);
|
|
23424
|
+
}
|
|
23425
|
+
}
|
|
23426
|
+
if (!member || !memberMethod) continue;
|
|
23427
|
+
const memberKey = [...owned].find((o) => o === member || localName(o) === localName(member));
|
|
23428
|
+
if (!memberKey) continue;
|
|
23429
|
+
const own = contract.methods.find((m) => m.name === realized.name);
|
|
23430
|
+
if (!own || own.signatureFrom !== void 0 || !own.params) continue;
|
|
23431
|
+
const target = (ctx.interfacesByComponent.get(memberKey) ?? []).flatMap((i) => i.methods).find((m) => m.name === memberMethod);
|
|
23432
|
+
if (!target || target.signatureFrom !== void 0) continue;
|
|
23433
|
+
if (!sameParams(own.params, target.params) || own.returns !== target.returns) continue;
|
|
23434
|
+
restating.push(`${own.name} \u2190 ${localName(memberKey)}.${memberMethod}`);
|
|
23435
|
+
}
|
|
23436
|
+
if (restating.length === 0) continue;
|
|
23437
|
+
ctx.addIssue(
|
|
23438
|
+
"notice",
|
|
23439
|
+
"SIGNATURE_SOURCE_AVAILABLE",
|
|
23440
|
+
`${restating.length === 1 ? "A method" : `${restating.length} methods`} of Repository facade "${contract.id}" restate${restating.length === 1 ? "s" : ""} exactly the owned member method${restating.length === 1 ? "" : "s"} ${restating.length === 1 ? "it forwards" : "they forward"} to: ${restating.map((u) => `"${u}"`).join("; ")}. ${restating.length === 1 ? "It" : "Each"} could name that member method as its signatureFrom (and drop its params and returns), so the signature is stated once. Optional \u2014 a facade's signature is its member's by doctrine.`,
|
|
23441
|
+
contract.id,
|
|
23442
|
+
ctx.isImplementationDraft(impl),
|
|
23443
|
+
void 0,
|
|
23444
|
+
{ at: contract.id, covers: restating }
|
|
23445
|
+
);
|
|
23446
|
+
}
|
|
23447
|
+
}
|
|
23448
|
+
};
|
|
23449
|
+
|
|
23012
23450
|
// src/core/rules/repository.ts
|
|
23013
23451
|
var SDD_RULES = [
|
|
23014
23452
|
hierarchyRule,
|
|
@@ -23028,6 +23466,9 @@ var SDD_RULES = [
|
|
|
23028
23466
|
typeDeclarationsRule,
|
|
23029
23467
|
fieldTypeReferencesRule,
|
|
23030
23468
|
signatureTypeReferencesRule,
|
|
23469
|
+
signatureSourcesRule,
|
|
23470
|
+
signatureTypesRule,
|
|
23471
|
+
signatureTextRule,
|
|
23031
23472
|
// Contracts and the targets narratives name, in four questions with one
|
|
23032
23473
|
// owner each: does the implementation mirror its contract, does a target
|
|
23033
23474
|
// inside this tree resolve, does a target that leaves it pin to exactly one
|
|
@@ -23213,6 +23654,7 @@ var SDD_RULES = [
|
|
|
23213
23654
|
narrativeComplexityRule,
|
|
23214
23655
|
namingDisciplineRule,
|
|
23215
23656
|
methodCohesionRule,
|
|
23657
|
+
signatureSourceSuggestionsRule,
|
|
23216
23658
|
// Pack resolution and reproducibility run late: they are about project
|
|
23217
23659
|
// CONFIGURATION (does the declared pack set resolve, and can it be reproduced
|
|
23218
23660
|
// elsewhere?) rather than spec content.
|
|
@@ -23580,24 +24022,6 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
23580
24022
|
if (!argument || !ts.isTypeQueryNode(argument) || !ts.isIdentifier(argument.exprName)) return void 0;
|
|
23581
24023
|
return argument.exprName.text;
|
|
23582
24024
|
};
|
|
23583
|
-
const baseObjectLiteral = (expression) => {
|
|
23584
|
-
let node = expression;
|
|
23585
|
-
const walked = /* @__PURE__ */ new Set();
|
|
23586
|
-
while (node && !walked.has(node)) {
|
|
23587
|
-
walked.add(node);
|
|
23588
|
-
if (ts.isCallExpression(node)) {
|
|
23589
|
-
const callee = node.expression;
|
|
23590
|
-
if (ts.isPropertyAccessExpression(callee) && callee.name.text === "object") {
|
|
23591
|
-
const literal = node.arguments.find((argument) => ts.isObjectLiteralExpression(argument));
|
|
23592
|
-
if (literal) return literal;
|
|
23593
|
-
}
|
|
23594
|
-
node = callee;
|
|
23595
|
-
} else if (ts.isPropertyAccessExpression(node)) {
|
|
23596
|
-
node = node.expression;
|
|
23597
|
-
} else break;
|
|
23598
|
-
}
|
|
23599
|
-
return void 0;
|
|
23600
|
-
};
|
|
23601
24025
|
const chainedCombinators = (expression) => {
|
|
23602
24026
|
const applied = /* @__PURE__ */ new Set();
|
|
23603
24027
|
let node = expression;
|
|
@@ -23867,13 +24291,48 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
23867
24291
|
ts.forEachChild(node, visit);
|
|
23868
24292
|
};
|
|
23869
24293
|
visit(sf);
|
|
24294
|
+
const composedMembers = (expression, seen) => {
|
|
24295
|
+
const extensions = [];
|
|
24296
|
+
const compose2 = (members) => {
|
|
24297
|
+
const byName = new Map(members.map((member) => [member.name, member]));
|
|
24298
|
+
for (const extension of [...extensions].reverse()) {
|
|
24299
|
+
for (const member of schemaMembers(extension)) byName.set(member.name, member);
|
|
24300
|
+
}
|
|
24301
|
+
return [...byName.values()];
|
|
24302
|
+
};
|
|
24303
|
+
let node = expression;
|
|
24304
|
+
const walked = /* @__PURE__ */ new Set();
|
|
24305
|
+
while (node && !walked.has(node)) {
|
|
24306
|
+
walked.add(node);
|
|
24307
|
+
if (ts.isCallExpression(node)) {
|
|
24308
|
+
const callee = node.expression;
|
|
24309
|
+
if (ts.isPropertyAccessExpression(callee) && callee.name.text === "object") {
|
|
24310
|
+
const literal = node.arguments.find((argument) => ts.isObjectLiteralExpression(argument));
|
|
24311
|
+
if (literal) return compose2(schemaMembers(literal));
|
|
24312
|
+
} else if (ts.isPropertyAccessExpression(callee) && callee.name.text === "extend") {
|
|
24313
|
+
const extension = node.arguments.find((argument) => ts.isObjectLiteralExpression(argument));
|
|
24314
|
+
if (!extension) return void 0;
|
|
24315
|
+
extensions.push(extension);
|
|
24316
|
+
}
|
|
24317
|
+
node = callee;
|
|
24318
|
+
} else if (ts.isPropertyAccessExpression(node)) {
|
|
24319
|
+
node = node.expression;
|
|
24320
|
+
} else if (ts.isIdentifier(node)) {
|
|
24321
|
+
const base = schemaConstants.get(node.text);
|
|
24322
|
+
if (!base || seen.has(node.text)) return void 0;
|
|
24323
|
+
const members = composedMembers(base, /* @__PURE__ */ new Set([...seen, node.text]));
|
|
24324
|
+
return members ? compose2(members) : void 0;
|
|
24325
|
+
} else break;
|
|
24326
|
+
}
|
|
24327
|
+
return void 0;
|
|
24328
|
+
};
|
|
23870
24329
|
for (const alias of derivedAliases) {
|
|
23871
24330
|
if (typeShapes.has(alias.name)) continue;
|
|
23872
24331
|
const initializer = schemaConstants.get(alias.constant);
|
|
23873
24332
|
if (!initializer) continue;
|
|
23874
|
-
const
|
|
23875
|
-
if (!
|
|
23876
|
-
typeShapes.set(alias.name, { origin: "derived", fields
|
|
24333
|
+
const fields = composedMembers(initializer, /* @__PURE__ */ new Set([alias.constant]));
|
|
24334
|
+
if (!fields) continue;
|
|
24335
|
+
typeShapes.set(alias.name, { origin: "derived", fields, methods: [] });
|
|
23877
24336
|
}
|
|
23878
24337
|
const reexportOnly = sf.statements.length > 0 && sf.statements.every((st) => ts.isExportDeclaration(st) && !!st.moduleSpecifier);
|
|
23879
24338
|
return { declared, anchors, exported, imports, reexports, starExports, namedReexports, complexity, calls, importBindings, typeOnlyBindings, fieldTypes, localTypes, typeShapes, functionParams, functionRoutes, mutableBindings, reexportOnly };
|
|
@@ -24172,7 +24631,7 @@ function publishesFrom(module2, name, target, symbol, readReexports, visited = /
|
|
|
24172
24631
|
}
|
|
24173
24632
|
return false;
|
|
24174
24633
|
}
|
|
24175
|
-
function findTestsReferencing(methods, projectRoot, testRoots
|
|
24634
|
+
function findTestsReferencing(methods, projectRoot, testRoots) {
|
|
24176
24635
|
const scanned = readTestFiles(testRoots, projectRoot);
|
|
24177
24636
|
if (scanned.length === 0) return [];
|
|
24178
24637
|
const indiscriminateAbove = scanned.length / 10;
|
|
@@ -24894,6 +25353,7 @@ function buildRuleContext(opts) {
|
|
|
24894
25353
|
...opts.exportTables ? { exportTables: opts.exportTables } : {},
|
|
24895
25354
|
...opts.projectFamily ? { projectFamily: opts.projectFamily } : {},
|
|
24896
25355
|
...opts.exportUsages ? { exportUsages: opts.exportUsages } : {},
|
|
25356
|
+
...opts.signatureFacts ? { signatureFacts: opts.signatureFacts } : {},
|
|
24897
25357
|
pinnedExternals,
|
|
24898
25358
|
codeModel: opts.codeModel ?? emptyCodeModel(),
|
|
24899
25359
|
roundTripIssues: opts.roundTripIssues,
|
|
@@ -25163,7 +25623,7 @@ function boundProjectIdentity() {
|
|
|
25163
25623
|
const lockedProjectId = readLockRecord()?.projectId;
|
|
25164
25624
|
return projectIdentity(config, lockedProjectId);
|
|
25165
25625
|
}
|
|
25166
|
-
function findTestsReferencing2(methods, projectRoot, testRoots
|
|
25626
|
+
function findTestsReferencing2(methods, projectRoot, testRoots) {
|
|
25167
25627
|
return findTestsReferencing(methods, projectRoot, testRoots);
|
|
25168
25628
|
}
|
|
25169
25629
|
function issue(severity, code, message, agentId, specId) {
|
|
@@ -25335,6 +25795,7 @@ function runOwnersGate(rulesOrOptions, projectType = "backend") {
|
|
|
25335
25795
|
const memberTables = family.nodes.filter((n) => n.namespace !== "").map((n) => resolveProjectExports(n.namespace));
|
|
25336
25796
|
const producers = new Set(family.references.filter((r) => r.consumer === "").map((r) => r.producer));
|
|
25337
25797
|
const exportUsages = [...producers].map((producer) => exportUsage("", producer));
|
|
25798
|
+
const signatures = signatureFacts();
|
|
25338
25799
|
const ctx = buildRuleContext({
|
|
25339
25800
|
system,
|
|
25340
25801
|
subsystems,
|
|
@@ -25356,6 +25817,7 @@ function runOwnersGate(rulesOrOptions, projectType = "backend") {
|
|
|
25356
25817
|
],
|
|
25357
25818
|
projectFamily: family,
|
|
25358
25819
|
exportUsages,
|
|
25820
|
+
signatureFacts: signatures,
|
|
25359
25821
|
pinnedExternals,
|
|
25360
25822
|
// By-name selections only: a legacy path ref pins nothing to check. A dry
|
|
25361
25823
|
// run supplies its candidate's; otherwise the stored ones.
|
|
@@ -25475,12 +25937,26 @@ function judgePartAlone(config, scopeSubsystem) {
|
|
|
25475
25937
|
if (ownIds.has(key) || context.ids.has(key)) continue;
|
|
25476
25938
|
issues.push(issue("warning", "EXTERNAL_CHECK_UNAVAILABLE", `"${by}" names "${key}", which neither this part nor its pinned excerpt of "${parentId}" holds \u2014 used since the pin: re-pin with \`wairon externals pin\` while the parent is on disk.`, by));
|
|
25477
25939
|
}
|
|
25940
|
+
const ownSignatures = signatureFacts();
|
|
25941
|
+
const resolved = resolveTree(
|
|
25942
|
+
[...own.interfaces, ...context.interfaces],
|
|
25943
|
+
[...own.components, ...context.components],
|
|
25944
|
+
[...own.types, ...context.types]
|
|
25945
|
+
);
|
|
25946
|
+
const ownInterfaceIds = new Set(own.interfaces.map((i) => i.id));
|
|
25947
|
+
const partSignatures = {
|
|
25948
|
+
sources: [
|
|
25949
|
+
...resolved.facts.sources.filter((f) => ownInterfaceIds.has(f.interfaceId) && f.outcome !== "restated"),
|
|
25950
|
+
...ownSignatures.sources.filter((f) => f.outcome === "restated")
|
|
25951
|
+
],
|
|
25952
|
+
staleTexts: ownSignatures.staleTexts
|
|
25953
|
+
};
|
|
25478
25954
|
const all = {
|
|
25479
25955
|
subsystems: [...own.subsystems, ...context.subsystems],
|
|
25480
25956
|
components: [...own.components, ...context.components],
|
|
25481
|
-
interfaces:
|
|
25957
|
+
interfaces: resolved.interfaces,
|
|
25482
25958
|
implementations: [...own.implementations, ...context.implementations],
|
|
25483
|
-
types:
|
|
25959
|
+
types: resolved.types
|
|
25484
25960
|
};
|
|
25485
25961
|
const system = context.system ?? SystemSpecSchema.parse({ createdAt: EXCERPT_EPOCH, updatedAt: EXCERPT_EPOCH, name: parentId, vision: `The part's parent, "${parentId}" (no L0 pinned).` });
|
|
25486
25962
|
const codeModel = buildCodeModel(own.implementations, own.types, root, [], []);
|
|
@@ -25500,6 +25976,7 @@ function judgePartAlone(config, scopeSubsystem) {
|
|
|
25500
25976
|
exportTables: [],
|
|
25501
25977
|
projectFamily: graph(),
|
|
25502
25978
|
exportUsages: [],
|
|
25979
|
+
signatureFacts: partSignatures,
|
|
25503
25980
|
pinnedExternals: [],
|
|
25504
25981
|
packSelections: packs.filter((p) => typeof p !== "string"),
|
|
25505
25982
|
packRequirements: [],
|
|
@@ -26354,7 +26831,7 @@ function projectFamilyGraph() {
|
|
|
26354
26831
|
|
|
26355
26832
|
// src/core/exports.ts
|
|
26356
26833
|
var CONSUMABLE = /* @__PURE__ */ new Set(["Portal", "Observer"]);
|
|
26357
|
-
function
|
|
26834
|
+
function localName2(id) {
|
|
26358
26835
|
return id.split("::").pop() ?? id;
|
|
26359
26836
|
}
|
|
26360
26837
|
function ownedBy(subsystemId, declaringSubsystem) {
|
|
@@ -26401,7 +26878,7 @@ function findInSource(world, source, table, request) {
|
|
|
26401
26878
|
if (request.typeDef) {
|
|
26402
26879
|
const type = lookupType(world, request.typeDef, source.id);
|
|
26403
26880
|
if (!type) return {};
|
|
26404
|
-
const item2 = { publicName:
|
|
26881
|
+
const item2 = { publicName: localName2(type.id), kind: "type", source: type.subsystem ?? source.id, typeDef: type.id, via: [] };
|
|
26405
26882
|
return { item: item2, found: table.entries.find((e) => e.kind === "type" && e.typeDef === type.id && e.source === item2.source) };
|
|
26406
26883
|
}
|
|
26407
26884
|
const intf = lookup(world.interfaces, request.interface, source.id);
|
|
@@ -26409,7 +26886,7 @@ function findInSource(world, source, table, request) {
|
|
|
26409
26886
|
if (!comp) return {};
|
|
26410
26887
|
const narrowed2 = intf?.id ?? request.interface;
|
|
26411
26888
|
const item = {
|
|
26412
|
-
publicName:
|
|
26889
|
+
publicName: localName2(narrowed2 ?? comp.id),
|
|
26413
26890
|
kind: "component",
|
|
26414
26891
|
source: comp.subsystem,
|
|
26415
26892
|
component: comp.id,
|
|
@@ -26449,7 +26926,7 @@ function bindOwn(world, sub, pi, problems) {
|
|
|
26449
26926
|
problems.push({ kind: "invalid", owner: sub.id, detail: `exports type "${pi.typeDef}" as its own, but ${type ? `it belongs to "${type.subsystem ?? "the system"}"` : "no such type exists"}` });
|
|
26450
26927
|
return void 0;
|
|
26451
26928
|
}
|
|
26452
|
-
const name2 = pi.as ??
|
|
26929
|
+
const name2 = pi.as ?? localName2(type.id);
|
|
26453
26930
|
checkPublicName(name2, sub.id, problems);
|
|
26454
26931
|
return { publicName: name2, kind: "type", source: type.subsystem ?? sub.id, typeDef: type.id, via: [] };
|
|
26455
26932
|
}
|
|
@@ -26457,7 +26934,7 @@ function bindOwn(world, sub, pi, problems) {
|
|
|
26457
26934
|
if (!comp || !ownedBy(sub.id, comp.subsystem)) return void 0;
|
|
26458
26935
|
const intf = lookup(world.interfaces, pi.interface, sub.id);
|
|
26459
26936
|
const narrowed2 = intf?.id ?? pi.interface;
|
|
26460
|
-
const name = pi.as ??
|
|
26937
|
+
const name = pi.as ?? localName2(narrowed2 ?? comp.id);
|
|
26461
26938
|
checkPublicName(name, sub.id, problems);
|
|
26462
26939
|
return {
|
|
26463
26940
|
publicName: name,
|
|
@@ -26492,7 +26969,7 @@ function subsystemCandidates(world, sub, tables, group, problems) {
|
|
|
26492
26969
|
source,
|
|
26493
26970
|
sourceTable,
|
|
26494
26971
|
{ component: pi.component, interface: pi.interface, typeDef: pi.typeDef },
|
|
26495
|
-
(item) => pi.as ??
|
|
26972
|
+
(item) => pi.as ?? localName2(pi.interface ?? item.typeDef ?? item.component ?? ""),
|
|
26496
26973
|
group.has(source.id),
|
|
26497
26974
|
problems
|
|
26498
26975
|
);
|
|
@@ -26668,16 +27145,16 @@ function classifySource(world, sourceId, label7, sources) {
|
|
|
26668
27145
|
function bindOwnType(world, owner, e, problems) {
|
|
26669
27146
|
const type = (world.types.get(e.typeDef) ?? []).find((t) => !t.subsystem);
|
|
26670
27147
|
if (!type) {
|
|
26671
|
-
problems.push({ kind: "invalid", owner, publicName: e.as ?? e.id ??
|
|
27148
|
+
problems.push({ kind: "invalid", owner, publicName: e.as ?? e.id ?? localName2(e.typeDef), detail: `exports type "${e.typeDef}" as its own, but the project owns no project-level type of that id` });
|
|
26672
27149
|
return void 0;
|
|
26673
27150
|
}
|
|
26674
|
-
const name = e.as ?? e.id ??
|
|
27151
|
+
const name = e.as ?? e.id ?? localName2(type.id);
|
|
26675
27152
|
checkPublicName(name, owner, problems);
|
|
26676
27153
|
return { publicName: name, kind: "type", source: owner, typeDef: type.id, via: [] };
|
|
26677
27154
|
}
|
|
26678
27155
|
function bindFromProject(owner, e, source, table, index, problems) {
|
|
26679
27156
|
const named2 = e.component !== void 0 || e.typeDef !== void 0 || e.interface !== void 0;
|
|
26680
|
-
const requested = named2 ?
|
|
27157
|
+
const requested = named2 ? localName2(e.interface ?? e.component ?? e.typeDef) : void 0;
|
|
26681
27158
|
const picked = named2 ? table.entries.filter((x) => x.publicName === requested) : table.entries;
|
|
26682
27159
|
if (named2 && picked.length === 0) {
|
|
26683
27160
|
problems.push({ kind: "invalid", owner, publicName: e.as ?? e.id ?? requested, detail: `re-exports "${requested}" from ${source.label}, whose export table has no such public name \u2014 another project is reached only through its L0 exports` });
|
|
@@ -26714,7 +27191,7 @@ function bindFromSubsystem(world, owner, e, subsystem, subsystemTables, index, p
|
|
|
26714
27191
|
// The default public name is the item's own LOCAL id: a member's L0 is
|
|
26715
27192
|
// read with its ids keyed under its project, and its entry names the
|
|
26716
27193
|
// item as the member wrote it.
|
|
26717
|
-
() => e.as ?? e.id ??
|
|
27194
|
+
() => e.as ?? e.id ?? localName2(e.interface ?? e.component ?? e.typeDef),
|
|
26718
27195
|
false,
|
|
26719
27196
|
problems
|
|
26720
27197
|
);
|
|
@@ -26855,6 +27332,124 @@ function pinnedUsageOf(consumer, alias) {
|
|
|
26855
27332
|
};
|
|
26856
27333
|
}
|
|
26857
27334
|
|
|
27335
|
+
// src/core/signature-sources.ts
|
|
27336
|
+
function emptySignatureFacts() {
|
|
27337
|
+
return { sources: [], staleTexts: [] };
|
|
27338
|
+
}
|
|
27339
|
+
function namespaceOf(key) {
|
|
27340
|
+
const at = key.lastIndexOf("::");
|
|
27341
|
+
return at === -1 ? "" : key.slice(0, at);
|
|
27342
|
+
}
|
|
27343
|
+
function unresolvedMethod(method) {
|
|
27344
|
+
const { params: _params, ...rest } = method;
|
|
27345
|
+
return { ...rest, returns: "unknown", signature: `${method.name}(...): unknown` };
|
|
27346
|
+
}
|
|
27347
|
+
function sameParams2(a, b) {
|
|
27348
|
+
const left = a ?? [];
|
|
27349
|
+
const right = b ?? [];
|
|
27350
|
+
return left.length === right.length && left.every((p, i) => p.name === right[i].name && p.type === right[i].type && !!p.optional === !!right[i].optional);
|
|
27351
|
+
}
|
|
27352
|
+
function tablesOf(interfaces, components, types, references) {
|
|
27353
|
+
const methodsOf = /* @__PURE__ */ new Map();
|
|
27354
|
+
for (const intf of interfaces) methodsOf.set(intf.component, [...methodsOf.get(intf.component) ?? [], ...intf.methods]);
|
|
27355
|
+
const boundTypes = /* @__PURE__ */ new Map();
|
|
27356
|
+
for (const ref of references) {
|
|
27357
|
+
if (ref.position !== "type" || ref.binding === "outside" || ref.binding === "unresolved") continue;
|
|
27358
|
+
boundTypes.set(`${ref.specId}|${ref.authored}`, ref.resolved);
|
|
27359
|
+
}
|
|
27360
|
+
return { methodsOf, componentKeys: new Set(components.map((c) => c.id)), types, boundTypes };
|
|
27361
|
+
}
|
|
27362
|
+
function methodReading(tables, intf, value) {
|
|
27363
|
+
const dot = value.lastIndexOf(".");
|
|
27364
|
+
if (dot <= 0 || dot === value.length - 1) return null;
|
|
27365
|
+
const head2 = value.slice(0, dot);
|
|
27366
|
+
const tail = value.slice(dot + 1);
|
|
27367
|
+
const ns = namespaceOf(intf.id);
|
|
27368
|
+
const keys = [head2, ...ns && !head2.startsWith(`${ns}::`) ? [`${ns}::${head2}`] : []];
|
|
27369
|
+
for (const key of keys) {
|
|
27370
|
+
if (!tables.componentKeys.has(key)) continue;
|
|
27371
|
+
const method = (tables.methodsOf.get(key) ?? []).find((m) => m.name === tail);
|
|
27372
|
+
if (method) return { target: `${key}.${tail}`, method };
|
|
27373
|
+
}
|
|
27374
|
+
return null;
|
|
27375
|
+
}
|
|
27376
|
+
function typeReading(tables, intf, value) {
|
|
27377
|
+
const bound2 = value.includes("::") ? tables.boundTypes.get(`${intf.id}|${value}`) : void 0;
|
|
27378
|
+
const named2 = bound2 !== void 0 ? tables.types.filter((t) => t.id === bound2) : tables.types.filter((t) => t.id === value || typeMatchesRef(t, value));
|
|
27379
|
+
const ns = namespaceOf(intf.id);
|
|
27380
|
+
const local = (t) => namespaceOf(t.id) === ns ? 0 : 1;
|
|
27381
|
+
const ranked = [...named2].sort((a, b) => local(a) - local(b));
|
|
27382
|
+
return { signature: ranked.find((t) => t.kind === "signature"), other: ranked.find((t) => t.kind !== "signature") };
|
|
27383
|
+
}
|
|
27384
|
+
function typeTarget(type) {
|
|
27385
|
+
return type.subsystem && !type.id.includes("::") ? `${type.subsystem}::${type.id}` : type.id;
|
|
27386
|
+
}
|
|
27387
|
+
function restatedFact(base, stored, params, returns) {
|
|
27388
|
+
const statesParams = stored.params !== void 0;
|
|
27389
|
+
const statesReturns = stored.returns !== void 0;
|
|
27390
|
+
if (!statesParams && !statesReturns) return null;
|
|
27391
|
+
const paramsDiffer = statesParams && !sameParams2(stored.params, params);
|
|
27392
|
+
const returnsDiffer = statesReturns && stored.returns !== returns;
|
|
27393
|
+
const differs = paramsDiffer || returnsDiffer;
|
|
27394
|
+
const detail = !differs ? "restates its source exactly" : [paramsDiffer ? "its params differ from the source's" : "", returnsDiffer ? `its returns "${stored.returns}" differ from the source's "${returns}"` : ""].filter(Boolean).join("; ");
|
|
27395
|
+
return { ...base, outcome: "restated", differs, detail };
|
|
27396
|
+
}
|
|
27397
|
+
function resolveSourced(tables, intf, stored, facts) {
|
|
27398
|
+
const source = stored.signatureFrom;
|
|
27399
|
+
const base = { interfaceId: intf.id, component: intf.component, method: stored.name, source };
|
|
27400
|
+
const hit = methodReading(tables, intf, source);
|
|
27401
|
+
const { signature, other } = typeReading(tables, intf, source);
|
|
27402
|
+
if (hit && signature) {
|
|
27403
|
+
facts.sources.push({ ...base, outcome: "ambiguous", candidates: [hit.target, typeTarget(signature)] });
|
|
27404
|
+
return unresolvedMethod(stored);
|
|
27405
|
+
}
|
|
27406
|
+
if (!hit && !signature) {
|
|
27407
|
+
facts.sources.push({ ...base, outcome: "unresolved", ...other ? { detail: `"${typeTarget(other)}" is a type of kind ${other.kind}, not a signature` } : {} });
|
|
27408
|
+
return unresolvedMethod(stored);
|
|
27409
|
+
}
|
|
27410
|
+
if (hit && hit.method.signatureFrom !== void 0) {
|
|
27411
|
+
facts.sources.push({ ...base, form: "method", target: hit.target, outcome: "chained", detail: hit.method.signatureFrom });
|
|
27412
|
+
return unresolvedMethod(stored);
|
|
27413
|
+
}
|
|
27414
|
+
const form = hit ? "method" : "signature";
|
|
27415
|
+
const target = hit ? hit.target : typeTarget(signature);
|
|
27416
|
+
const params = hit ? hit.method.params : signature.params;
|
|
27417
|
+
const returns = hit ? hit.method.returns : signature.returns ?? "unknown";
|
|
27418
|
+
const restated = restatedFact({ ...base, form, target }, stored, params, returns);
|
|
27419
|
+
if (restated) facts.sources.push(restated);
|
|
27420
|
+
facts.sources.push({ ...base, form, target, outcome: "resolved" });
|
|
27421
|
+
const resolved = { ...stored, returns };
|
|
27422
|
+
if (params) resolved.params = params.map((p) => ({ ...p }));
|
|
27423
|
+
else delete resolved.params;
|
|
27424
|
+
if (!params && hit) resolved.signature = hit.method.signature.replace(new RegExp(`^\\s*${hit.method.name}\\b`), stored.name);
|
|
27425
|
+
return resolved;
|
|
27426
|
+
}
|
|
27427
|
+
function withDerivedText(method, stored, specId, kind, facts) {
|
|
27428
|
+
const derived = deriveMethodSignature({ ...method, signature: stored ?? method.signature });
|
|
27429
|
+
if (derived === void 0) return method;
|
|
27430
|
+
if (stored !== void 0 && stored !== derived) facts.staleTexts.push({ specId, kind, method: method.name, stored, derived });
|
|
27431
|
+
return { ...method, signature: derived };
|
|
27432
|
+
}
|
|
27433
|
+
function resolveTree(interfaces, components, types, references = []) {
|
|
27434
|
+
const intfs = interfaces.map((i) => ({ ...i, methods: i.methods.map((m) => ({ ...m })) }));
|
|
27435
|
+
const typeCopies = types.map((t) => ({ ...t, methods: t.methods.map((m) => ({ ...m })) }));
|
|
27436
|
+
const tables = tablesOf(intfs, [...components], typeCopies, references);
|
|
27437
|
+
const facts = emptySignatureFacts();
|
|
27438
|
+
const sourced = intfs.map((intf) => ({
|
|
27439
|
+
...intf,
|
|
27440
|
+
methods: intf.methods.map((m) => m.signatureFrom !== void 0 ? resolveSourced(tables, intf, m, facts) : m)
|
|
27441
|
+
}));
|
|
27442
|
+
const resolvedInterfaces = sourced.map((intf, i) => ({
|
|
27443
|
+
...intf,
|
|
27444
|
+
methods: intf.methods.map((m, j) => withDerivedText(m, intfs[i].methods[j].signature, intf.id, "interface", facts))
|
|
27445
|
+
}));
|
|
27446
|
+
const resolvedTypes = typeCopies.map((t) => ({
|
|
27447
|
+
...t,
|
|
27448
|
+
methods: t.methods.map((m) => withDerivedText(m, m.signature, t.id, "type", facts))
|
|
27449
|
+
}));
|
|
27450
|
+
return { interfaces: resolvedInterfaces, types: resolvedTypes, facts };
|
|
27451
|
+
}
|
|
27452
|
+
|
|
26858
27453
|
// src/core/specs.ts
|
|
26859
27454
|
var PartReadOnly = class extends WaironError {
|
|
26860
27455
|
constructor(message) {
|
|
@@ -26921,7 +27516,8 @@ function emptyIndex() {
|
|
|
26921
27516
|
implementation: {},
|
|
26922
27517
|
type: {},
|
|
26923
27518
|
group: {}
|
|
26924
|
-
}
|
|
27519
|
+
},
|
|
27520
|
+
signatures: { sources: [], staleTexts: [] }
|
|
26925
27521
|
};
|
|
26926
27522
|
}
|
|
26927
27523
|
function isWithin(dir, file) {
|
|
@@ -27154,6 +27750,17 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
|
27154
27750
|
walk2(root, "", /* @__PURE__ */ new Set([chainDirKey(root)]), 0);
|
|
27155
27751
|
return inspection;
|
|
27156
27752
|
}
|
|
27753
|
+
function signatureSourceParts(value) {
|
|
27754
|
+
const dot = value.lastIndexOf(".");
|
|
27755
|
+
if (dot <= 0 || dot === value.length - 1) return null;
|
|
27756
|
+
return { head: value.slice(0, dot), tail: value.slice(dot + 1) };
|
|
27757
|
+
}
|
|
27758
|
+
function mapSignatureSource(value, map) {
|
|
27759
|
+
const parts = signatureSourceParts(value);
|
|
27760
|
+
if (!parts) return value;
|
|
27761
|
+
const head2 = map("signatureFrom", parts.head);
|
|
27762
|
+
return head2 === parts.head ? value : `${head2}.${parts.tail}`;
|
|
27763
|
+
}
|
|
27157
27764
|
function mapSpecReferences(kind, spec, map) {
|
|
27158
27765
|
switch (kind) {
|
|
27159
27766
|
case "subsystem": {
|
|
@@ -27184,7 +27791,15 @@ function mapSpecReferences(kind, spec, map) {
|
|
|
27184
27791
|
}
|
|
27185
27792
|
case "interface": {
|
|
27186
27793
|
const i = spec;
|
|
27187
|
-
return {
|
|
27794
|
+
return {
|
|
27795
|
+
...i,
|
|
27796
|
+
component: map("contract", i.component),
|
|
27797
|
+
// A method source's head is a component reference; a value with no
|
|
27798
|
+
// head is a raw type position the mapper is never asked about.
|
|
27799
|
+
...i.methods?.some((m) => m.signatureFrom !== void 0) ? {
|
|
27800
|
+
methods: i.methods.map((m) => m.signatureFrom !== void 0 ? { ...m, signatureFrom: mapSignatureSource(m.signatureFrom, map) } : m)
|
|
27801
|
+
} : {}
|
|
27802
|
+
};
|
|
27188
27803
|
}
|
|
27189
27804
|
case "implementation": {
|
|
27190
27805
|
const impl = spec;
|
|
@@ -27229,6 +27844,7 @@ function rawReferences(kind, spec) {
|
|
|
27229
27844
|
for (const m of spec.methods) {
|
|
27230
27845
|
qualifiedTypeNames(m.returns).forEach((t) => add2("type", t));
|
|
27231
27846
|
m.params?.forEach((p) => qualifiedTypeNames(p.type).forEach((t) => add2("type", t)));
|
|
27847
|
+
if (m.signatureFrom !== void 0 && !signatureSourceParts(m.signatureFrom)) add2("type", m.signatureFrom);
|
|
27232
27848
|
}
|
|
27233
27849
|
break;
|
|
27234
27850
|
case "implementation":
|
|
@@ -27240,9 +27856,14 @@ function rawReferences(kind, spec) {
|
|
|
27240
27856
|
}
|
|
27241
27857
|
}
|
|
27242
27858
|
break;
|
|
27243
|
-
case "type":
|
|
27244
|
-
|
|
27859
|
+
case "type": {
|
|
27860
|
+
const t = spec;
|
|
27861
|
+
for (const f of t.fields) qualifiedTypeNames(f.type).forEach((n) => add2("type", n));
|
|
27862
|
+
t.params?.forEach((p) => qualifiedTypeNames(p.type).forEach((n) => add2("type", n)));
|
|
27863
|
+
qualifiedTypeNames(t.returns).forEach((n) => add2("type", n));
|
|
27864
|
+
for (const m of t.methods ?? []) m.params?.forEach((p) => qualifiedTypeNames(p.type).forEach((n) => add2("type", n)));
|
|
27245
27865
|
break;
|
|
27866
|
+
}
|
|
27246
27867
|
default:
|
|
27247
27868
|
break;
|
|
27248
27869
|
}
|
|
@@ -27273,6 +27894,8 @@ function bareRawReferences(kind, spec) {
|
|
|
27273
27894
|
case "type": {
|
|
27274
27895
|
const t = spec;
|
|
27275
27896
|
for (const f of t.fields) for (const ref of fieldTypeRefs(t, f.type)) add2("type", ref);
|
|
27897
|
+
for (const ref of signatureTypeRefs(t)) add2("type", ref);
|
|
27898
|
+
for (const m of t.methods ?? []) for (const p of m.params ?? []) for (const ref of fieldTypeRefs(t, p.type)) add2("type", ref);
|
|
27276
27899
|
break;
|
|
27277
27900
|
}
|
|
27278
27901
|
case "implementation":
|
|
@@ -27339,6 +27962,9 @@ function respellStoredReferences(kind, doc, map) {
|
|
|
27339
27962
|
typed(m, "signature");
|
|
27340
27963
|
typed(m, "returns");
|
|
27341
27964
|
for (const p of list(m.params)) typed(p, "type");
|
|
27965
|
+
if (typeof m.signatureFrom === "string") {
|
|
27966
|
+
m.signatureFrom = signatureSourceParts(m.signatureFrom) ? mapSignatureSource(m.signatureFrom, map) : mapTypeNames(m.signatureFrom, map);
|
|
27967
|
+
}
|
|
27342
27968
|
}
|
|
27343
27969
|
break;
|
|
27344
27970
|
case "implementation":
|
|
@@ -27364,6 +27990,9 @@ function respellStoredReferences(kind, doc, map) {
|
|
|
27364
27990
|
at(doc, "subsystem", "subsystem");
|
|
27365
27991
|
at(doc, "group", "group");
|
|
27366
27992
|
for (const f of list(doc.fields)) typed(f, "type");
|
|
27993
|
+
for (const p of list(doc.params)) typed(p, "type");
|
|
27994
|
+
typed(doc, "returns");
|
|
27995
|
+
for (const m of list(doc.methods)) for (const p of list(m.params)) typed(p, "type");
|
|
27367
27996
|
break;
|
|
27368
27997
|
default:
|
|
27369
27998
|
break;
|
|
@@ -27383,7 +28012,9 @@ function mapRawReferences(kind, spec, map) {
|
|
|
27383
28012
|
...m,
|
|
27384
28013
|
...m.signature !== void 0 ? { signature: mapTypeNames(m.signature, map) } : {},
|
|
27385
28014
|
...m.returns !== void 0 ? { returns: mapTypeNames(m.returns, map) } : {},
|
|
27386
|
-
...m.params ? { params: m.params.map((p) => ({ ...p, type: mapTypeNames(p.type, map) })) } : {}
|
|
28015
|
+
...m.params ? { params: m.params.map((p) => ({ ...p, type: mapTypeNames(p.type, map) })) } : {},
|
|
28016
|
+
// A type source is a raw type position; a method source's head is bound, never raw.
|
|
28017
|
+
...m.signatureFrom !== void 0 && !signatureSourceParts(m.signatureFrom) ? { signatureFrom: mapTypeNames(m.signatureFrom, map) } : {}
|
|
27387
28018
|
}))
|
|
27388
28019
|
};
|
|
27389
28020
|
}
|
|
@@ -27411,7 +28042,14 @@ function mapRawReferences(kind, spec, map) {
|
|
|
27411
28042
|
}
|
|
27412
28043
|
case "type": {
|
|
27413
28044
|
const t = spec;
|
|
27414
|
-
|
|
28045
|
+
const typedParams = (params) => params ? { params: params.map((p) => ({ ...p, type: mapTypeNames(p.type, map) })) } : {};
|
|
28046
|
+
return {
|
|
28047
|
+
...t,
|
|
28048
|
+
fields: t.fields.map((f) => ({ ...f, type: mapTypeNames(f.type, map) })),
|
|
28049
|
+
...typedParams(t.params),
|
|
28050
|
+
...t.returns !== void 0 ? { returns: mapTypeNames(t.returns, map) } : {},
|
|
28051
|
+
methods: (t.methods ?? []).map((m) => ({ ...m, ...typedParams(m.params) }))
|
|
28052
|
+
};
|
|
27415
28053
|
}
|
|
27416
28054
|
default:
|
|
27417
28055
|
return spec;
|
|
@@ -27750,6 +28388,7 @@ function specKind(raw) {
|
|
|
27750
28388
|
if ("component" in raw && Array.isArray(raw.methods)) return "interface";
|
|
27751
28389
|
if ("contract" in raw && Array.isArray(raw.methods)) return "implementation";
|
|
27752
28390
|
if ("kind" in raw && Array.isArray(raw.fields)) return "type";
|
|
28391
|
+
if (raw.kind === "signature") return "type";
|
|
27753
28392
|
return void 0;
|
|
27754
28393
|
}
|
|
27755
28394
|
function rewriteSpecRefs(raw, remap) {
|
|
@@ -27804,6 +28443,16 @@ function rewriteSpecRefs(raw, remap) {
|
|
|
27804
28443
|
rewrite(raw, "component", "component");
|
|
27805
28444
|
for (const method of entries(raw.methods)) {
|
|
27806
28445
|
for (const param of entries(method?.params)) rewrite(param, "type", "type");
|
|
28446
|
+
const source = method?.signatureFrom;
|
|
28447
|
+
if (typeof source !== "string") continue;
|
|
28448
|
+
const parts = signatureSourceParts(source);
|
|
28449
|
+
const name = parts ? remap(parts.tail, "method", parts.head) : void 0;
|
|
28450
|
+
const component = parts ? remap(parts.head, "component", parts.tail) : void 0;
|
|
28451
|
+
const next = parts && (component !== parts.head || name !== parts.tail) ? `${component}.${name}` : remap(source, "type");
|
|
28452
|
+
if (next !== source) {
|
|
28453
|
+
method.signatureFrom = next;
|
|
28454
|
+
changed = true;
|
|
28455
|
+
}
|
|
27807
28456
|
}
|
|
27808
28457
|
} else if (kind === "implementation") {
|
|
27809
28458
|
rewrite(raw, "contract", "interface");
|
|
@@ -27834,6 +28483,11 @@ function rewriteSpecRefs(raw, remap) {
|
|
|
27834
28483
|
} else if (kind === "type") {
|
|
27835
28484
|
rewrite(raw, "componentClass", "entity-class");
|
|
27836
28485
|
for (const field of entries(raw.fields)) rewrite(field, "type", "type");
|
|
28486
|
+
for (const param of entries(raw.params)) rewrite(param, "type", "type");
|
|
28487
|
+
rewrite(raw, "returns", "type");
|
|
28488
|
+
for (const method of entries(raw.methods)) {
|
|
28489
|
+
for (const param of entries(method?.params)) rewrite(param, "type", "type");
|
|
28490
|
+
}
|
|
27837
28491
|
}
|
|
27838
28492
|
return changed;
|
|
27839
28493
|
}
|
|
@@ -28352,6 +29006,10 @@ var SpecWorkspace = class {
|
|
|
28352
29006
|
index.groups.push(...raw.index.groups);
|
|
28353
29007
|
for (const kind of Object.keys(index.paths)) Object.assign(index.paths[kind], raw.index.paths[kind]);
|
|
28354
29008
|
}
|
|
29009
|
+
const signatures = resolveTree(index.interfaces, index.components, index.types, raws.flatMap((r) => r.record.authoredReferences));
|
|
29010
|
+
index.interfaces = signatures.interfaces;
|
|
29011
|
+
index.types = signatures.types;
|
|
29012
|
+
index.signatures = signatures.facts;
|
|
28355
29013
|
return { index, raws, readables };
|
|
28356
29014
|
}
|
|
28357
29015
|
/**
|
|
@@ -28777,7 +29435,9 @@ var SpecWorkspace = class {
|
|
|
28777
29435
|
rewrite: local
|
|
28778
29436
|
});
|
|
28779
29437
|
};
|
|
29438
|
+
const localComponents = new Set(index.components.map((c) => nameKey(c.id.split("::").pop())));
|
|
28780
29439
|
const bindLocal = (kind, specKey) => (position, value) => {
|
|
29440
|
+
if (position === "signatureFrom" && !value.includes("::") && !localComponents.has(nameKey(value))) return value;
|
|
28781
29441
|
if (value.includes("::")) {
|
|
28782
29442
|
raw.pending.push({ kind, specKey, position, authored: value, raw: false });
|
|
28783
29443
|
return value;
|
|
@@ -29112,7 +29772,8 @@ var SpecWorkspace = class {
|
|
|
29112
29772
|
this.scanAll();
|
|
29113
29773
|
const from = this.getSubprojectPrefix(spec.id) ?? "";
|
|
29114
29774
|
const carrying = carry && !this.carryDisabled ? /* @__PURE__ */ new Map() : null;
|
|
29115
|
-
const
|
|
29775
|
+
const components = new Set(this.scanAll().components.map((c) => c.id));
|
|
29776
|
+
const mapped = mapSpecReferences(kind, spec, (position, value) => position === "signatureFrom" && !components.has(value) ? value : this.writeReference(from, spec.id, position, value, carrying));
|
|
29116
29777
|
return { ...mapped, id: localOf(from, spec.id).split("::").pop() };
|
|
29117
29778
|
}
|
|
29118
29779
|
// -------------------------------------------------------------------------
|
|
@@ -29208,8 +29869,8 @@ var SpecWorkspace = class {
|
|
|
29208
29869
|
if (pathExists(this.paths.specsInterfacesDir()) && listFiles(this.paths.specsInterfacesDir(), ".yaml").length > 0) {
|
|
29209
29870
|
return path21.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
|
|
29210
29871
|
}
|
|
29211
|
-
const
|
|
29212
|
-
return path21.join(this.paths.specsDir(), "default",
|
|
29872
|
+
const targetComponent2 = componentId || "default";
|
|
29873
|
+
return path21.join(this.paths.specsDir(), "default", targetComponent2, ".interface.yaml");
|
|
29213
29874
|
}
|
|
29214
29875
|
getImplementationPath(id, contractId) {
|
|
29215
29876
|
const index = this.scanAll();
|
|
@@ -29405,8 +30066,15 @@ var SpecWorkspace = class {
|
|
|
29405
30066
|
prepareComponentForWrite(spec) {
|
|
29406
30067
|
return this.relativizeSpec("component", spec);
|
|
29407
30068
|
}
|
|
30069
|
+
/**
|
|
30070
|
+
* spec_registry.saveInterfaceSpec steps 1-2: every method in its stored form
|
|
30071
|
+
* (method_signature.storedForm — the text a method's params derive, nothing
|
|
30072
|
+
* a signatureFrom supplies), then every reference written back relative to
|
|
30073
|
+
* the owning project.
|
|
30074
|
+
*/
|
|
29408
30075
|
prepareInterfaceForWrite(spec) {
|
|
29409
|
-
|
|
30076
|
+
const stored = { ...spec, methods: (spec.methods ?? []).map((m) => storedMethodSignature(m)) };
|
|
30077
|
+
return this.relativizeSpec("interface", stored);
|
|
29410
30078
|
}
|
|
29411
30079
|
prepareImplementationForWrite(spec, carry = true) {
|
|
29412
30080
|
const relative19 = this.relativizeSpec("implementation", spec, carry);
|
|
@@ -29416,8 +30084,10 @@ var SpecWorkspace = class {
|
|
|
29416
30084
|
const partDir = this.partHolding(this.getImplementationPath(spec.id, spec.contract))?.part.directory;
|
|
29417
30085
|
return partDir ? partRelativeFilePaths(relative19, this.rootDir, partDir) : relative19;
|
|
29418
30086
|
}
|
|
30087
|
+
/** A type written in its stored form — every params-bearing method's text derived — relative to the owning project. */
|
|
29419
30088
|
prepareTypeForWrite(spec) {
|
|
29420
|
-
|
|
30089
|
+
const stored = { ...spec, methods: (spec.methods ?? []).map((m) => storedTypeMethod(m)) };
|
|
30090
|
+
return this.relativizeSpec("type", stored);
|
|
29421
30091
|
}
|
|
29422
30092
|
prepareGroupForWrite(spec) {
|
|
29423
30093
|
return this.relativizeSpec("group", spec);
|
|
@@ -29627,7 +30297,7 @@ var SpecWorkspace = class {
|
|
|
29627
30297
|
if (!pathExists(p)) return null;
|
|
29628
30298
|
try {
|
|
29629
30299
|
const raw = readSpecFile(p);
|
|
29630
|
-
return InterfaceSpecSchema.parse(raw);
|
|
30300
|
+
return resolveTree([InterfaceSpecSchema.parse(raw)], index.components, index.types).interfaces[0];
|
|
29631
30301
|
} catch (e) {
|
|
29632
30302
|
this.loaderIssues.push({
|
|
29633
30303
|
severity: "error",
|
|
@@ -30192,6 +30862,17 @@ var SpecWorkspace = class {
|
|
|
30192
30862
|
* dry-run a promotion (write 'complete' → validate → restore) without leaving
|
|
30193
30863
|
* any change behind if validation fails or the user cancels.
|
|
30194
30864
|
*/
|
|
30865
|
+
/**
|
|
30866
|
+
* ispec_index.signatureFacts — what the current scan's signature resolution
|
|
30867
|
+
* recorded: every signatureFrom met and how it resolved, and every stored
|
|
30868
|
+
* text its params contradict. Read from the cached scan, rescanning first
|
|
30869
|
+
* when the tree changed.
|
|
30870
|
+
*/
|
|
30871
|
+
signatureFacts() {
|
|
30872
|
+
const index = this;
|
|
30873
|
+
index.listProjectRoots();
|
|
30874
|
+
return this.cachedIndex.signatures;
|
|
30875
|
+
}
|
|
30195
30876
|
snapshotSpecFiles() {
|
|
30196
30877
|
const index = this.scanAll();
|
|
30197
30878
|
const snapshot = /* @__PURE__ */ new Map();
|
|
@@ -30289,7 +30970,7 @@ var SpecWorkspace = class {
|
|
|
30289
30970
|
*/
|
|
30290
30971
|
updateSpec(kind, id, delta, hooks, dryRun = false) {
|
|
30291
30972
|
const notices = [];
|
|
30292
|
-
const result = this.load(kind, id);
|
|
30973
|
+
const result = storedFormOf(kind, this.load(kind, id));
|
|
30293
30974
|
if (!result) {
|
|
30294
30975
|
throw new Error(`Spec of kind "${kind}" with ID "${id}" does not exist. Define it first.`);
|
|
30295
30976
|
}
|
|
@@ -30802,6 +31483,7 @@ var SpecWorkspace = class {
|
|
|
30802
31483
|
const qualifiedDelta = qualifyDeltaRefs(mergeableDelta);
|
|
30803
31484
|
const mergedResult = mergeDelta(result, qualifiedDelta);
|
|
30804
31485
|
for (const field of unsetFields) delete mergedResult[field];
|
|
31486
|
+
deriveMergedTexts(kind, mergedResult);
|
|
30805
31487
|
const withDefaults = deltaSchema.safeParse(mergedResult);
|
|
30806
31488
|
if (withDefaults.success) {
|
|
30807
31489
|
for (const [key, value] of Object.entries(withDefaults.data)) {
|
|
@@ -31338,6 +32020,26 @@ var PROSE_FIELDS = /* @__PURE__ */ new Set([
|
|
|
31338
32020
|
"caller"
|
|
31339
32021
|
]);
|
|
31340
32022
|
var DELTA_JUMP_PINS = /* @__PURE__ */ Symbol("jumps written by this delta");
|
|
32023
|
+
function storedFormOf(kind, spec) {
|
|
32024
|
+
if (!spec) return spec;
|
|
32025
|
+
if (kind === "interface") {
|
|
32026
|
+
const intf = spec;
|
|
32027
|
+
return { ...intf, methods: intf.methods.map((m) => storedMethodSignature(m)) };
|
|
32028
|
+
}
|
|
32029
|
+
if (kind === "type") {
|
|
32030
|
+
const type = spec;
|
|
32031
|
+
return { ...type, methods: type.methods.map((m) => storedTypeMethod(m)) };
|
|
32032
|
+
}
|
|
32033
|
+
return spec;
|
|
32034
|
+
}
|
|
32035
|
+
function deriveMergedTexts(kind, merged) {
|
|
32036
|
+
if (kind !== "interface" && kind !== "type" || !Array.isArray(merged.methods)) return;
|
|
32037
|
+
merged.methods = merged.methods.map((m) => {
|
|
32038
|
+
if (!m || typeof m !== "object" || m.signatureFrom !== void 0 || !Array.isArray(m.params)) return m;
|
|
32039
|
+
const derived = deriveMethodSignature(m);
|
|
32040
|
+
return derived === void 0 ? m : { ...m, signature: derived };
|
|
32041
|
+
});
|
|
32042
|
+
}
|
|
31341
32043
|
function cloneSpec(spec) {
|
|
31342
32044
|
return JSON.parse(JSON.stringify(spec));
|
|
31343
32045
|
}
|
|
@@ -31646,6 +32348,9 @@ function removePackSelection(packName) {
|
|
|
31646
32348
|
function setProjectType(projectType) {
|
|
31647
32349
|
projectConfigRepository.setProjectType(projectType);
|
|
31648
32350
|
}
|
|
32351
|
+
function describeProject(name, description) {
|
|
32352
|
+
projectConfigRepository.describeProject(name, description);
|
|
32353
|
+
}
|
|
31649
32354
|
function recordProfileSelection(selection) {
|
|
31650
32355
|
projectConfigRepository.recordProfileSelection(selection);
|
|
31651
32356
|
}
|
|
@@ -31701,6 +32406,9 @@ function specPathsInScope(scopeSubsystem) {
|
|
|
31701
32406
|
function snapshotSpecFiles() {
|
|
31702
32407
|
return current().snapshotSpecFiles();
|
|
31703
32408
|
}
|
|
32409
|
+
function signatureFacts() {
|
|
32410
|
+
return current().signatureFacts();
|
|
32411
|
+
}
|
|
31704
32412
|
function findLegacySpecFiles() {
|
|
31705
32413
|
return current().findLegacySpecFiles();
|
|
31706
32414
|
}
|
|
@@ -31969,7 +32677,7 @@ function referencedKeys(part, types) {
|
|
|
31969
32677
|
}
|
|
31970
32678
|
for (const i of loadInterfaceSpecs().filter((x) => own.has(x.id))) {
|
|
31971
32679
|
add2(i.component);
|
|
31972
|
-
for (const m of i.methods) addTypes(
|
|
32680
|
+
for (const m of i.methods) addTypes(sourcedMethodTypeRefs(m));
|
|
31973
32681
|
}
|
|
31974
32682
|
for (const impl of loadImplementationSpecs().filter((x) => own.has(x.id))) {
|
|
31975
32683
|
add2(impl.contract);
|
|
@@ -31982,10 +32690,20 @@ function referencedKeys(part, types) {
|
|
|
31982
32690
|
}
|
|
31983
32691
|
for (const t of types.filter((x) => own.has(x.id))) {
|
|
31984
32692
|
add2(t.subsystem);
|
|
31985
|
-
|
|
32693
|
+
addTypes(typeSpecTypeRefs(t));
|
|
31986
32694
|
}
|
|
31987
32695
|
return out;
|
|
31988
32696
|
}
|
|
32697
|
+
function sourcedMethodTypeRefs(m) {
|
|
32698
|
+
return [...methodTypeRefs(m), ...m.signatureFrom !== void 0 ? [m.signatureFrom] : []];
|
|
32699
|
+
}
|
|
32700
|
+
function typeSpecTypeRefs(t) {
|
|
32701
|
+
return [
|
|
32702
|
+
...(t.fields ?? []).flatMap((f) => fieldTypeRefs(t, f.type)),
|
|
32703
|
+
...(t.methods ?? []).filter((m) => m.params !== void 0).flatMap((m) => methodTypeRefs(m)),
|
|
32704
|
+
...signatureTypeRefs(t)
|
|
32705
|
+
];
|
|
32706
|
+
}
|
|
31989
32707
|
var KINDS = ["component", "interface", "subsystem", "type", "implementation"];
|
|
31990
32708
|
function closeOver(keys, types) {
|
|
31991
32709
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -32005,10 +32723,9 @@ function closeOver(keys, types) {
|
|
|
32005
32723
|
queue.push(comp.subsystem);
|
|
32006
32724
|
for (const contract of interfaces.filter((i) => i.component === comp.id)) queue.push(contract.id);
|
|
32007
32725
|
} else if (found.kind === "interface") {
|
|
32008
|
-
for (const m of found.spec.methods) addTypes(
|
|
32726
|
+
for (const m of found.spec.methods) addTypes(sourcedMethodTypeRefs(m));
|
|
32009
32727
|
} else if (found.kind === "type") {
|
|
32010
|
-
|
|
32011
|
-
for (const f of type.fields ?? []) addTypes(fieldTypeRefs(type, f.type));
|
|
32728
|
+
addTypes(typeSpecTypeRefs(found.spec));
|
|
32012
32729
|
} else if (found.kind === "implementation") {
|
|
32013
32730
|
queue.push(found.spec.contract);
|
|
32014
32731
|
}
|
|
@@ -33548,7 +34265,11 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
|
|
|
33548
34265
|
for (const contract of moving) {
|
|
33549
34266
|
saveInterfaceSpec({
|
|
33550
34267
|
...contract,
|
|
33551
|
-
methods: contract.methods.map((m) => m.name === methodName ? {
|
|
34268
|
+
methods: contract.methods.map((m) => m.name === methodName ? {
|
|
34269
|
+
...m,
|
|
34270
|
+
name: newName,
|
|
34271
|
+
...m.params === void 0 && m.signatureFrom === void 0 ? { signature: renameInSignature(m.signature, methodName, newName) } : {}
|
|
34272
|
+
} : m)
|
|
33552
34273
|
});
|
|
33553
34274
|
renamed.push(contract.id);
|
|
33554
34275
|
}
|
|
@@ -33957,16 +34678,16 @@ var path28 = __toESM(require("path"));
|
|
|
33957
34678
|
function builtinTemplatesDir() {
|
|
33958
34679
|
return path28.resolve(__dirname, "..", "templates");
|
|
33959
34680
|
}
|
|
33960
|
-
function loadTemplate(
|
|
33961
|
-
const dirs = templateSearchDirs(
|
|
34681
|
+
function loadTemplate(templateName, globalTemplatesDir2) {
|
|
34682
|
+
const dirs = templateSearchDirs(globalTemplatesDir2);
|
|
33962
34683
|
for (const dir of dirs) {
|
|
33963
|
-
const filePath = path28.join(dir, `${
|
|
34684
|
+
const filePath = path28.join(dir, `${templateName}.yaml`);
|
|
33964
34685
|
if (pathExists(filePath)) {
|
|
33965
34686
|
const raw = readYamlFile(filePath);
|
|
33966
|
-
return { ...TemplateSchema.parse(raw), templateName
|
|
34687
|
+
return { ...TemplateSchema.parse(raw), templateName };
|
|
33967
34688
|
}
|
|
33968
34689
|
}
|
|
33969
|
-
throw new TemplateNotFoundError(
|
|
34690
|
+
throw new TemplateNotFoundError(templateName);
|
|
33970
34691
|
}
|
|
33971
34692
|
function loadAgentOverride(agentId) {
|
|
33972
34693
|
const filePath = path28.join(AI_PATHS.root(), "agents", `${agentId}.md`);
|
|
@@ -34249,7 +34970,7 @@ function inferSourcePathForComponent(comp, subsystems) {
|
|
|
34249
34970
|
return null;
|
|
34250
34971
|
}
|
|
34251
34972
|
}
|
|
34252
|
-
function
|
|
34973
|
+
function summarize(text3, max = 140) {
|
|
34253
34974
|
const clean = text3.replace(/\s+/g, " ").trim();
|
|
34254
34975
|
const period = clean.indexOf(". ");
|
|
34255
34976
|
const firstSentence = period > 0 ? clean.slice(0, period + 1) : clean;
|
|
@@ -34304,7 +35025,7 @@ function resolveLayer(delegate) {
|
|
|
34304
35025
|
agents.push({
|
|
34305
35026
|
id: "system-architect",
|
|
34306
35027
|
name: `${system.name} Architect`,
|
|
34307
|
-
description: `Global architect for ${system.name} \u2014 owns the spec tree and topology. ${
|
|
35028
|
+
description: `Global architect for ${system.name} \u2014 owns the spec tree and topology. ${summarize(system.vision)}`,
|
|
34308
35029
|
template: "architect",
|
|
34309
35030
|
creationReason: "Automatically inferred from L0 system spec",
|
|
34310
35031
|
ownedPaths: [".wai/specs/**"],
|
|
@@ -34388,7 +35109,7 @@ function resolveLayer(delegate) {
|
|
|
34388
35109
|
agents.push({
|
|
34389
35110
|
id: `${sub.id}-owner`,
|
|
34390
35111
|
name: `${sub.name} Owner`,
|
|
34391
|
-
description: `Owns the ${sub.id} subsystem. ${
|
|
35112
|
+
description: `Owns the ${sub.id} subsystem. ${summarize(sub.description)}${partNote ? ` ${partNote}` : ""}`,
|
|
34392
35113
|
template: "domain-owner",
|
|
34393
35114
|
creationReason: `Automatically inferred from L1 subsystem spec: ${sub.id}`,
|
|
34394
35115
|
domainRoot: sub.id,
|
|
@@ -34453,7 +35174,7 @@ function resolveLayer(delegate) {
|
|
|
34453
35174
|
agents.push({
|
|
34454
35175
|
id: `${dom.id}-owner`,
|
|
34455
35176
|
name: `${dom.name ?? dom.id} Owner`,
|
|
34456
|
-
description: dom.description ?
|
|
35177
|
+
description: dom.description ? summarize(dom.description) : `Owner agent for the free-standing "${dom.id}" domain.`,
|
|
34457
35178
|
template: "domain-owner",
|
|
34458
35179
|
creationReason: "Inferred from a free-standing domain in .wai/topology.yaml",
|
|
34459
35180
|
domainRoot: dom.id,
|
|
@@ -35063,6 +35784,46 @@ function repairForeignStepFields(apply3) {
|
|
|
35063
35784
|
return repairs;
|
|
35064
35785
|
}
|
|
35065
35786
|
|
|
35787
|
+
// src/core/signature-repair.ts
|
|
35788
|
+
function repairSignatures(apply3) {
|
|
35789
|
+
const facts = signatureFacts();
|
|
35790
|
+
const repairs = /* @__PURE__ */ new Map();
|
|
35791
|
+
const repairOf = (specId, kind) => {
|
|
35792
|
+
const key = `${kind}:${specId}`;
|
|
35793
|
+
let repair = repairs.get(key);
|
|
35794
|
+
if (!repair) {
|
|
35795
|
+
repair = { specId, kind, regenerated: [], dropped: [] };
|
|
35796
|
+
repairs.set(key, repair);
|
|
35797
|
+
}
|
|
35798
|
+
return repair;
|
|
35799
|
+
};
|
|
35800
|
+
const held = new Set(facts.sources.filter((f) => f.outcome === "restated" && f.differs).map((f) => f.interfaceId));
|
|
35801
|
+
const own = (specId, kind) => !specId.includes("::") && !(kind === "interface" && held.has(specId));
|
|
35802
|
+
for (const stale of facts.staleTexts) {
|
|
35803
|
+
if (own(stale.specId, stale.kind)) repairOf(stale.specId, stale.kind).regenerated.push(stale);
|
|
35804
|
+
}
|
|
35805
|
+
for (const fact of facts.sources) {
|
|
35806
|
+
if (fact.outcome !== "restated" || fact.differs || !own(fact.interfaceId, "interface")) continue;
|
|
35807
|
+
repairOf(fact.interfaceId, "interface").dropped.push(fact.method);
|
|
35808
|
+
}
|
|
35809
|
+
const planned = [...repairs.values()];
|
|
35810
|
+
if (apply3 && planned.length > 0) {
|
|
35811
|
+
const interfaces = new Map(loadInterfaceSpecs().map((i) => [i.id, i]));
|
|
35812
|
+
const types = new Map(loadTypeSpecs().map((t) => [t.id, t]));
|
|
35813
|
+
for (const repair of planned) {
|
|
35814
|
+
if (repair.kind === "interface") {
|
|
35815
|
+
const intf = interfaces.get(repair.specId);
|
|
35816
|
+
if (intf) saveInterfaceSpec(intf);
|
|
35817
|
+
continue;
|
|
35818
|
+
}
|
|
35819
|
+
const type = types.get(repair.specId);
|
|
35820
|
+
if (type) saveSpec("type", type);
|
|
35821
|
+
}
|
|
35822
|
+
invalidateSpecCache();
|
|
35823
|
+
}
|
|
35824
|
+
return planned;
|
|
35825
|
+
}
|
|
35826
|
+
|
|
35066
35827
|
// src/core/approval.ts
|
|
35067
35828
|
var crypto7 = __toESM(require("crypto"));
|
|
35068
35829
|
var path35 = __toESM(require("path"));
|
|
@@ -35320,8 +36081,11 @@ function localGuideFilePath(projectRoot, targetType) {
|
|
|
35320
36081
|
if (targetType === "gemini" || targetType === "agy") return path36.join(projectRoot, ".gemini", "GEMINI.md");
|
|
35321
36082
|
return null;
|
|
35322
36083
|
}
|
|
36084
|
+
function guideBody(scope) {
|
|
36085
|
+
return scope === "global" ? GLOBAL_GUIDE_BODY : LOCAL_GUIDE_BODY;
|
|
36086
|
+
}
|
|
35323
36087
|
function injectGuide(filePath, scope) {
|
|
35324
|
-
const body = scope
|
|
36088
|
+
const body = guideBody(scope);
|
|
35325
36089
|
const section = `
|
|
35326
36090
|
|
|
35327
36091
|
${GUIDE_MARKER_START}
|
|
@@ -35530,7 +36294,7 @@ function renderWaironGuide() {
|
|
|
35530
36294
|
lines.push("---");
|
|
35531
36295
|
lines.push("");
|
|
35532
36296
|
}
|
|
35533
|
-
lines.push(
|
|
36297
|
+
lines.push(guideBody("global"));
|
|
35534
36298
|
lines.push("");
|
|
35535
36299
|
return lines.join("\n");
|
|
35536
36300
|
}
|
|
@@ -35991,22 +36755,6 @@ function packSkillId(skill) {
|
|
|
35991
36755
|
function packNamespace(pack) {
|
|
35992
36756
|
return pack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
35993
36757
|
}
|
|
35994
|
-
function extensionsFor(builtin, packSkills) {
|
|
35995
|
-
return packSkills.filter((s) => s.extends === builtin && fs22.existsSync(s.sourcePath));
|
|
35996
|
-
}
|
|
35997
|
-
function composeBuiltinSkill(name, packSkills) {
|
|
35998
|
-
const srcPath = skillTemplatePath(name);
|
|
35999
|
-
const base = fs22.existsSync(srcPath) ? fs22.readFileSync(srcPath, "utf-8") : "";
|
|
36000
|
-
const sections = extensionsFor(name, packSkills);
|
|
36001
|
-
if (sections.length === 0) return base;
|
|
36002
|
-
const parts = [base.trimEnd()];
|
|
36003
|
-
for (const section of sections) {
|
|
36004
|
-
const body = fs22.readFileSync(section.sourcePath, "utf-8").replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "");
|
|
36005
|
-
parts.push(`## Platform: ${section.pack}`, body.trim());
|
|
36006
|
-
}
|
|
36007
|
-
return `${parts.join("\n\n")}
|
|
36008
|
-
`;
|
|
36009
|
-
}
|
|
36010
36758
|
function readFrontmatter(raw, fallbackName) {
|
|
36011
36759
|
const match2 = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
36012
36760
|
const block2 = match2 ? match2[1] : "";
|
|
@@ -36029,12 +36777,6 @@ function activeTargetTypes2() {
|
|
|
36029
36777
|
}
|
|
36030
36778
|
var SKILL_RESOURCE_SCHEME = "wairon-skill";
|
|
36031
36779
|
var RESOURCE_SKILL_IDS = [...SKILL_NAMES].sort();
|
|
36032
|
-
var SkillResourceNotFoundError = class extends Error {
|
|
36033
|
-
constructor(resourceId) {
|
|
36034
|
-
super(`Unknown SDD skill resource id: "${resourceId}".`);
|
|
36035
|
-
this.name = "SkillResourceNotFoundError";
|
|
36036
|
-
}
|
|
36037
|
-
};
|
|
36038
36780
|
function readSkillFrontmatter(name) {
|
|
36039
36781
|
return readFrontmatter(fs22.readFileSync(skillTemplatePath(name), "utf-8"), name);
|
|
36040
36782
|
}
|
|
@@ -36064,24 +36806,9 @@ function listSkillResources() {
|
|
|
36064
36806
|
});
|
|
36065
36807
|
return [...builtin, ...pack];
|
|
36066
36808
|
}
|
|
36067
|
-
function readSkillResource(resourceId) {
|
|
36068
|
-
const packSkills = loadProjectExtensions().skills;
|
|
36069
|
-
if (SKILL_NAMES.includes(resourceId)) return composeBuiltinSkill(resourceId, packSkills);
|
|
36070
|
-
const packSkill = packSkills.find((s) => s.extends === void 0 && packSkillId(s) === resourceId);
|
|
36071
|
-
if (packSkill) return fs22.readFileSync(packSkill.sourcePath, "utf-8");
|
|
36072
|
-
return fs22.readFileSync(skillTemplatePath(resourceId), "utf-8");
|
|
36073
|
-
}
|
|
36074
|
-
function listResources() {
|
|
36075
|
-
return listSkillResources();
|
|
36076
|
-
}
|
|
36077
36809
|
function buildServerInstructions2() {
|
|
36078
36810
|
return buildServerInstructions();
|
|
36079
36811
|
}
|
|
36080
|
-
function readResource(resourceId) {
|
|
36081
|
-
const known = listSkillResources().some((d) => d.id === resourceId);
|
|
36082
|
-
if (!known) throw new SkillResourceNotFoundError(resourceId);
|
|
36083
|
-
return readSkillResource(resourceId);
|
|
36084
|
-
}
|
|
36085
36812
|
|
|
36086
36813
|
// src/mcp/server.ts
|
|
36087
36814
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
@@ -36124,6 +36851,8 @@ function componentCandidateGate(options = candidateOptions(), storedOwner) {
|
|
|
36124
36851
|
return {
|
|
36125
36852
|
gate: (kind, merged) => {
|
|
36126
36853
|
refuseUnknownOwner(kind, merged, storedOwner);
|
|
36854
|
+
const restated = kind === "interface" ? restatedSources(merged.methods) : [];
|
|
36855
|
+
if (restated.length) throw new Error(`${restatedSourceRefusal(String(merged.id), restated)} Nothing was written.`);
|
|
36127
36856
|
if (kind !== "component") return;
|
|
36128
36857
|
const verdict = validateComponentCandidate(merged, options);
|
|
36129
36858
|
if (verdict.errors.length) throw new Error(formatCandidateRefusal(verdict));
|
|
@@ -36131,6 +36860,43 @@ function componentCandidateGate(options = candidateOptions(), storedOwner) {
|
|
|
36131
36860
|
}
|
|
36132
36861
|
};
|
|
36133
36862
|
}
|
|
36863
|
+
function restatedSources(methods) {
|
|
36864
|
+
if (!Array.isArray(methods)) return [];
|
|
36865
|
+
return methods.filter((m) => m && typeof m === "object" && m.signatureFrom !== void 0 && (m.params !== void 0 || m.returns !== void 0)).map((m) => String(m.name));
|
|
36866
|
+
}
|
|
36867
|
+
function restatedSourceRefusal(id, methods) {
|
|
36868
|
+
return `SIGNATURE_SOURCE_RESTATED: interface "${id}" \u2014 ${methods.map((n) => `"${n}"`).join(", ")} ${methods.length === 1 ? "names" : "name"} a signatureFrom and also ${methods.length === 1 ? "states" : "state"} params or returns. The source supplies them: state the signatureFrom alone, or the params and returns alone. To adopt a source on a method that states its own, unset its params and returns in the same delta.`;
|
|
36869
|
+
}
|
|
36870
|
+
function unsignedMethods(methods) {
|
|
36871
|
+
if (!Array.isArray(methods)) return [];
|
|
36872
|
+
return methods.filter((m) => m && typeof m === "object" && m.signatureFrom === void 0 && m.params === void 0 && (typeof m.signature !== "string" || m.signature.trim() === "")).map((m) => String(m.name));
|
|
36873
|
+
}
|
|
36874
|
+
function deriveStatedTexts(kind, candidate) {
|
|
36875
|
+
if (kind !== "interface" && kind !== "type" || !Array.isArray(candidate.methods)) return [];
|
|
36876
|
+
const differed = [];
|
|
36877
|
+
candidate.methods = candidate.methods.map((m) => {
|
|
36878
|
+
if (!m || typeof m !== "object" || m.signatureFrom !== void 0 || !Array.isArray(m.params)) return m;
|
|
36879
|
+
const derived = deriveMethodSignature(m);
|
|
36880
|
+
if (derived === void 0) return m;
|
|
36881
|
+
if (typeof m.signature === "string" && m.signature !== derived) differed.push(`"${m.name}": stated "${m.signature}", written "${derived}"`);
|
|
36882
|
+
return { ...m, signature: derived };
|
|
36883
|
+
});
|
|
36884
|
+
return differed.length === 0 ? [] : [
|
|
36885
|
+
`Signature text derived from params, not taken as stated \u2014 ${differed.join("; ")}. A method with params shows the text its params derive.`
|
|
36886
|
+
];
|
|
36887
|
+
}
|
|
36888
|
+
function storedForm(kind, spec) {
|
|
36889
|
+
if (!spec) return spec;
|
|
36890
|
+
if (kind === "interface") {
|
|
36891
|
+
const intf = spec;
|
|
36892
|
+
return { ...intf, methods: intf.methods.map((m) => storedMethodSignature(m)) };
|
|
36893
|
+
}
|
|
36894
|
+
if (kind === "type") {
|
|
36895
|
+
const type = spec;
|
|
36896
|
+
return { ...type, methods: type.methods.map((m) => storedTypeMethod(m)) };
|
|
36897
|
+
}
|
|
36898
|
+
return spec;
|
|
36899
|
+
}
|
|
36134
36900
|
function refuseUnknownOwner(kind, merged, storedOwner) {
|
|
36135
36901
|
if (kind !== "component" && kind !== "type") return;
|
|
36136
36902
|
const owner = merged.subsystem;
|
|
@@ -36175,7 +36941,8 @@ function restatementParent(restatement) {
|
|
|
36175
36941
|
return null;
|
|
36176
36942
|
}
|
|
36177
36943
|
}
|
|
36178
|
-
function applyRestatement(restatement,
|
|
36944
|
+
function applyRestatement(restatement, loaded, parent) {
|
|
36945
|
+
const existing = storedForm(restatement.kind, loaded);
|
|
36179
36946
|
const replacedExisting = existing !== null;
|
|
36180
36947
|
const parentRef = restatementParent(restatement);
|
|
36181
36948
|
if (parentRef && !parent) return refused(restatement, replacedExisting, MISSING_PARENT[restatement.kind](parentRef.id));
|
|
@@ -36186,6 +36953,19 @@ function applyRestatement(restatement, existing, parent) {
|
|
|
36186
36953
|
const carried = carryInto(restatement, existing, candidate);
|
|
36187
36954
|
const cleared = clearedByOmission(existing, candidate, restatement.fields);
|
|
36188
36955
|
stampLifecycle(candidate, existing, status.status);
|
|
36956
|
+
if (restatement.kind === "interface") {
|
|
36957
|
+
const restated = restatedSources(candidate.methods);
|
|
36958
|
+
if (restated.length) return refused(restatement, replacedExisting, `${restatedSourceRefusal(String(candidate.id), restated)} Nothing was written.`);
|
|
36959
|
+
}
|
|
36960
|
+
const unsigned = restatement.kind === "interface" || restatement.kind === "type" ? unsignedMethods(candidate.methods) : [];
|
|
36961
|
+
if (unsigned.length) {
|
|
36962
|
+
return refused(
|
|
36963
|
+
restatement,
|
|
36964
|
+
replacedExisting,
|
|
36965
|
+
`Refusing to write ${restatement.kind} "${String(candidate.id)}": ${unsigned.map((n) => `"${n}"`).join(", ")} ${unsigned.length === 1 ? "states" : "state"} neither params${restatement.kind === "interface" ? ", a signatureFrom" : ""} nor a prose signature, so nothing says what the method takes. Nothing was written.`
|
|
36966
|
+
);
|
|
36967
|
+
}
|
|
36968
|
+
const derivedNotices = deriveStatedTexts(restatement.kind, candidate);
|
|
36189
36969
|
const labelErrors = resolveLabelsOf(restatement.kind, candidate);
|
|
36190
36970
|
if (labelErrors.length) {
|
|
36191
36971
|
return refused(restatement, replacedExisting, `Unresolved narrative label references \u2014 nothing was saved:
|
|
@@ -36197,7 +36977,7 @@ function applyRestatement(restatement, existing, parent) {
|
|
|
36197
36977
|
spec: parsed.spec,
|
|
36198
36978
|
...status.status ? { status: status.status } : {},
|
|
36199
36979
|
replacedExisting,
|
|
36200
|
-
notices: existing ? rewriteNotices(restatement.kind, existing, candidate, carried, cleared) : [],
|
|
36980
|
+
notices: [...existing ? rewriteNotices(restatement.kind, existing, candidate, carried, cleared) : [], ...derivedNotices],
|
|
36201
36981
|
changedMethods: changedMethodsOf(restatement.kind, existing, candidate)
|
|
36202
36982
|
};
|
|
36203
36983
|
}
|
|
@@ -40208,8 +40988,27 @@ var getSpecOutput = {
|
|
|
40208
40988
|
}).optional().describe(
|
|
40209
40989
|
"Derived, read-only guidance for a variant-tagged component \u2014 resolved from the variant registry, not part of the spec. Never write it back."
|
|
40210
40990
|
),
|
|
40991
|
+
resolvedSignatures: import_zod11.z.array(import_zod11.z.object({
|
|
40992
|
+
method: import_zod11.z.string().describe("The contract method that takes its signature from a source."),
|
|
40993
|
+
signatureFrom: import_zod11.z.string().describe("The source it names, as the spec holds it."),
|
|
40994
|
+
signature: import_zod11.z.string().describe("The text it shows, derived from the resolved params and returns."),
|
|
40995
|
+
params: import_zod11.z.array(import_zod11.z.record(import_zod11.z.unknown())).optional().describe("The params the source supplies; absent when it supplies none (unresolved, ambiguous or chained)."),
|
|
40996
|
+
returns: import_zod11.z.string().describe("The returns the source supplies (`unknown` when it supplies none).")
|
|
40997
|
+
})).optional().describe(
|
|
40998
|
+
"Derived, read-only: for a contract whose methods take their signature from a source, each such method's RESOLVED params, returns and text. The spec carries those methods in stored form (the signatureFrom alone) so it can be re-authored from as it is; never write these back beside the source."
|
|
40999
|
+
),
|
|
40211
41000
|
...staleServerOutput
|
|
40212
41001
|
};
|
|
41002
|
+
function storedContractAnswer(loaded) {
|
|
41003
|
+
const resolvedSignatures = loaded.methods.filter((m) => m.signatureFrom !== void 0).map((m) => ({
|
|
41004
|
+
method: m.name,
|
|
41005
|
+
signatureFrom: m.signatureFrom,
|
|
41006
|
+
signature: m.signature,
|
|
41007
|
+
...m.params ? { params: m.params } : {},
|
|
41008
|
+
returns: m.returns
|
|
41009
|
+
}));
|
|
41010
|
+
return { spec: { ...loaded, methods: loaded.methods.map((m) => storedMethodSignature(m)) }, resolvedSignatures };
|
|
41011
|
+
}
|
|
40213
41012
|
var FINGERPRINT_VERSION = 1;
|
|
40214
41013
|
function schemaShape(schema, seen = /* @__PURE__ */ new Map()) {
|
|
40215
41014
|
const def = schema?._def;
|
|
@@ -40280,7 +41079,7 @@ function schemaFingerprint() {
|
|
|
40280
41079
|
implementation: schemaShape(ImplementationSpecSchema),
|
|
40281
41080
|
type: schemaShape(TypeSpecSchema)
|
|
40282
41081
|
};
|
|
40283
|
-
const registered =
|
|
41082
|
+
const registered = createBareMcpServer()._registeredTools;
|
|
40284
41083
|
const tools = [...SPEC_WRITE_TOOLS].sort().map((name) => [name, schemaShape(registered[name]?.inputSchema)]);
|
|
40285
41084
|
runningFingerprint = crypto10.createHash("sha256").update(JSON.stringify({ version: FINGERPRINT_VERSION, specs, tools })).digest("hex");
|
|
40286
41085
|
return runningFingerprint;
|
|
@@ -40384,113 +41183,7 @@ function reg(server, name, config, cb) {
|
|
|
40384
41183
|
var statusInput = import_zod11.z.enum(STATUS_VALUES).optional().describe(
|
|
40385
41184
|
"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."
|
|
40386
41185
|
);
|
|
40387
|
-
|
|
40388
|
-
function skillIdFromResourceUri(uri) {
|
|
40389
|
-
try {
|
|
40390
|
-
const u = new URL(uri);
|
|
40391
|
-
return u.host || u.pathname.replace(/^\/+/, "") || uri;
|
|
40392
|
-
} catch {
|
|
40393
|
-
return uri;
|
|
40394
|
-
}
|
|
40395
|
-
}
|
|
40396
|
-
var AGENT_BRIEF_SCHEME = "wairon-agent://";
|
|
40397
|
-
function listAgentBriefResources() {
|
|
40398
|
-
try {
|
|
40399
|
-
return resolveAgentTopology().map((a) => ({
|
|
40400
|
-
uri: `${AGENT_BRIEF_SCHEME}${a.id}`,
|
|
40401
|
-
name: a.name,
|
|
40402
|
-
description: a.description,
|
|
40403
|
-
mimeType: SKILL_RESOURCE_MIME
|
|
40404
|
-
}));
|
|
40405
|
-
} catch {
|
|
40406
|
-
return [];
|
|
40407
|
-
}
|
|
40408
|
-
}
|
|
40409
|
-
function renderAgentBriefMarkdown(brief) {
|
|
40410
|
-
const lines = [
|
|
40411
|
-
`# Agent brief: ${brief.agentId}`,
|
|
40412
|
-
"",
|
|
40413
|
-
`- **Name**: ${brief.name}`,
|
|
40414
|
-
`- **Template**: ${brief.template}`,
|
|
40415
|
-
...brief.domainRoot ? [`- **Domain root**: ${brief.domainRoot}`] : [],
|
|
40416
|
-
`- **Owned paths**: ${brief.ownedPaths.join(", ")}`,
|
|
40417
|
-
...brief.readPaths?.length ? [`- **Read paths**: ${brief.readPaths.join(", ")}`] : [],
|
|
40418
|
-
"",
|
|
40419
|
-
"## Instructions",
|
|
40420
|
-
"",
|
|
40421
|
-
brief.instructions
|
|
40422
|
-
];
|
|
40423
|
-
if (brief.variantGuidance && !brief.instructions.includes(brief.variantGuidance)) {
|
|
40424
|
-
lines.push("", "## Variant guidance", "", brief.variantGuidance);
|
|
40425
|
-
}
|
|
40426
|
-
if (brief.budget && brief.profile) {
|
|
40427
|
-
lines.push(
|
|
40428
|
-
"",
|
|
40429
|
-
"## Execution budget",
|
|
40430
|
-
"",
|
|
40431
|
-
...summarize(brief.budget, brief.profile),
|
|
40432
|
-
"",
|
|
40433
|
-
"Advisory \u2014 apply these when spawning. Map the capability tier onto your host tool's models; a tool that cannot express a field should ignore it rather than approximate it."
|
|
40434
|
-
);
|
|
40435
|
-
}
|
|
40436
|
-
return `${lines.join("\n")}
|
|
40437
|
-
`;
|
|
40438
|
-
}
|
|
40439
|
-
function registerSkillResources(server, listChanged) {
|
|
40440
|
-
server.server.registerCapabilities({ resources: listChanged ? { listChanged: true } : {} });
|
|
40441
|
-
server.server.setRequestHandler(import_types12.ListResourcesRequestSchema, () => ({
|
|
40442
|
-
resources: [
|
|
40443
|
-
...listResources().map((d) => ({
|
|
40444
|
-
uri: d.resourceUri,
|
|
40445
|
-
name: d.name,
|
|
40446
|
-
description: d.description,
|
|
40447
|
-
mimeType: SKILL_RESOURCE_MIME
|
|
40448
|
-
})),
|
|
40449
|
-
...listAgentBriefResources()
|
|
40450
|
-
]
|
|
40451
|
-
}));
|
|
40452
|
-
server.server.setRequestHandler(import_types12.ReadResourceRequestSchema, (request) => {
|
|
40453
|
-
const uri = request.params.uri;
|
|
40454
|
-
if (uri.startsWith(AGENT_BRIEF_SCHEME)) {
|
|
40455
|
-
try {
|
|
40456
|
-
const brief = composeAgentBrief(uri.slice(AGENT_BRIEF_SCHEME.length));
|
|
40457
|
-
return { contents: [{ uri, mimeType: SKILL_RESOURCE_MIME, text: renderAgentBriefMarkdown(brief) }] };
|
|
40458
|
-
} catch (e) {
|
|
40459
|
-
throw new import_types12.McpError(import_types12.ErrorCode.InvalidParams, e instanceof Error ? e.message : String(e));
|
|
40460
|
-
}
|
|
40461
|
-
}
|
|
40462
|
-
try {
|
|
40463
|
-
const content = readResource(skillIdFromResourceUri(uri));
|
|
40464
|
-
return { contents: [{ uri, mimeType: SKILL_RESOURCE_MIME, text: content }] };
|
|
40465
|
-
} catch (e) {
|
|
40466
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
40467
|
-
throw new import_types12.McpError(import_types12.ErrorCode.InvalidParams, message);
|
|
40468
|
-
}
|
|
40469
|
-
});
|
|
40470
|
-
}
|
|
40471
|
-
function registerSkillPrompts(server, listChanged) {
|
|
40472
|
-
server.server.registerCapabilities({ prompts: listChanged ? { listChanged: true } : {} });
|
|
40473
|
-
server.server.setRequestHandler(import_types12.ListPromptsRequestSchema, () => ({
|
|
40474
|
-
prompts: listResources().map((d) => ({
|
|
40475
|
-
name: d.id,
|
|
40476
|
-
title: d.name,
|
|
40477
|
-
description: d.description
|
|
40478
|
-
}))
|
|
40479
|
-
}));
|
|
40480
|
-
server.server.setRequestHandler(import_types12.GetPromptRequestSchema, (request) => {
|
|
40481
|
-
const name = request.params.name;
|
|
40482
|
-
try {
|
|
40483
|
-
const content = readResource(name);
|
|
40484
|
-
return {
|
|
40485
|
-
description: `The wairon "${name}" skill.`,
|
|
40486
|
-
messages: [{ role: "user", content: { type: "text", text: content } }]
|
|
40487
|
-
};
|
|
40488
|
-
} catch (e) {
|
|
40489
|
-
throw new import_types12.McpError(import_types12.ErrorCode.InvalidParams, e instanceof Error ? e.message : String(e));
|
|
40490
|
-
}
|
|
40491
|
-
});
|
|
40492
|
-
}
|
|
40493
|
-
function createMcpServer(options = {}) {
|
|
41186
|
+
function createBareMcpServer(options = {}) {
|
|
40494
41187
|
const server = new import_mcp.McpServer({
|
|
40495
41188
|
name: "wairon",
|
|
40496
41189
|
version: WAIRON_VERSION
|
|
@@ -41093,19 +41786,25 @@ ${renderChangeReport(report2)}`,
|
|
|
41093
41786
|
}
|
|
41094
41787
|
}
|
|
41095
41788
|
);
|
|
41789
|
+
const methodParamItem = import_zod11.z.object({
|
|
41790
|
+
name: import_zod11.z.string(),
|
|
41791
|
+
type: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The parameter's type")),
|
|
41792
|
+
description: import_zod11.z.string().optional(),
|
|
41793
|
+
optional: import_zod11.z.boolean().optional().describe(
|
|
41794
|
+
'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.'
|
|
41795
|
+
)
|
|
41796
|
+
}).strict();
|
|
41096
41797
|
const interfaceMethodShape = {
|
|
41097
41798
|
name: import_zod11.z.string(),
|
|
41098
41799
|
description: import_zod11.z.string(),
|
|
41099
|
-
signature: import_zod11.z.string()
|
|
41100
|
-
|
|
41101
|
-
|
|
41102
|
-
|
|
41103
|
-
|
|
41104
|
-
|
|
41105
|
-
|
|
41106
|
-
|
|
41107
|
-
)
|
|
41108
|
-
}).strict()).optional().describe("Structured parameters \u2014 authoritative for type checking (the prose signature becomes display-only). Strongly preferred."),
|
|
41800
|
+
signature: import_zod11.z.string().optional().describe(
|
|
41801
|
+
"Prose signature \u2014 only for a method WITHOUT params. With params the server derives and writes the text (`name(a: T, b?: U): R`) and ignores this one (a notice names one that differed); a method with a signatureFrom states none."
|
|
41802
|
+
),
|
|
41803
|
+
returns: import_zod11.z.string().optional().describe(TYPE_REF_GRAMMAR("The type the method answers with. Required unless signatureFrom is set, whose source supplies it")),
|
|
41804
|
+
signatureFrom: import_zod11.z.string().min(1).optional().describe(
|
|
41805
|
+
"Take this method's params and returns from ONE source instead of stating them: a signature type id (`billing.change_listener`, `alias::name`) or a contract method `component.method` whose component this one names in dependsOn or owns (no chains). State it ALONE \u2014 params or returns beside it are refused (SIGNATURE_SOURCE_RESTATED). A value that names both a method and a signature type is ambiguous: qualify it."
|
|
41806
|
+
),
|
|
41807
|
+
params: import_zod11.z.array(methodParamItem).optional().describe("Structured parameters \u2014 authoritative for type checking, and the signature text is derived from them. Strongly preferred."),
|
|
41109
41808
|
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)"),
|
|
41110
41809
|
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"),
|
|
41111
41810
|
invokedBy: import_zod11.z.object({
|
|
@@ -41133,7 +41832,7 @@ ${renderChangeReport(report2)}`,
|
|
|
41133
41832
|
server,
|
|
41134
41833
|
"sdd_define_interface",
|
|
41135
41834
|
{
|
|
41136
|
-
description: "Define an L3 Contract / Interface with method signatures for a component.
|
|
41835
|
+
description: "Define an L3 Contract / Interface with method signatures for a component. Each method states its signature ONE of three ways: structured `params` with `returns` (strongly preferred \u2014 authoritative for type checking, and the signature text is then DERIVED and written by the server; a text you pass is ignored and a notice names one that differed), a `signatureFrom` naming its source \u2014 a signature type, or `component.method` along a dependsOn/owns edge \u2014 with neither params nor returns (both together are refused, SIGNATURE_SOURCE_RESTATED), or, for a method without params, a prose `signature` with `returns`. 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.",
|
|
41137
41836
|
inputSchema: interfaceInput,
|
|
41138
41837
|
outputSchema: specWriteReceiptOutput
|
|
41139
41838
|
},
|
|
@@ -41341,7 +42040,7 @@ ${renderChangeReport(report2)}`,
|
|
|
41341
42040
|
}
|
|
41342
42041
|
);
|
|
41343
42042
|
const typeInput = {
|
|
41344
|
-
kind: import_zod11.z.enum(["entity", "value-object"]).describe("entity (owned by a subsystem)
|
|
42043
|
+
kind: import_zod11.z.enum(["entity", "value-object", "signature"]).describe("entity (owned by a subsystem), value-object (often system-level shared), or signature \u2014 a named function type: params and returns, nothing else"),
|
|
41345
42044
|
id: import_zod11.z.string().describe("Lowercase identifier"),
|
|
41346
42045
|
name: import_zod11.z.string().describe("Human-readable name"),
|
|
41347
42046
|
description: import_zod11.z.string().optional(),
|
|
@@ -41357,7 +42056,8 @@ ${renderChangeReport(report2)}`,
|
|
|
41357
42056
|
}).strict()).optional().describe('Data fields (type is a primitive or a qualified type id, e.g. "billing.Invoice")'),
|
|
41358
42057
|
methods: import_zod11.z.array(import_zod11.z.object({
|
|
41359
42058
|
name: import_zod11.z.string(),
|
|
41360
|
-
signature: import_zod11.z.string(),
|
|
42059
|
+
signature: import_zod11.z.string().optional().describe("Prose signature \u2014 only for a method WITHOUT params; with params the server derives and writes the text"),
|
|
42060
|
+
params: import_zod11.z.array(methodParamItem).optional().describe("Structured parameters \u2014 authoritative for type checking; the signature text is derived from them"),
|
|
41361
42061
|
returns: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The type the method answers with")),
|
|
41362
42062
|
description: import_zod11.z.string().optional(),
|
|
41363
42063
|
sourcePath: import_zod11.z.string().optional().describe("Source file realizing this method when the type's own sourcePath does not hold it \u2014 a pure type method often lives apart from the declaration"),
|
|
@@ -41372,18 +42072,20 @@ ${renderChangeReport(report2)}`,
|
|
|
41372
42072
|
table: import_zod11.z.string().optional().describe("Optional database table name for table-schema types"),
|
|
41373
42073
|
linkedEntity: import_zod11.z.string().optional().describe("Optional logical entity id represented by this table-schema type"),
|
|
41374
42074
|
sourcePath: import_zod11.z.string().optional().describe("Source file holding the declaration of this type (project-relative). Naming one turns the type into a claim on code: the file must resolve and the declaration must be anchored in it (UNREALIZED_TYPE)"),
|
|
41375
|
-
symbol: import_zod11.z.string().optional().describe('Code-level name realizing the declaration when it differs from name, e.g. a type named "Invoice Line" declared as InvoiceLine')
|
|
42075
|
+
symbol: import_zod11.z.string().optional().describe('Code-level name realizing the declaration when it differs from name, e.g. a type named "Invoice Line" declared as InvoiceLine'),
|
|
42076
|
+
params: import_zod11.z.array(methodParamItem).optional().describe("kind signature only: the function type's parameters, in declared order (SIGNATURE_TYPE_MEMBERS on any other kind)"),
|
|
42077
|
+
returns: import_zod11.z.string().optional().describe(TYPE_REF_GRAMMAR("kind signature only, and required there: the function type's one output"))
|
|
41376
42078
|
};
|
|
41377
42079
|
const typeInputFields = Object.keys(typeInput);
|
|
41378
42080
|
reg(
|
|
41379
42081
|
server,
|
|
41380
42082
|
"sdd_add_type",
|
|
41381
42083
|
{
|
|
41382
|
-
description: "Define an entity or value-object
|
|
42084
|
+
description: "Define a type: an entity or value-object (the data components operate on), or a signature \u2014 a named function type. Entities are owned by a subsystem; shared value objects and signatures 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 \u2014 and a type method may carry structured params, which then derive its signature text as a contract method's do. A signature carries top-level params and returns and nothing else (no fields, methods or invariants \u2014 SIGNATURE_TYPE_MEMBERS); a contract method takes it by naming it as its signatureFrom, and a param may be typed by one (a callback). A type may also CLAIM code: sourcePath names the file holding its declaration (and each method may name its own), symbol binds the code-level name when it differs \u2014 the file must then resolve and the declaration must be anchored in it. An owning subsystem the tree does not have is refused, writing nothing, exactly as a component under an unknown subsystem is. Re-defining an existing id REPLACES fields/methods/invariants and restates sourcePath/symbol (an omitted list or path 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.",
|
|
41383
42085
|
inputSchema: typeInput,
|
|
41384
42086
|
outputSchema: specWriteReceiptOutput
|
|
41385
42087
|
},
|
|
41386
|
-
({ kind, id, name, description, subsystem, group, fields, methods, componentClass, invariants, database, table, linkedEntity, sourcePath, symbol }) => {
|
|
42088
|
+
({ kind, id, name, description, subsystem, group, fields, methods, componentClass, invariants, database, table, linkedEntity, sourcePath, symbol, params, returns }) => {
|
|
41387
42089
|
try {
|
|
41388
42090
|
const spec = {
|
|
41389
42091
|
kind,
|
|
@@ -41407,7 +42109,9 @@ ${renderChangeReport(report2)}`,
|
|
|
41407
42109
|
...table ? { table } : {},
|
|
41408
42110
|
...linkedEntity ? { linkedEntity } : {},
|
|
41409
42111
|
...sourcePath ? { sourcePath } : {},
|
|
41410
|
-
...symbol ? { symbol } : {}
|
|
42112
|
+
...symbol ? { symbol } : {},
|
|
42113
|
+
...params ? { params } : {},
|
|
42114
|
+
...returns ? { returns } : {}
|
|
41411
42115
|
};
|
|
41412
42116
|
const receipt = writeSpec({ kind: "type", spec, fields: typeInputFields });
|
|
41413
42117
|
return writeReceipt(
|
|
@@ -41465,7 +42169,7 @@ ${renderChangeReport(report2)}`,
|
|
|
41465
42169
|
server,
|
|
41466
42170
|
"sdd_get_spec",
|
|
41467
42171
|
{
|
|
41468
|
-
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
|
|
42172
|
+
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. A contract's methods come back in their STORED form \u2014 a method that takes its signature from a source carries its signatureFrom, not the params the loader resolves into it \u2014 so the answer can be re-authored from as it is; the resolved params, returns and text of each such method come back as a derived, read-only "resolvedSignatures" marker. The structured content carries the same answer with the derived markers KEPT SEPARATE from the stored spec ({kind, id, spec, partialResult?, variantGuidance?, resolvedSignatures?}), so nothing derived can be mistaken for something stored; the text block folds them in as it always has.`,
|
|
41469
42173
|
inputSchema: {
|
|
41470
42174
|
kind: import_zod11.z.enum(["system", "subsystem", "component", "interface", "implementation", "type"]).describe("The kind of specification"),
|
|
41471
42175
|
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")'),
|
|
@@ -41498,6 +42202,12 @@ ${renderChangeReport(report2)}`,
|
|
|
41498
42202
|
break;
|
|
41499
42203
|
}
|
|
41500
42204
|
if (!result) return errText(`Spec of kind "${kind}" with ID "${id}" does not exist.`);
|
|
42205
|
+
let resolvedSignatures = [];
|
|
42206
|
+
if (kind === "interface") {
|
|
42207
|
+
const answer = storedContractAnswer(result);
|
|
42208
|
+
result = answer.spec;
|
|
42209
|
+
resolvedSignatures = answer.resolvedSignatures;
|
|
42210
|
+
}
|
|
41501
42211
|
if (methods !== void 0) {
|
|
41502
42212
|
const declared = result.methods;
|
|
41503
42213
|
if (!Array.isArray(declared)) {
|
|
@@ -41519,19 +42229,23 @@ ${renderChangeReport(report2)}`,
|
|
|
41519
42229
|
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.`
|
|
41520
42230
|
};
|
|
41521
42231
|
result = { ...result, methods: kept };
|
|
42232
|
+
resolvedSignatures = resolvedSignatures.filter((r) => methods.includes(r.method));
|
|
41522
42233
|
}
|
|
41523
42234
|
const guidance = kind === "component" ? resolveComponentVariantGuidance(result) : null;
|
|
42235
|
+
const resolved = resolvedSignatures.length > 0 ? { resolvedSignatures } : {};
|
|
41524
42236
|
const folded = {
|
|
41525
42237
|
...result,
|
|
41526
42238
|
...partial2 ? { partialResult: partial2 } : {},
|
|
41527
|
-
...guidance ? { variantGuidance: guidance } : {}
|
|
42239
|
+
...guidance ? { variantGuidance: guidance } : {},
|
|
42240
|
+
...resolved
|
|
41528
42241
|
};
|
|
41529
42242
|
return structured(JSON.stringify(folded, null, 2), {
|
|
41530
42243
|
kind,
|
|
41531
42244
|
id,
|
|
41532
42245
|
spec: result,
|
|
41533
42246
|
...partial2 ? { partialResult: partial2 } : {},
|
|
41534
|
-
...guidance ? { variantGuidance: guidance } : {}
|
|
42247
|
+
...guidance ? { variantGuidance: guidance } : {},
|
|
42248
|
+
...resolved
|
|
41535
42249
|
});
|
|
41536
42250
|
} catch (e) {
|
|
41537
42251
|
return errText(String(e));
|
|
@@ -41670,8 +42384,6 @@ ${testsBlock}` : ""}`, deletion);
|
|
|
41670
42384
|
}
|
|
41671
42385
|
}
|
|
41672
42386
|
);
|
|
41673
|
-
registerSkillResources(server, !options.hostedTools);
|
|
41674
|
-
registerSkillPrompts(server, !options.hostedTools);
|
|
41675
42387
|
try {
|
|
41676
42388
|
const chainingParent = resolveChainingParent();
|
|
41677
42389
|
if (chainingParent) {
|
|
@@ -41682,105 +42394,8 @@ ${testsBlock}` : ""}`, deletion);
|
|
|
41682
42394
|
}
|
|
41683
42395
|
} catch {
|
|
41684
42396
|
}
|
|
41685
|
-
advertiseHostedTools(server, options);
|
|
41686
42397
|
return server;
|
|
41687
42398
|
}
|
|
41688
|
-
function advertiseHostedTools(server, options) {
|
|
41689
|
-
if (options.hostedTools) {
|
|
41690
|
-
const hostedStub = () => errText("This hosted tool is dispatched by the hosting data plane before reaching the MCP server; it is unavailable outside a hosted request.");
|
|
41691
|
-
reg(server, "sdd_host_lock_project", {
|
|
41692
|
-
description: "Hosted project lifecycle (execute-primary): LOCK the bound project (validate-as-complete gate + commit-scoped lock record). Executes directly when your resolved permission is yes and returns the completed outcome; when it is approval, a pending approval request is created instead (await it with sdd_host_await_approval).",
|
|
41693
|
-
inputSchema: {}
|
|
41694
|
-
}, hostedStub);
|
|
41695
|
-
reg(server, "sdd_host_initialize_project", {
|
|
41696
|
-
description: "Hosted project lifecycle (execute-primary): initialize a new hosted project into its REQUIRED owner organization unit (with an optional profile selection). Executes directly when your resolved permission is yes; when it is approval, a pending approval request is created instead.",
|
|
41697
|
-
inputSchema: {
|
|
41698
|
-
id: import_zod11.z.string().describe("Requested project id"),
|
|
41699
|
-
displayName: import_zod11.z.string().optional(),
|
|
41700
|
-
description: import_zod11.z.string().optional(),
|
|
41701
|
-
ownerUnitId: import_zod11.z.string().describe("REQUIRED organization unit that owns the new project (every project is placed at creation)"),
|
|
41702
|
-
environment: import_zod11.z.string().optional()
|
|
41703
|
-
}
|
|
41704
|
-
}, hostedStub);
|
|
41705
|
-
reg(server, "sdd_host_get_approval_status", {
|
|
41706
|
-
description: "Hosted project lifecycle: read the status of one of your approval requests.",
|
|
41707
|
-
inputSchema: { requestId: import_zod11.z.string() }
|
|
41708
|
-
}, hostedStub);
|
|
41709
|
-
reg(server, "sdd_host_await_approval", {
|
|
41710
|
-
description: "Hosted project lifecycle: long-poll one of YOUR approval requests until it is decided (approved requests auto-execute, so an approval resolves as completed) or the timeout elapses. Returns the request in its current state.",
|
|
41711
|
-
inputSchema: {
|
|
41712
|
-
requestId: import_zod11.z.string(),
|
|
41713
|
-
timeoutSeconds: import_zod11.z.number().optional().describe("How long to wait server-side (clamped; 0 returns the current state immediately)")
|
|
41714
|
-
}
|
|
41715
|
-
}, hostedStub);
|
|
41716
|
-
reg(server, "sdd_landscape_list_reachable_projects", {
|
|
41717
|
-
description: "Hosted landscape: the projects reachable from the BOUND project through ACTIVE cross-project relations (directional, relations-only), each with the relation ids/kinds and target public interface ids.",
|
|
41718
|
-
inputSchema: {}
|
|
41719
|
-
}, hostedStub);
|
|
41720
|
-
reg(server, "sdd_landscape_list_reachable_project_interfaces", {
|
|
41721
|
-
description: "Hosted landscape: redacted, audience-filtered public interface summaries of one reachable target project (Forbidden outside the reachable set; private by default).",
|
|
41722
|
-
inputSchema: { projectId: import_zod11.z.string().describe("The reachable target project id") }
|
|
41723
|
-
}, hostedStub);
|
|
41724
|
-
reg(server, "sdd_landscape_list_visible_surfaces", {
|
|
41725
|
-
description: "Hosted landscape: the visibility-resolved discovery catalog for the BOUND project \u2014 every target the organization unit graph exposes to it (open-within-tenant, closed groups hidden, exposeTo grants honored), with audience distance and audience-filtered summaries. No relation required.",
|
|
41726
|
-
inputSchema: {}
|
|
41727
|
-
}, hostedStub);
|
|
41728
|
-
reg(server, "sdd_landscape_get_project_surface", {
|
|
41729
|
-
description: `Hosted landscape: fetch a visible target project's CONTRACT-GRADE surface snapshot (full method contracts, dispatch tables, type closure) at your audience-distance ceiling, origin "exchanged" \u2014 save it under .wai/surfaces/ (wairon surface import) so your adapters validate against the declared contract.`,
|
|
41730
|
-
inputSchema: { projectId: import_zod11.z.string().describe("The visible target project id") }
|
|
41731
|
-
}, hostedStub);
|
|
41732
|
-
reg(server, "sdd_host_pack_list", {
|
|
41733
|
-
description: "Hosted project ops: list the BOUND project's registered extension packs (requires project:read over it).",
|
|
41734
|
-
inputSchema: {}
|
|
41735
|
-
}, hostedStub);
|
|
41736
|
-
reg(server, "sdd_host_pack_install", {
|
|
41737
|
-
description: "Hosted project ops: install a DECLARATIVE extension pack (profiles + language/platform tables \u2014 never rule/code packs) into the BOUND project (requires project:admin over it).",
|
|
41738
|
-
inputSchema: {
|
|
41739
|
-
name: import_zod11.z.string().describe("Pack name (letters, digits, dot, underscore, hyphen)"),
|
|
41740
|
-
content: import_zod11.z.string().describe("The declarative pack YAML content")
|
|
41741
|
-
}
|
|
41742
|
-
}, hostedStub);
|
|
41743
|
-
reg(server, "sdd_host_pack_impact", {
|
|
41744
|
-
description: "Hosted project ops: measure, writing nothing, what installing a DECLARATIVE pack (content given) or adopting the server-global pack of that name (content omitted) would change on the BOUND project \u2014 the pack's doctrine against wairon's defaults (rules loosened, raised, turned off or added; profiles and concepts added, redefined or removed), which of its profiles would govern, and the findings that change. Show it to your human before sdd_host_pack_install, which applies without it. Nothing in it is a finding: packs exist to adjust wairon's checks. Requires project:read over the project.",
|
|
41745
|
-
inputSchema: {
|
|
41746
|
-
name: import_zod11.z.string().describe("Pack name (letters, digits, dot, underscore, hyphen); the server-global pack to adopt when content is omitted"),
|
|
41747
|
-
content: import_zod11.z.string().optional().describe("The declarative pack YAML an install would upload; omitted, the server-global pack an adoption would vendor")
|
|
41748
|
-
}
|
|
41749
|
-
}, hostedStub);
|
|
41750
|
-
reg(server, "sdd_host_policy_evaluate", {
|
|
41751
|
-
description: "Hosted project ops: evaluate the BOUND project's packs and profile selection against the instance pack policy \u2014 compliance without side effects (requires project:write over it).",
|
|
41752
|
-
inputSchema: {}
|
|
41753
|
-
}, hostedStub);
|
|
41754
|
-
reg(server, "sdd_host_policy_reconcile", {
|
|
41755
|
-
description: "Hosted project ops: reconcile the BOUND project against the instance pack policy \u2014 under auto_reconcile enforcement the missing required/default declarative packs are applied (requires project:write over it).",
|
|
41756
|
-
inputSchema: {}
|
|
41757
|
-
}, hostedStub);
|
|
41758
|
-
reg(server, "sdd_host_produce", {
|
|
41759
|
-
description: "Hosted project ops: run a configured producer projection (Notion/Miro) of the BOUND project to the named target (requires project:admin over it).",
|
|
41760
|
-
inputSchema: { target: import_zod11.z.string().describe("The configured producer target (e.g. notion, miro)") }
|
|
41761
|
-
}, hostedStub);
|
|
41762
|
-
reg(server, "sdd_host_commit_project", {
|
|
41763
|
-
description: "Hosted project ops: publish a DELIBERATE, .wai/-scoped commit+push of the BOUND project's specs to its bound repository (commit = local save, push = the actual backup; a clean scope publishes nothing). The data plane binds ONE project, so there is no project argument. Requires project:write over it.",
|
|
41764
|
-
inputSchema: {
|
|
41765
|
-
subsystem: import_zod11.z.string().optional().describe("Narrow staging to .wai/specs/<subsystem>/ (a convenience \u2014 git history stays per-repo)"),
|
|
41766
|
-
message: import_zod11.z.string().optional().describe("Commit message; defaults to a timestamped wairon message")
|
|
41767
|
-
}
|
|
41768
|
-
}, hostedStub);
|
|
41769
|
-
reg(server, "sdd_host_export_tree", {
|
|
41770
|
-
description: "Hosted spec-tree transfer: pack the BOUND project's WHOLE spec tree \u2014 its own .wai plus every chained subproject \u2014 into a .waitree archive, returned as base64 with its roots, file count and state id. The migration counterpart of an import: use it to take a hosted project local, or to move it to another instance. Requires project:read over the project. Bounded by the data-plane body cap; a very large tree exports through the web download route instead. Refuses when a chained mount cannot be packed (escaping, missing, cyclic, too deep, or holding no .wai), naming every one and why, unless allowPartial is set \u2014 then the archive is built anyway and the result lists what was skipped.",
|
|
41771
|
-
inputSchema: {
|
|
41772
|
-
allowPartial: import_zod11.z.boolean().optional().describe("Build the archive even when some members cannot be packed, listing them as skipped; default false (refuse and name them)")
|
|
41773
|
-
}
|
|
41774
|
-
}, hostedStub);
|
|
41775
|
-
reg(server, "sdd_host_import_tree", {
|
|
41776
|
-
description: "Hosted spec-tree transfer: REPLACE the BOUND project's spec tree from a base64 .waitree archive. Requires project:admin over the project (strictly above project:write \u2014 this replaces the whole design, not one spec). Refuses an occupied destination unless replaceExisting is set, always refuses executable entries (rule/code packs install only through the trusted filesystem), and moves the previous tree aside to a backup whose path is returned.",
|
|
41777
|
-
inputSchema: {
|
|
41778
|
-
archiveBase64: import_zod11.z.string().describe("The .waitree archive bytes, base64-encoded"),
|
|
41779
|
-
replaceExisting: import_zod11.z.boolean().optional().describe("Replace a tree already present (backed up first); without it an occupied destination is refused")
|
|
41780
|
-
}
|
|
41781
|
-
}, hostedStub);
|
|
41782
|
-
}
|
|
41783
|
-
}
|
|
41784
42399
|
|
|
41785
42400
|
// src/index.ts
|
|
41786
42401
|
function loadProjectConfig3() {
|
|
@@ -41889,6 +42504,10 @@ function loadProjectConfig3() {
|
|
|
41889
42504
|
RETIRED_STEREOTYPES,
|
|
41890
42505
|
RegistrySchema,
|
|
41891
42506
|
RequirementItemSchema,
|
|
42507
|
+
ResolvedInterfaceSpecSchema,
|
|
42508
|
+
ResolvedMethodSignatureSchema,
|
|
42509
|
+
ResolvedTypeMethodSchema,
|
|
42510
|
+
ResolvedTypeSpecSchema,
|
|
41892
42511
|
RulesConfigSchema,
|
|
41893
42512
|
SCAN_EXCLUDE_DIRS,
|
|
41894
42513
|
SDD_RULES,
|
|
@@ -41900,6 +42519,8 @@ function loadProjectConfig3() {
|
|
|
41900
42519
|
SURFACE_AUDIENCES,
|
|
41901
42520
|
SpecIdSchema,
|
|
41902
42521
|
SpecStatusSchema,
|
|
42522
|
+
StoredMethodSignatureSchema,
|
|
42523
|
+
StoredTypeMethodSchema,
|
|
41903
42524
|
SubsystemSpecSchema,
|
|
41904
42525
|
SurfaceAudienceSchema,
|
|
41905
42526
|
SurfaceContractEntrySchema,
|
|
@@ -41984,7 +42605,10 @@ function loadProjectConfig3() {
|
|
|
41984
42605
|
dependencyCycles,
|
|
41985
42606
|
deregisterPackRef,
|
|
41986
42607
|
deriveExecutionProfile,
|
|
42608
|
+
deriveMethodSignature,
|
|
42609
|
+
deriveTypeSignature,
|
|
41987
42610
|
derivedDocPaths,
|
|
42611
|
+
describeProject,
|
|
41988
42612
|
detectDomainCandidates,
|
|
41989
42613
|
diagnoseProjectPacks,
|
|
41990
42614
|
diagramSetIndex,
|
|
@@ -42142,6 +42766,7 @@ function loadProjectConfig3() {
|
|
|
42142
42766
|
renameMethod,
|
|
42143
42767
|
renderDiagram,
|
|
42144
42768
|
repairForeignStepFields,
|
|
42769
|
+
repairSignatures,
|
|
42145
42770
|
repointExternal,
|
|
42146
42771
|
requiredPolicies,
|
|
42147
42772
|
resolveAgentTopology,
|
|
@@ -42153,6 +42778,7 @@ function loadProjectConfig3() {
|
|
|
42153
42778
|
resolveImport,
|
|
42154
42779
|
resolveInstalledPack,
|
|
42155
42780
|
resolveProjectExports,
|
|
42781
|
+
resolveSignatures,
|
|
42156
42782
|
resolveSubprojectForNamespace,
|
|
42157
42783
|
resolveSubsystemExports,
|
|
42158
42784
|
resolveVariantGuidance,
|
|
@@ -42174,11 +42800,15 @@ function loadProjectConfig3() {
|
|
|
42174
42800
|
setProjectRoot,
|
|
42175
42801
|
setProjectType,
|
|
42176
42802
|
settledSpecPaths,
|
|
42803
|
+
signatureFacts,
|
|
42804
|
+
signatureTypeRefs,
|
|
42177
42805
|
specPathsInScope,
|
|
42178
42806
|
splitNamespace,
|
|
42179
42807
|
stepConfigVerdict,
|
|
42180
42808
|
stepFieldsFor,
|
|
42181
42809
|
stepGraph,
|
|
42810
|
+
storedMethodSignature,
|
|
42811
|
+
storedTypeMethod,
|
|
42182
42812
|
syncContextFiles,
|
|
42183
42813
|
technologyName,
|
|
42184
42814
|
technologyTokens,
|