@nimiplatform/nimi-coding 0.2.8 → 0.3.0

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.
Files changed (205) hide show
  1. package/CHANGELOG.md +8 -92
  2. package/CONTRIBUTING.md +5 -34
  3. package/README.md +47 -350
  4. package/README.zh-CN.md +33 -287
  5. package/cli/commands/start.mjs +48 -688
  6. package/cli/commands/validate-spec-audit.mjs +1 -5
  7. package/cli/constants.mjs +9 -417
  8. package/cli/help.mjs +28 -145
  9. package/cli/index.mjs +5 -33
  10. package/cli/lib/blueprint-audit.mjs +5 -12
  11. package/cli/lib/bootstrap.mjs +0 -9
  12. package/cli/lib/contracts.mjs +0 -163
  13. package/cli/lib/doctor.mjs +155 -10
  14. package/cli/lib/entrypoints.mjs +63 -167
  15. package/cli/lib/internal/contracts-loaders.mjs +0 -85
  16. package/cli/lib/internal/contracts-parse.mjs +84 -520
  17. package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +13 -8
  18. package/cli/lib/internal/surface-taxonomy-validators.mjs +316 -66
  19. package/cli/lib/internal/validators-shared.mjs +0 -16
  20. package/cli/lib/internal/validators-spec-helpers.mjs +7 -140
  21. package/cli/lib/internal/validators-spec.mjs +103 -342
  22. package/cli/lib/shared.mjs +1 -42
  23. package/cli/lib/validators.mjs +0 -48
  24. package/cli/seeds/seed-policy.yaml +0 -3
  25. package/config/bootstrap.yaml +4 -4
  26. package/config/spec-generation-inputs.yaml +6 -12
  27. package/contracts/domain-admission.schema.yaml +3 -3
  28. package/contracts/migration-inventory.schema.yaml +12 -75
  29. package/contracts/negative-fixtures.yaml +19 -99
  30. package/contracts/placement-contract.schema.yaml +49 -78
  31. package/contracts/projection-edge.schema.yaml +37 -121
  32. package/contracts/shared-enums.yaml +4 -8
  33. package/contracts/spec-generation-inputs.schema.yaml +15 -112
  34. package/contracts/spec-layout.schema.yaml +32 -0
  35. package/contracts/surface-taxonomy.schema.yaml +43 -94
  36. package/contracts/table-family.schema.yaml +1 -1
  37. package/contracts/tracked-output-admission.schema.yaml +13 -66
  38. package/methodology/core.yaml +33 -25
  39. package/methodology/four-closure-policy.yaml +18 -26
  40. package/methodology/role-separation-policy.yaml +21 -27
  41. package/methodology/spec-reconstruction.yaml +17 -34
  42. package/package.json +2 -4
  43. package/spec/_meta/spec-tree-model.yaml +5 -101
  44. package/spec/product-scope.yaml +25 -57
  45. package/adapters/README.md +0 -25
  46. package/adapters/claude/README.md +0 -89
  47. package/adapters/claude/profile.yaml +0 -70
  48. package/adapters/codex/README.md +0 -53
  49. package/adapters/codex/profile.yaml +0 -78
  50. package/adapters/oh-my-codex/README.md +0 -184
  51. package/adapters/oh-my-codex/profile.yaml +0 -46
  52. package/cli/commands/admit-high-risk-decision.mjs +0 -108
  53. package/cli/commands/audit-sweep.mjs +0 -364
  54. package/cli/commands/closeout.mjs +0 -186
  55. package/cli/commands/decide-high-risk-execution.mjs +0 -124
  56. package/cli/commands/handoff.mjs +0 -123
  57. package/cli/commands/ingest-high-risk-execution.mjs +0 -95
  58. package/cli/commands/review-high-risk-execution.mjs +0 -95
  59. package/cli/commands/sweep-design.mjs +0 -295
  60. package/cli/commands/sweep.mjs +0 -22
  61. package/cli/commands/topic-formatters.mjs +0 -382
  62. package/cli/commands/topic-goal.mjs +0 -33
  63. package/cli/commands/topic-options-shared.mjs +0 -27
  64. package/cli/commands/topic-options-workflow.mjs +0 -767
  65. package/cli/commands/topic-options.mjs +0 -626
  66. package/cli/commands/topic-runner.mjs +0 -169
  67. package/cli/commands/topic.mjs +0 -795
  68. package/cli/commands/validate-acceptance.mjs +0 -5
  69. package/cli/commands/validate-execution-packet.mjs +0 -5
  70. package/cli/commands/validate-orchestration-state.mjs +0 -5
  71. package/cli/commands/validate-prompt.mjs +0 -5
  72. package/cli/commands/validate-worker-output.mjs +0 -5
  73. package/cli/lib/adapter-profiles.mjs +0 -403
  74. package/cli/lib/audit-execution.mjs +0 -52
  75. package/cli/lib/audit-sweep-runtime/admissions.mjs +0 -508
  76. package/cli/lib/audit-sweep-runtime/audit-validity.mjs +0 -356
  77. package/cli/lib/audit-sweep-runtime/chunks.mjs +0 -697
  78. package/cli/lib/audit-sweep-runtime/claude-auditor.mjs +0 -658
  79. package/cli/lib/audit-sweep-runtime/closeout.mjs +0 -144
  80. package/cli/lib/audit-sweep-runtime/codex-auditor-evidence.mjs +0 -654
  81. package/cli/lib/audit-sweep-runtime/codex-auditor.mjs +0 -527
  82. package/cli/lib/audit-sweep-runtime/common.mjs +0 -341
  83. package/cli/lib/audit-sweep-runtime/coverage-quality.mjs +0 -172
  84. package/cli/lib/audit-sweep-runtime/evidence-assignment.mjs +0 -155
  85. package/cli/lib/audit-sweep-runtime/format.mjs +0 -57
  86. package/cli/lib/audit-sweep-runtime/ingest.mjs +0 -486
  87. package/cli/lib/audit-sweep-runtime/inventory-spec-chunks.mjs +0 -425
  88. package/cli/lib/audit-sweep-runtime/inventory.mjs +0 -798
  89. package/cli/lib/audit-sweep-runtime/ledger.mjs +0 -315
  90. package/cli/lib/audit-sweep-runtime/p0p1-profile.mjs +0 -101
  91. package/cli/lib/audit-sweep-runtime/remediation.mjs +0 -349
  92. package/cli/lib/audit-sweep-runtime/rerun.mjs +0 -129
  93. package/cli/lib/audit-sweep-runtime/risk-budget.mjs +0 -300
  94. package/cli/lib/audit-sweep-runtime/status.mjs +0 -62
  95. package/cli/lib/audit-sweep-runtime/validators-ledger.mjs +0 -215
  96. package/cli/lib/audit-sweep-runtime/validators.mjs +0 -797
  97. package/cli/lib/audit-sweep.mjs +0 -19
  98. package/cli/lib/authority-convergence.mjs +0 -720
  99. package/cli/lib/closeout.mjs +0 -732
  100. package/cli/lib/codex-sdk-runner.mjs +0 -76
  101. package/cli/lib/external-execution.mjs +0 -101
  102. package/cli/lib/handoff.mjs +0 -812
  103. package/cli/lib/high-risk-admission.mjs +0 -512
  104. package/cli/lib/high-risk-decision.mjs +0 -353
  105. package/cli/lib/high-risk-ingest.mjs +0 -321
  106. package/cli/lib/high-risk-review.mjs +0 -267
  107. package/cli/lib/internal/contracts-parse-high-risk.mjs +0 -131
  108. package/cli/lib/internal/contracts-validators.mjs +0 -399
  109. package/cli/lib/internal/doctor-bootstrap-surface.mjs +0 -406
  110. package/cli/lib/internal/doctor-delegated-surface.mjs +0 -256
  111. package/cli/lib/internal/doctor-finalize.mjs +0 -383
  112. package/cli/lib/internal/doctor-format.mjs +0 -286
  113. package/cli/lib/internal/doctor-inspectors.mjs +0 -327
  114. package/cli/lib/internal/doctor-state.mjs +0 -205
  115. package/cli/lib/internal/validators-artifacts.mjs +0 -515
  116. package/cli/lib/sweep-design-runtime/common.mjs +0 -246
  117. package/cli/lib/sweep-design-runtime/engine.mjs +0 -733
  118. package/cli/lib/sweep-design-runtime/fix-topic.mjs +0 -414
  119. package/cli/lib/sweep-design-runtime/lifecycle.mjs +0 -54
  120. package/cli/lib/sweep-design-runtime/results.mjs +0 -324
  121. package/cli/lib/sweep-design.mjs +0 -8
  122. package/cli/lib/topic-artifacts.mjs +0 -186
  123. package/cli/lib/topic-authority-coverage.mjs +0 -73
  124. package/cli/lib/topic-closeout.mjs +0 -560
  125. package/cli/lib/topic-common.mjs +0 -404
  126. package/cli/lib/topic-decisions.mjs +0 -332
  127. package/cli/lib/topic-draft-packets.mjs +0 -167
  128. package/cli/lib/topic-execution.mjs +0 -533
  129. package/cli/lib/topic-goal.mjs +0 -440
  130. package/cli/lib/topic-ledger.mjs +0 -281
  131. package/cli/lib/topic-lifecycle-artifacts.mjs +0 -173
  132. package/cli/lib/topic-root-validation.mjs +0 -288
  133. package/cli/lib/topic-runner-commands.mjs +0 -174
  134. package/cli/lib/topic-runner-deferral.mjs +0 -532
  135. package/cli/lib/topic-runner-stale-gates.mjs +0 -114
  136. package/cli/lib/topic-runner-validation.mjs +0 -138
  137. package/cli/lib/topic-runner.mjs +0 -727
  138. package/cli/lib/topic-scaffold.mjs +0 -252
  139. package/cli/lib/topic-waves.mjs +0 -403
  140. package/cli/lib/topic.mjs +0 -81
  141. package/config/audit-execution-artifacts.yaml +0 -20
  142. package/config/external-execution-artifacts.yaml +0 -16
  143. package/config/host-adapter.yaml +0 -30
  144. package/config/host-profile.yaml +0 -29
  145. package/config/installer-evidence.yaml +0 -31
  146. package/config/skill-installer.yaml +0 -23
  147. package/config/skill-manifest.yaml +0 -48
  148. package/config/skills.yaml +0 -30
  149. package/contracts/acceptance.schema.yaml +0 -16
  150. package/contracts/admission-checklist.schema.yaml +0 -15
  151. package/contracts/audit-chunk.schema.yaml +0 -123
  152. package/contracts/audit-closeout.schema.yaml +0 -51
  153. package/contracts/audit-finding.schema.yaml +0 -61
  154. package/contracts/audit-ledger.schema.yaml +0 -138
  155. package/contracts/audit-plan.schema.yaml +0 -138
  156. package/contracts/audit-remediation-map.schema.yaml +0 -52
  157. package/contracts/audit-rerun.schema.yaml +0 -31
  158. package/contracts/audit-sweep-result.yaml +0 -53
  159. package/contracts/authority-convergence-audit.schema.yaml +0 -19
  160. package/contracts/closeout.schema.yaml +0 -25
  161. package/contracts/decision-review.schema.yaml +0 -16
  162. package/contracts/doc-spec-audit-result.yaml +0 -19
  163. package/contracts/execution-packet.schema.yaml +0 -49
  164. package/contracts/external-host-compatibility.yaml +0 -22
  165. package/contracts/forbidden-shortcuts.catalog.yaml +0 -23
  166. package/contracts/high-risk-admission.schema.yaml +0 -23
  167. package/contracts/high-risk-execution-result.yaml +0 -20
  168. package/contracts/orchestration-state.schema.yaml +0 -41
  169. package/contracts/overflow-continuation.schema.yaml +0 -12
  170. package/contracts/packet.schema.yaml +0 -30
  171. package/contracts/pending-note.schema.yaml +0 -17
  172. package/contracts/prompt.schema.yaml +0 -12
  173. package/contracts/remediation.schema.yaml +0 -16
  174. package/contracts/result.schema.yaml +0 -24
  175. package/contracts/spec-reconstruction-result.yaml +0 -41
  176. package/contracts/sweep-design-result.yaml +0 -349
  177. package/contracts/topic-goal.schema.yaml +0 -87
  178. package/contracts/topic-run-ledger.schema.yaml +0 -72
  179. package/contracts/topic-step-decision.schema.yaml +0 -45
  180. package/contracts/topic.schema.yaml +0 -65
  181. package/contracts/true-close.schema.yaml +0 -15
  182. package/contracts/wave.schema.yaml +0 -29
  183. package/contracts/worker-output.schema.yaml +0 -15
  184. package/contracts/workflow-consumer.schema.yaml +0 -110
  185. package/methodology/audit-sweep-p0p1-recall.yaml +0 -45
  186. package/methodology/authority-convergence-policy.yaml +0 -42
  187. package/methodology/overflow-continuation-policy.yaml +0 -14
  188. package/methodology/skill-exchange-projection.yaml +0 -114
  189. package/methodology/skill-handoff.yaml +0 -34
  190. package/methodology/skill-installer-result.yaml +0 -27
  191. package/methodology/skill-installer-summary-projection.yaml +0 -181
  192. package/methodology/skill-runtime.yaml +0 -23
  193. package/methodology/spec-target-truth-profile.yaml +0 -46
  194. package/methodology/topic-lifecycle-report.yaml +0 -144
  195. package/methodology/topic-lifecycle.yaml +0 -37
  196. package/methodology/topic-naming-ontology.yaml +0 -21
  197. package/methodology/topic-ontology.yaml +0 -38
  198. package/methodology/topic-validation-policy.yaml +0 -9
  199. package/methodology/wave-dag-policy.yaml +0 -14
  200. package/spec/_meta/command-gating-matrix.yaml +0 -143
  201. package/spec/_meta/generate-drift-migration-checklist.yaml +0 -137
  202. package/spec/_meta/governance-routing-cutover-checklist.yaml +0 -35
  203. package/spec/_meta/phase2-impacted-surface-matrix.yaml +0 -44
  204. package/spec/_meta/spec-authority-cutover-readiness.yaml +0 -102
  205. package/spec/bootstrap-state.yaml +0 -99
@@ -1,406 +0,0 @@
1
- import path from "node:path";
2
-
3
- import {
4
- BLUEPRINT_REFERENCE_REF,
5
- COMMAND_GATING_MATRIX_REF,
6
- LOCAL_GITIGNORE_ENTRIES,
7
- PACKAGE_NAME,
8
- REQUIRED_LOCAL_DIRS,
9
- SPEC_GENERATION_AUDIT_CONTRACT_REF,
10
- SPEC_GENERATION_AUDIT_REF,
11
- SPEC_GENERATION_INPUTS_CONTRACT_REF,
12
- SPEC_GENERATION_INPUTS_REF,
13
- SPEC_TREE_MODEL_REF,
14
- } from "../../constants.mjs";
15
- import { getBootstrapSeedEntries } from "../../seeds/bootstrap.mjs";
16
- import { inspectBootstrapCompatibility } from "../bootstrap.mjs";
17
- import {
18
- findCommandGatingRule,
19
- loadBlueprintReference,
20
- loadCommandGatingMatrix,
21
- loadSpecGenerationAuditContract,
22
- loadSpecGenerationInputsConfig,
23
- loadSpecGenerationInputsContract,
24
- loadSpecTreeModelContract,
25
- } from "../contracts.mjs";
26
- import { pathExists, readTextIfFile } from "../fs-helpers.mjs";
27
- import { validateSpecAudit } from "../validators.mjs";
28
- import {
29
- readYamlScalar,
30
- } from "../yaml-helpers.mjs";
31
- import {
32
- buildCheck,
33
- createDoctorMissingRootResult,
34
- emptySpecGenerationAudit,
35
- } from "./doctor-state.mjs";
36
- import {
37
- inspectBootstrapStateContract,
38
- inspectCanonicalTree,
39
- inspectStandaloneCompletionTruth,
40
- } from "./doctor-inspectors.mjs";
41
-
42
- export async function inspectDoctorBootstrapSurface(projectRoot) {
43
- const nimiRoot = path.join(projectRoot, ".nimi");
44
- const checks = [];
45
-
46
- const nimiInfo = await pathExists(nimiRoot);
47
- if (!nimiInfo) {
48
- return {
49
- done: true,
50
- result: createDoctorMissingRootResult(
51
- projectRoot,
52
- ".nimi directory is missing",
53
- "Run `nimicoding start` to seed the project-local .nimi bootstrap truth.",
54
- ),
55
- };
56
- }
57
-
58
- if (!nimiInfo.isDirectory()) {
59
- return {
60
- done: true,
61
- result: createDoctorMissingRootResult(
62
- projectRoot,
63
- ".nimi exists but is not a directory",
64
- "Replace the non-directory `.nimi` path, then rerun `nimicoding start`.",
65
- ),
66
- };
67
- }
68
-
69
- checks.push(buildCheck("nimi_root", true, ".nimi directory exists"));
70
-
71
- const seedEntries = await getBootstrapSeedEntries();
72
- const missingBootstrapFiles = [];
73
- const driftedPackageCanonicalFiles = [];
74
- for (const entry of seedEntries) {
75
- const absolutePath = path.join(projectRoot, entry.outputRelativePath);
76
- const info = await pathExists(absolutePath);
77
- if (!info || !info.isFile()) {
78
- missingBootstrapFiles.push(entry.outputRelativePath);
79
- continue;
80
- }
81
- if (entry.ownership !== "package_canonical") {
82
- continue;
83
- }
84
- const actual = await readTextIfFile(absolutePath);
85
- if (actual !== entry.content) {
86
- driftedPackageCanonicalFiles.push(entry.outputRelativePath);
87
- }
88
- }
89
- checks.push(
90
- buildCheck(
91
- "bootstrap_seed_files",
92
- missingBootstrapFiles.length === 0,
93
- missingBootstrapFiles.length === 0
94
- ? `All bootstrap seed files declared by the seed projection policy are present (${seedEntries.length}/${seedEntries.length})`
95
- : `Missing bootstrap seed files declared by the seed projection policy: ${missingBootstrapFiles.join(", ")}`,
96
- ),
97
- );
98
- checks.push({
99
- id: "bootstrap_seed_package_canonical_in_sync",
100
- ok: true,
101
- severity: driftedPackageCanonicalFiles.length === 0 ? "ok" : "warn",
102
- detail: driftedPackageCanonicalFiles.length === 0
103
- ? "All package_canonical seed files match package source byte-for-byte"
104
- : `package_canonical seed files diverge from package source; run \`nimicoding sync --apply\` to refresh, or \`nimicoding sync --check\` for the authoritative gate: ${driftedPackageCanonicalFiles.join(", ")}`,
105
- });
106
-
107
- const missingLocalDirs = [];
108
- for (const relativePath of REQUIRED_LOCAL_DIRS) {
109
- const info = await pathExists(path.join(projectRoot, relativePath));
110
- if (!info || !info.isDirectory()) {
111
- missingLocalDirs.push(relativePath);
112
- }
113
- }
114
- checks.push({
115
- id: "local_state_dirs",
116
- ok: true,
117
- severity: missingLocalDirs.length === 0 ? "ok" : "warn",
118
- detail: missingLocalDirs.length === 0
119
- ? "Local state directories are present"
120
- : `Local state directories are absent and can be recreated on demand: ${missingLocalDirs.join(", ")}`,
121
- });
122
-
123
- const gitignoreText = await readTextIfFile(path.join(projectRoot, ".gitignore"));
124
- const missingGitignoreEntries = gitignoreText === null
125
- ? LOCAL_GITIGNORE_ENTRIES.slice()
126
- : LOCAL_GITIGNORE_ENTRIES.filter((entry) => !gitignoreText.includes(entry));
127
- checks.push(
128
- buildCheck(
129
- "gitignore_local_state",
130
- missingGitignoreEntries.length === 0,
131
- missingGitignoreEntries.length === 0
132
- ? "Local nimicoding state is ignored by .gitignore"
133
- : `.gitignore is missing local-state entries: ${missingGitignoreEntries.join(", ")}`,
134
- ),
135
- );
136
-
137
- const bootstrapConfigText = await readTextIfFile(path.join(projectRoot, ".nimi", "config", "bootstrap.yaml"));
138
- const bootstrapIdentityOk = Boolean(bootstrapConfigText)
139
- && readYamlScalar(bootstrapConfigText, "initialized_by") === PACKAGE_NAME
140
- && Boolean(readYamlScalar(bootstrapConfigText, "cli_version"));
141
- checks.push(
142
- buildCheck(
143
- "bootstrap_config_contract",
144
- bootstrapIdentityOk,
145
- bootstrapIdentityOk
146
- ? "bootstrap.yaml declares the package bootstrap identity"
147
- : "bootstrap.yaml is missing or does not match the package bootstrap identity",
148
- ),
149
- );
150
-
151
- const bootstrapCompatibility = await inspectBootstrapCompatibility(projectRoot);
152
- checks.push({
153
- id: "bootstrap_contract_version",
154
- ok: bootstrapCompatibility.status !== "unsupported",
155
- severity: bootstrapCompatibility.status === "supported"
156
- ? "ok"
157
- : bootstrapCompatibility.status === "legacy"
158
- ? "warn"
159
- : bootstrapCompatibility.status === "missing"
160
- ? "warn"
161
- : "error",
162
- detail: bootstrapCompatibility.status === "supported"
163
- ? `bootstrap contract ${bootstrapCompatibility.contractId} version ${bootstrapCompatibility.contractVersion} is supported`
164
- : bootstrapCompatibility.status === "legacy"
165
- ? "bootstrap.yaml was created by nimicoding but is missing bootstrap contract metadata"
166
- : bootstrapCompatibility.status === "missing"
167
- ? "bootstrap.yaml is missing and bootstrap contract compatibility could not be checked"
168
- : "bootstrap.yaml declares an unsupported bootstrap contract id or version",
169
- });
170
-
171
- const specGenerationInputsContract = await loadSpecGenerationInputsContract(projectRoot);
172
- const specGenerationAuditContract = await loadSpecGenerationAuditContract(projectRoot);
173
- const specGenerationInputs = await loadSpecGenerationInputsConfig(projectRoot);
174
- const usesV2SurfaceModel = specGenerationInputs.ok && specGenerationInputs.mode === "class_filtered";
175
-
176
- const bootstrapStateText = await readTextIfFile(path.join(projectRoot, ".nimi", "spec", "bootstrap-state.yaml"));
177
- const bootstrapStateContract = inspectBootstrapStateContract(bootstrapStateText);
178
- checks.push(
179
- buildCheck(
180
- "bootstrap_state_contract",
181
- usesV2SurfaceModel || bootstrapStateContract.ok,
182
- usesV2SurfaceModel
183
- ? "v2 host-local surface model does not require .nimi/spec/bootstrap-state.yaml"
184
- : bootstrapStateContract.ok
185
- ? `bootstrap-state.yaml matches the ${bootstrapStateContract.treeState} tree-state contract`
186
- : "bootstrap-state.yaml is missing required lifecycle fields or declares an unsupported lifecycle state",
187
- usesV2SurfaceModel ? "info" : undefined,
188
- ),
189
- );
190
-
191
- const productScopeText = await readTextIfFile(path.join(projectRoot, ".nimi", "spec", "product-scope.yaml"));
192
- const completionTruth = inspectStandaloneCompletionTruth(productScopeText);
193
- checks.push(
194
- buildCheck(
195
- "standalone_completion_truth",
196
- usesV2SurfaceModel || completionTruth.ok,
197
- usesV2SurfaceModel
198
- ? "v2 host-local surface model does not require .nimi/spec/product-scope.yaml"
199
- : completionTruth.ok
200
- ? `Product scope declares standalone completion profile ${completionTruth.completionProfile}`
201
- : "product-scope.yaml is missing or drifted from the package-owned standalone completion truth",
202
- usesV2SurfaceModel ? "info" : undefined,
203
- ),
204
- );
205
-
206
- const specTreeModel = await loadSpecTreeModelContract(projectRoot);
207
- checks.push(
208
- buildCheck(
209
- "spec_tree_model_contract",
210
- usesV2SurfaceModel || specTreeModel.ok,
211
- usesV2SurfaceModel
212
- ? ".nimi/contracts/surface-taxonomy.schema.yaml supplies the v2 spec surface profile"
213
- : specTreeModel.ok
214
- ? `${SPEC_TREE_MODEL_REF} declares canonical root ${specTreeModel.canonicalRoot} with profile ${specTreeModel.profile}`
215
- : `${SPEC_TREE_MODEL_REF} is missing or malformed`,
216
- usesV2SurfaceModel ? "ok" : undefined,
217
- ),
218
- );
219
-
220
- checks.push(
221
- buildCheck(
222
- "spec_generation_inputs_contract",
223
- specGenerationInputsContract.ok,
224
- specGenerationInputsContract.ok
225
- ? `${SPEC_GENERATION_INPUTS_CONTRACT_REF} is present and structurally valid`
226
- : `${SPEC_GENERATION_INPUTS_CONTRACT_REF} is missing or malformed`,
227
- ),
228
- );
229
-
230
- checks.push(
231
- buildCheck(
232
- "spec_generation_audit_contract",
233
- specGenerationAuditContract.ok,
234
- specGenerationAuditContract.ok
235
- ? `${SPEC_GENERATION_AUDIT_CONTRACT_REF} is present and structurally valid`
236
- : `${SPEC_GENERATION_AUDIT_CONTRACT_REF} is missing or malformed`,
237
- ),
238
- );
239
-
240
- checks.push(
241
- buildCheck(
242
- "spec_generation_inputs_config",
243
- specGenerationInputs.ok,
244
- specGenerationInputs.ok
245
- ? `${SPEC_GENERATION_INPUTS_REF} declares ${specGenerationInputs.mode} canonical spec generation inputs`
246
- : `${SPEC_GENERATION_INPUTS_REF} is missing or malformed`,
247
- ),
248
- );
249
-
250
- const commandGatingMatrix = await loadCommandGatingMatrix(projectRoot);
251
- checks.push(
252
- buildCheck(
253
- "command_gating_matrix_contract",
254
- usesV2SurfaceModel || commandGatingMatrix.ok,
255
- usesV2SurfaceModel
256
- ? "v2 workflow gates are provided by project-local .nimi/contracts and .nimi/methodology"
257
- : commandGatingMatrix.ok
258
- ? `${COMMAND_GATING_MATRIX_REF} declares ${commandGatingMatrix.entries.length} command gating rules`
259
- : `${COMMAND_GATING_MATRIX_REF} is missing or malformed`,
260
- usesV2SurfaceModel ? "ok" : undefined,
261
- ),
262
- );
263
-
264
- const blueprintReference = await loadBlueprintReference(projectRoot);
265
- const blueprintReferenceExpected = usesV2SurfaceModel
266
- ? specGenerationInputs.benchmarkMode !== "none" || typeof specGenerationInputs.benchmarkBlueprintRoot === "string"
267
- : bootstrapStateContract.blueprintMode !== "none";
268
- const expectedBlueprintCanonicalRoot = usesV2SurfaceModel
269
- ? specGenerationInputs.canonicalTargetRoot
270
- : specTreeModel.canonicalRoot;
271
- const blueprintReferenceAligned = !blueprintReferenceExpected
272
- ? !blueprintReference.present
273
- : blueprintReference.present
274
- && blueprintReference.ok
275
- && (usesV2SurfaceModel || blueprintReference.mode === bootstrapStateContract.blueprintMode)
276
- && blueprintReference.canonicalTargetRoot === expectedBlueprintCanonicalRoot;
277
- checks.push(
278
- buildCheck(
279
- "blueprint_reference_contract",
280
- blueprintReferenceAligned,
281
- blueprintReferenceExpected
282
- ? blueprintReferenceAligned
283
- ? `${BLUEPRINT_REFERENCE_REF} matches blueprint mode ${bootstrapStateContract.blueprintMode}`
284
- : `${BLUEPRINT_REFERENCE_REF} is required and must match the declared blueprint mode`
285
- : "No explicit project-local blueprint reference is declared",
286
- blueprintReferenceExpected
287
- ? (blueprintReferenceAligned ? "ok" : "error")
288
- : "info",
289
- ),
290
- );
291
-
292
- const benchmarkRoot = specGenerationInputs.benchmarkBlueprintRoot ?? blueprintReference.root ?? null;
293
- const benchmarkAvailable = typeof benchmarkRoot === "string" && benchmarkRoot.length > 0;
294
- const benchmarkAuditReadiness = {
295
- available: benchmarkAvailable,
296
- ready: benchmarkAvailable && Boolean(
297
- specGenerationInputs.ok
298
- && (usesV2SurfaceModel || specTreeModel.ok)
299
- && (
300
- specGenerationInputs.benchmarkMode === "none"
301
- ? !blueprintReference.present
302
- : blueprintReference.present
303
- && blueprintReference.ok
304
- && blueprintReference.root === benchmarkRoot
305
- ),
306
- ),
307
- benchmarkRoot,
308
- acceptanceMode: specGenerationInputs.acceptanceMode ?? null,
309
- reason: typeof benchmarkRoot === "string" && benchmarkRoot.length > 0
310
- ? "Benchmark audit can compare the declared blueprint root against the candidate canonical tree"
311
- : "No benchmark blueprint is declared for this project.",
312
- };
313
- checks.push({
314
- id: "benchmark_audit_readiness",
315
- ok: !benchmarkAuditReadiness.available || benchmarkAuditReadiness.ready,
316
- severity: benchmarkAuditReadiness.available
317
- ? benchmarkAuditReadiness.ready ? "ok" : "warn"
318
- : "info",
319
- detail: benchmarkAuditReadiness.reason,
320
- });
321
-
322
- const canonicalTree = await inspectCanonicalTree(projectRoot, specTreeModel);
323
- checks.push({
324
- id: "canonical_tree_progress",
325
- ok: true,
326
- severity: canonicalTree.requiredFilesValid
327
- ? "ok"
328
- : bootstrapStateContract.treeState === "bootstrap_only"
329
- ? "info"
330
- : "warn",
331
- detail: canonicalTree.requiredFilesValid
332
- ? "Declared canonical tree required files are present"
333
- : `Canonical tree required files are still missing: ${canonicalTree.missing.join(", ")}`,
334
- });
335
-
336
- const specGenerationAuditRef = usesV2SurfaceModel
337
- ? ".nimi/local/state/spec-generation/spec-generation-audit.yaml"
338
- : SPEC_GENERATION_AUDIT_REF;
339
- const specGenerationAuditInfo = await pathExists(path.join(projectRoot, specGenerationAuditRef));
340
- let specGenerationAudit = emptySpecGenerationAudit();
341
- specGenerationAudit.auditPath = specGenerationAuditRef;
342
- if (specGenerationAuditInfo?.isFile()) {
343
- const specGenerationAuditReport = await validateSpecAudit(
344
- path.join(projectRoot, specGenerationAuditRef),
345
- { projectRoot },
346
- );
347
- specGenerationAudit = {
348
- present: true,
349
- ok: specGenerationAuditReport.ok,
350
- auditPath: specGenerationAuditRef,
351
- validator: "validate-spec-audit",
352
- summary: specGenerationAuditReport.summary ?? null,
353
- reason: specGenerationAuditReport.ok
354
- ? "Spec generation audit is present and structurally valid"
355
- : specGenerationAuditReport.errors.join("; "),
356
- };
357
- }
358
- const specGenerationAuditCheckSeverity = !specGenerationAudit.present
359
- ? canonicalTree.requiredFilesValid ? "warn" : "info"
360
- : specGenerationAudit.ok ? "ok" : canonicalTree.requiredFilesValid ? "error" : "warn";
361
- checks.push({
362
- id: "spec_generation_audit",
363
- ok: !specGenerationAudit.present ? true : specGenerationAudit.ok,
364
- severity: specGenerationAuditCheckSeverity,
365
- detail: !specGenerationAudit.present
366
- ? canonicalTree.requiredFilesValid
367
- ? "Canonical tree is ready and spec generation audit is missing; run the audit workflow when file-level generation evidence is required"
368
- : specGenerationAudit.reason
369
- : specGenerationAudit.ok
370
- ? specGenerationAudit.reason
371
- : `Canonical tree is ready but spec generation audit is still missing or invalid: ${specGenerationAudit.reason}`,
372
- });
373
-
374
- const highRiskCloseoutGate = findCommandGatingRule(commandGatingMatrix, "closeout", "high_risk_execution");
375
- checks.push(
376
- buildCheck(
377
- "high_risk_closeout_gate",
378
- usesV2SurfaceModel || Boolean(highRiskCloseoutGate?.completedRequires?.tree_state === "canonical_tree_ready"),
379
- usesV2SurfaceModel
380
- ? "v2 high-risk closeout gates are contract-driven by project-local .nimi/contracts"
381
- : highRiskCloseoutGate
382
- ? "Command gating matrix includes high_risk_execution closeout readiness"
383
- : "command gating matrix is missing closeout gating for high_risk_execution",
384
- usesV2SurfaceModel ? "ok" : undefined,
385
- ),
386
- );
387
-
388
- return {
389
- done: false,
390
- projectRoot,
391
- checks,
392
- bootstrapCompatibility,
393
- bootstrapStateContract,
394
- completionTruth,
395
- specTreeModel,
396
- specGenerationInputsContract,
397
- specGenerationAuditContract,
398
- specGenerationInputs,
399
- commandGatingMatrix,
400
- blueprintReference,
401
- blueprintReferenceAligned,
402
- canonicalTree,
403
- benchmarkAuditReadiness,
404
- specGenerationAudit,
405
- };
406
- }
@@ -1,256 +0,0 @@
1
- import path from "node:path";
2
-
3
- import {
4
- AUDIT_SWEEP_RESULT_CONTRACT_REF,
5
- DOC_SPEC_AUDIT_RESULT_CONTRACT_REF,
6
- EXTERNAL_EXECUTION_ARTIFACTS_CONFIG_REF,
7
- EXTERNAL_HOST_COMPATIBILITY_CONTRACT_REF,
8
- HIGH_RISK_EXECUTION_RESULT_CONTRACT_REF,
9
- HOST_ADAPTER_CONFIG_REF,
10
- SPEC_RECONSTRUCTION_RESULT_CONTRACT_REF,
11
- } from "../../constants.mjs";
12
- import { readTextIfFile, pathExists } from "../fs-helpers.mjs";
13
- import { arraysEqual } from "../value-helpers.mjs";
14
- import {
15
- parseSkillSection,
16
- readYamlList,
17
- readYamlScalar,
18
- } from "../yaml-helpers.mjs";
19
- import { buildCheck } from "./doctor-state.mjs";
20
-
21
- export async function inspectDoctorDelegatedSurface(projectRoot) {
22
- const checks = [];
23
-
24
- const skillsConfigText = await readTextIfFile(path.join(projectRoot, ".nimi", "config", "skills.yaml"));
25
- const skillsConfigOk = Boolean(skillsConfigText)
26
- && skillsConfigText.includes("runtime_installed: false")
27
- && skillsConfigText.includes("runtime_owner: external_ai_host")
28
- && skillsConfigText.includes("handoff_contract: .nimi/methodology/skill-handoff.yaml")
29
- && skillsConfigText.includes(`canonical_host_adapter: ${HOST_ADAPTER_CONFIG_REF}`);
30
- checks.push(
31
- buildCheck(
32
- "skills_contract",
33
- skillsConfigOk,
34
- skillsConfigOk
35
- ? "skills.yaml keeps runtime delegated and handoff-driven"
36
- : "skills.yaml is missing delegated runtime contract fields",
37
- ),
38
- );
39
-
40
- const handoffText = await readTextIfFile(path.join(projectRoot, ".nimi", "methodology", "skill-handoff.yaml"));
41
- const manifestText = await readTextIfFile(path.join(projectRoot, ".nimi", "config", "skill-manifest.yaml"));
42
- const hostProfileText = await readTextIfFile(path.join(projectRoot, ".nimi", "config", "host-profile.yaml"));
43
- const hostAdapterText = await readTextIfFile(path.join(projectRoot, HOST_ADAPTER_CONFIG_REF));
44
- const runtimeContractText = await readTextIfFile(path.join(projectRoot, ".nimi", "methodology", "skill-runtime.yaml"));
45
- const installerText = await readTextIfFile(path.join(projectRoot, ".nimi", "config", "skill-installer.yaml"));
46
- const installerResultText = await readTextIfFile(path.join(projectRoot, ".nimi", "methodology", "skill-installer-result.yaml"));
47
-
48
- const contractRuntimeOwnerValues = [
49
- readYamlScalar(skillsConfigText, "runtime_owner"),
50
- readYamlScalar(manifestText, "runtime_owner"),
51
- readYamlScalar(handoffText, "runtime_owner"),
52
- readYamlScalar(runtimeContractText, "runtime_owner"),
53
- readYamlScalar(hostProfileText, "id"),
54
- readYamlScalar(installerText, "installer_owner"),
55
- ];
56
- const contractRuntimeOwnersAligned = contractRuntimeOwnerValues.every((value) => value === "external_ai_host");
57
-
58
- const delegatedModeAligned = [
59
- readYamlScalar(manifestText, "execution_mode"),
60
- readYamlScalar(hostProfileText, "execution_mode"),
61
- readYamlScalar(runtimeContractText, "runtime_mode"),
62
- readYamlScalar(installerText, "installer_mode"),
63
- ].every((value) => value === "delegated");
64
-
65
- const selfHostedAligned = [
66
- readYamlScalar(handoffText, "self_hosted_runtime"),
67
- readYamlScalar(hostProfileText, "self_hosted"),
68
- readYamlScalar(runtimeContractText, "self_hosted"),
69
- readYamlScalar(installerText, "self_hosted"),
70
- ].every((value) => value === "false");
71
-
72
- checks.push(
73
- buildCheck(
74
- "delegated_contract_posture",
75
- contractRuntimeOwnersAligned && delegatedModeAligned && selfHostedAligned,
76
- contractRuntimeOwnersAligned && delegatedModeAligned && selfHostedAligned
77
- ? "Delegated runtime ownership and non-self-hosted posture are consistent across contracts"
78
- : "Delegated runtime ownership, execution mode, or self-hosted posture drifted across contracts",
79
- ),
80
- );
81
-
82
- const referenceChecks = [
83
- readYamlScalar(manifestText, "runtime_contract_ref") === ".nimi/methodology/skill-runtime.yaml",
84
- readYamlScalar(manifestText, "host_profile_ref") === ".nimi/config/host-profile.yaml",
85
- readYamlScalar(manifestText, "installer_ref") === ".nimi/config/skill-installer.yaml",
86
- readYamlScalar(manifestText, "installer_result_contract_ref") === ".nimi/methodology/skill-installer-result.yaml",
87
- readYamlScalar(hostProfileText, "runtime_contract_ref") === ".nimi/methodology/skill-runtime.yaml",
88
- readYamlScalar(hostProfileText, "compatibility_contract_ref") === EXTERNAL_HOST_COMPATIBILITY_CONTRACT_REF,
89
- readYamlScalar(hostProfileText, "installer_ref") === ".nimi/config/skill-installer.yaml",
90
- readYamlScalar(hostProfileText, "installer_result_contract_ref") === ".nimi/methodology/skill-installer-result.yaml",
91
- readYamlScalar(hostAdapterText, "runtime_owner") === "external_ai_host",
92
- readYamlScalar(hostAdapterText, "host_profile_ref") === ".nimi/config/host-profile.yaml",
93
- readYamlScalar(hostAdapterText, "manifest_ref") === ".nimi/config/skill-manifest.yaml",
94
- readYamlScalar(hostAdapterText, "artifact_contract_ref") === EXTERNAL_EXECUTION_ARTIFACTS_CONFIG_REF,
95
- readYamlScalar(hostAdapterText, "handoff_ref") === ".nimi/methodology/skill-handoff.yaml",
96
- readYamlScalar(runtimeContractText, "manifest_ref") === ".nimi/config/skill-manifest.yaml",
97
- readYamlScalar(runtimeContractText, "host_profile_ref") === ".nimi/config/host-profile.yaml",
98
- readYamlScalar(runtimeContractText, "installer_ref") === ".nimi/config/skill-installer.yaml",
99
- readYamlScalar(runtimeContractText, "installer_result_contract_ref") === ".nimi/methodology/skill-installer-result.yaml",
100
- readYamlScalar(runtimeContractText, "handoff_ref") === ".nimi/methodology/skill-handoff.yaml",
101
- readYamlScalar(installerText, "manifest_ref") === ".nimi/config/skill-manifest.yaml",
102
- readYamlScalar(installerText, "runtime_contract_ref") === ".nimi/methodology/skill-runtime.yaml",
103
- readYamlScalar(installerText, "host_profile_ref") === ".nimi/config/host-profile.yaml",
104
- readYamlScalar(installerText, "result_contract_ref") === ".nimi/methodology/skill-installer-result.yaml",
105
- readYamlScalar(installerResultText, "installer_ref") === ".nimi/config/skill-installer.yaml",
106
- readYamlScalar(handoffText, "runtime_contract_ref") === ".nimi/methodology/skill-runtime.yaml",
107
- readYamlScalar(handoffText, "host_profile_ref") === ".nimi/config/host-profile.yaml",
108
- readYamlScalar(handoffText, "host_compatibility_contract_ref") === EXTERNAL_HOST_COMPATIBILITY_CONTRACT_REF,
109
- readYamlScalar(handoffText, "installer_ref") === ".nimi/config/skill-installer.yaml",
110
- readYamlScalar(handoffText, "installer_result_contract_ref") === ".nimi/methodology/skill-installer-result.yaml",
111
- readYamlScalar(handoffText, "exchange_projection_contract_ref") === ".nimi/methodology/skill-exchange-projection.yaml",
112
- ];
113
- checks.push(
114
- buildCheck(
115
- "contract_reference_alignment",
116
- referenceChecks.every(Boolean),
117
- referenceChecks.every(Boolean)
118
- ? "Manifest, runtime, installer, host-profile, host-adapter, and handoff references are aligned"
119
- : "Cross-contract reference drift detected between manifest/runtime/installer/host-profile/host-adapter/handoff truth",
120
- ),
121
- );
122
-
123
- const manifestSkills = parseSkillSection(manifestText, "skills");
124
- const expectedSkills = parseSkillSection(skillsConfigText, "expected_skill_surfaces");
125
-
126
- const reconstructionSkill = manifestSkills.find((skill) => skill.id === "spec_reconstruction") ?? null;
127
- const docAuditSkill = manifestSkills.find((skill) => skill.id === "doc_spec_audit") ?? null;
128
- const auditSweepSkill = manifestSkills.find((skill) => skill.id === "audit_sweep") ?? null;
129
- const highRiskSkill = manifestSkills.find((skill) => skill.id === "high_risk_execution") ?? null;
130
- const resultContractAlignment = reconstructionSkill?.result_contract_ref === SPEC_RECONSTRUCTION_RESULT_CONTRACT_REF
131
- && docAuditSkill?.result_contract_ref === DOC_SPEC_AUDIT_RESULT_CONTRACT_REF
132
- && auditSweepSkill?.result_contract_ref === AUDIT_SWEEP_RESULT_CONTRACT_REF
133
- && highRiskSkill?.result_contract_ref === HIGH_RISK_EXECUTION_RESULT_CONTRACT_REF;
134
- checks.push(
135
- buildCheck(
136
- "skill_result_contract_alignment",
137
- resultContractAlignment,
138
- resultContractAlignment
139
- ? "Skill manifest result contract refs align with the declared machine contracts"
140
- : "Skill manifest result contract refs drifted away from the declared machine contracts",
141
- ),
142
- );
143
-
144
- const hostRequiredContext = readYamlList(hostProfileText, "required_context");
145
- const handoffRequiredContext = readYamlList(handoffText, "required_context_order");
146
- const missingHandoffContextEntries = hostRequiredContext.filter((entry) => !handoffRequiredContext.includes(entry));
147
- const missingHandoffPaths = [];
148
- for (const relativePath of handoffRequiredContext) {
149
- const info = await pathExists(path.join(projectRoot, relativePath));
150
- if (!info && relativePath !== ".nimi/spec") {
151
- missingHandoffPaths.push(relativePath);
152
- }
153
- }
154
- const handoffContextOk = missingHandoffContextEntries.length === 0 && missingHandoffPaths.length === 0;
155
- checks.push(
156
- buildCheck(
157
- "handoff_context_contract",
158
- handoffContextOk,
159
- handoffContextOk
160
- ? "Handoff context order contains the declared host context and all listed paths exist"
161
- : [
162
- missingHandoffContextEntries.length > 0
163
- ? `handoff context is missing host-required entries: ${missingHandoffContextEntries.join(", ")}`
164
- : null,
165
- missingHandoffPaths.length > 0
166
- ? `handoff context paths are missing on disk: ${missingHandoffPaths.join(", ")}`
167
- : null,
168
- ].filter(Boolean).join("; "),
169
- ),
170
- );
171
-
172
- const manifestSkillIds = manifestSkills.map((skill) => skill.id);
173
- const expectedSkillIds = expectedSkills.map((skill) => skill.id);
174
- const skillSurfaceAligned = arraysEqual(manifestSkillIds, expectedSkillIds);
175
- checks.push(
176
- buildCheck(
177
- "skill_surface_alignment",
178
- skillSurfaceAligned,
179
- skillSurfaceAligned
180
- ? "Manifest skills align with the expected skill surfaces declared in skills.yaml"
181
- : "Manifest skills and expected skill surfaces drifted out of alignment",
182
- ),
183
- );
184
-
185
- const admittedAdapterIds = readYamlList(hostAdapterText, "admitted_adapter_ids");
186
- const selectedAdapterId = readYamlScalar(hostAdapterText, "selected_adapter_id");
187
- const adapterSelected = selectedAdapterId !== null && selectedAdapterId !== "none";
188
- const adapterSelectionValid = selectedAdapterId !== null
189
- && (!adapterSelected || admittedAdapterIds.includes(selectedAdapterId));
190
- checks.push(
191
- buildCheck(
192
- "host_adapter_contract",
193
- adapterSelectionValid,
194
- adapterSelectionValid
195
- ? adapterSelected
196
- ? `Host adapter ${selectedAdapterId} is selected and admitted`
197
- : "No host adapter selected; vendor-neutral delegated host posture remains active"
198
- : "host-adapter selected_adapter_id must be none or one of admitted_adapter_ids",
199
- ),
200
- );
201
-
202
- const adapterBoundaryAligned = readYamlScalar(hostAdapterText, "semantic_review_owner") === "nimicoding_manager"
203
- && readYamlScalar(hostAdapterText, "handoff_mode") === "prompt_output_evidence_handoff"
204
- && readYamlScalar(hostAdapterText, "evidence_mode") === "candidate_only";
205
- checks.push(
206
- buildCheck(
207
- "host_adapter_boundary",
208
- adapterBoundaryAligned,
209
- adapterBoundaryAligned
210
- ? "Host adapter boundary keeps semantic review in nimicoding and limits handoff to prompt/output/evidence"
211
- : "host-adapter boundary drifted away from prompt/output/evidence-only handoff with nimicoding semantic review ownership",
212
- ),
213
- );
214
-
215
- const delegatedContracts = {
216
- runtimeOwner: readYamlScalar(handoffText, "runtime_owner"),
217
- executionMode: readYamlScalar(runtimeContractText, "runtime_mode"),
218
- installerMode: readYamlScalar(installerText, "installer_mode"),
219
- selfHostedRuntime: readYamlScalar(handoffText, "self_hosted_runtime") === "true",
220
- triggerMode: readYamlScalar(handoffText, "trigger_mode"),
221
- expectedSkillIds: manifestSkillIds,
222
- selectedAdapterId,
223
- admittedAdapterIds,
224
- adapterHandoffMode: readYamlScalar(hostAdapterText, "handoff_mode"),
225
- semanticReviewOwner: readYamlScalar(hostAdapterText, "semantic_review_owner"),
226
- };
227
-
228
- return {
229
- checks,
230
- skillsConfigText,
231
- runtimeInstalled: Boolean(skillsConfigText) && skillsConfigText.includes("runtime_installed: true"),
232
- handoffText,
233
- manifestText,
234
- hostProfileText,
235
- hostAdapterText,
236
- runtimeContractText,
237
- installerText,
238
- installerResultText,
239
- contractRuntimeOwnersAligned,
240
- delegatedModeAligned,
241
- selfHostedAligned,
242
- referenceChecks,
243
- resultContractAlignment,
244
- handoffContextOk,
245
- handoffRequiredContext,
246
- missingHandoffContextEntries,
247
- missingHandoffPaths,
248
- manifestSkillIds,
249
- selectedAdapterId,
250
- admittedAdapterIds,
251
- adapterSelected,
252
- adapterSelectionValid,
253
- adapterBoundaryAligned,
254
- delegatedContracts,
255
- };
256
- }