@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,284 +1,73 @@
1
1
  import {
2
- BLUEPRINT_REFERENCE_REF,
3
- SPEC_GENERATION_AUDIT_CONTRACT_REF,
4
2
  SPEC_GENERATION_AUDIT_COVERAGE_STATUS_ENUM,
5
- SPEC_GENERATION_AUDIT_FILE_REQUIRED_FIELDS,
6
- SPEC_GENERATION_AUDIT_REF,
7
3
  SPEC_GENERATION_AUDIT_REQUIRED_TOP_LEVEL_FIELDS,
8
4
  SPEC_GENERATION_AUDIT_SOURCE_BASIS_ENUM,
9
- SPEC_GENERATION_INPUTS_CONTRACT_REF,
10
- SPEC_GENERATION_INPUTS_REF,
11
- SPEC_RECONSTRUCTION_SUMMARY_REQUIRED_FIELDS,
12
- SPEC_RECONSTRUCTION_SUMMARY_STATUS,
13
- SPEC_TREE_MODEL_REF,
14
5
  } from "../../constants.mjs";
15
- import {
16
- arraysEqual,
17
- isPlainObject,
18
- toStringArray,
19
- } from "../value-helpers.mjs";
6
+ import { arraysEqual, isPlainObject, toStringArray } from "../value-helpers.mjs";
20
7
  import { parseYamlText } from "../yaml-helpers.mjs";
21
- export {
22
- parseAuditSweepContract,
23
- parseDocSpecAuditContract,
24
- parseExternalHostCompatibilityContract,
25
- parseHighRiskAdmissionContract,
26
- parseHighRiskExecutionContract,
27
- parseHighRiskSchemaContract,
28
- } from "./contracts-parse-high-risk.mjs";
29
8
 
30
- const SPEC_TREE_PROFILE_ENUM = ["minimal", "standard", "mature", "surface_taxonomy_v1"];
31
- const AUTHORITY_MODE_ENUM = [
32
- "external_authority_active",
33
- "external_blueprint_active",
34
- "canonical_cutover_ready",
35
- "canonical_active",
36
- "surface_class_validated",
37
- ];
38
- const BLUEPRINT_MODE_ENUM = [
39
- "none",
40
- "repo_spec_blueprint",
41
- "custom_blueprint",
42
- ];
43
- const SPEC_GENERATION_MODE_ENUM = ["mixed", "class_filtered"];
44
- const SPEC_GENERATION_ACCEPTANCE_MODE_ENUM = [
45
- "canonical_tree_validity_without_blueprint",
9
+ const ACCEPTANCE_MODES = [
46
10
  "semantic_and_structural_parity_when_blueprint_exists",
47
11
  "placement_validity_before_generation",
48
12
  ];
49
- const SPEC_GENERATION_ORDER_ENUM = [
50
- "index",
51
- "kernel_markdown",
52
- "kernel_tables",
53
- "generated_views",
54
- "thin_guides",
55
- "classify_inputs",
56
- "validate_placement",
57
- "product_authority",
58
- "product_authority_tables",
59
- "derived_views",
60
- "generation_audit",
13
+ const SPEC_GENERATION_INPUT_FIELDS = [
14
+ "mode",
15
+ "canonical_target_root",
16
+ "code_inputs",
17
+ "docs_inputs",
18
+ "structure_inputs",
19
+ "local_inputs",
20
+ "forbidden_source_classes",
21
+ "generation_order",
22
+ "inference_rules",
23
+ "acceptance_mode",
24
+ ];
25
+ const SPEC_GENERATION_INPUT_DOCUMENT_FIELDS = [
26
+ "version",
27
+ "contract_ref",
28
+ "spec_generation_inputs",
61
29
  ];
62
- const TOPIC_LIFECYCLE_REPORT_MARKDOWN = /^\.nimi\/topics\/(?:proposal|ongoing|pending|closed)\/\d{4}-\d{2}-\d{2}-[a-z0-9]+(?:-[a-z0-9]+)*\/[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*\.md$/;
63
-
64
- function normalizeAuthorityModeValue(value) {
65
- return value === "external_blueprint_active" ? "external_authority_active" : value;
66
- }
67
30
 
68
31
  function toStringOrNull(value) {
69
32
  return typeof value === "string" ? value : null;
70
33
  }
71
34
 
72
- function toStringList(value) {
73
- if (typeof value === "string") {
74
- return [value];
75
- }
76
- return toStringArray(value);
35
+ function hasExactFields(value, expectedFields) {
36
+ return isPlainObject(value)
37
+ && arraysEqual(Object.keys(value).sort(), [...expectedFields].sort());
77
38
  }
78
39
 
79
- function normalizePathClass(entry) {
80
- if (!isPlainObject(entry)) {
81
- return null;
82
- }
83
-
84
- return {
85
- id: toStringOrNull(entry.id),
86
- pathPatterns: toStringArray(entry.path_patterns),
87
- excludedPathPatterns: toStringArray(entry.excluded_path_patterns),
88
- allowedExtensions: toStringArray(entry.allowed_extensions),
89
- generatorRefs: toStringArray(entry.generator_refs),
90
- mustReferenceNormativeIds: entry.must_reference_normative_ids === true,
91
- normative: entry.normative === true,
92
- };
93
- }
94
-
95
- function normalizeSpecDomain(entry) {
96
- if (!isPlainObject(entry)) {
97
- return null;
98
- }
99
-
100
- return {
101
- id: toStringOrNull(entry.id),
102
- root: toStringOrNull(entry.root),
103
- normativeRoot: toStringOrNull(entry.normative_root),
104
- tablesRoot: toStringOrNull(entry.tables_root),
105
- generatedRoot: toStringOrNull(entry.generated_root),
106
- guidePaths: toStringArray(entry.guide_paths),
107
- };
108
- }
109
-
110
- function normalizeGeneratedPipeline(entry) {
111
- if (!isPlainObject(entry)) {
112
- return null;
113
- }
114
-
115
- return {
116
- id: toStringOrNull(entry.id),
117
- ownerSurface: toStringOrNull(entry.owner_surface),
118
- inputRoots: toStringArray(entry.input_roots).length > 0
119
- ? toStringArray(entry.input_roots)
120
- : [
121
- ...toStringList(entry.input_contract_ref),
122
- ...toStringList(entry.input_config_ref),
123
- ],
124
- outputRoots: toStringArray(entry.output_roots),
125
- generateCommand: toStringOrNull(entry.generate_command),
126
- driftCheckCommand: toStringOrNull(entry.drift_check_command),
127
- };
128
- }
129
-
130
- function normalizeV2SpecDomain(entry) {
131
- if (!isPlainObject(entry)) {
132
- return null;
133
- }
134
- const root = toStringOrNull(entry.root);
135
- return {
136
- id: toStringOrNull(entry.id),
137
- root,
138
- normativeRoot: root ? `${root}/kernel` : null,
139
- tablesRoot: root ? `${root}/kernel/tables` : null,
140
- generatedRoot: null,
141
- guidePaths: [],
142
- };
143
- }
144
-
145
- function normalizeV2PathClass(entry) {
146
- if (!isPlainObject(entry)) {
147
- return null;
148
- }
149
- return {
150
- id: toStringOrNull(entry.id),
151
- pathPatterns: toStringArray(entry.path_patterns),
152
- excludedPathPatterns: toStringArray(entry.excluded_path_patterns),
153
- allowedExtensions: toStringArray(entry.allowed_extensions),
154
- generatorRefs: [],
155
- mustReferenceNormativeIds: entry.must_reference_product_authority_ids === true,
156
- normative: ["product_authority", "product_authority_table"].includes(entry.id),
157
- };
158
- }
159
-
160
- function pathStartsWithRoot(targetPath, root) {
161
- if (typeof targetPath !== "string" || typeof root !== "string") {
162
- return false;
163
- }
164
-
165
- return targetPath === root || targetPath.startsWith(`${root}/`);
166
- }
167
-
168
- function isDatePrefixedTopicLifecycleMarkdownPath(value) {
169
- if (typeof value !== "string") {
170
- return false;
171
- }
172
- return TOPIC_LIFECYCLE_REPORT_MARKDOWN.test(value);
173
- }
174
-
175
- function topicLifecycleMarkdownPathsAreSortable(paths) {
176
- return paths.every((entry) => {
177
- if (typeof entry !== "string") {
178
- return true;
179
- }
180
- if (entry.startsWith(".local/report/")) {
181
- return false;
182
- }
183
- if (!entry.startsWith(".nimi/topics/")) {
184
- return true;
185
- }
186
- if (!entry.endsWith(".md")) {
187
- return true;
188
- }
189
- return isDatePrefixedTopicLifecycleMarkdownPath(entry);
190
- });
191
- }
192
-
193
- function isAllowedV2AuthorityDocsRoot(root) {
194
- if (typeof root !== "string" || root.length === 0) {
195
- return false;
196
- }
197
- if (root === "." || root === "./" || root === "/" || root === "**" || root.includes("..")) {
198
- return false;
199
- }
200
- return root === ".nimi/spec" || root.startsWith(".nimi/spec/");
201
- }
202
-
203
- export function parseSpecReconstructionContract(text) {
204
- const parsed = parseYamlText(text);
205
- const version = parsed?.version ?? null;
206
- const summaryRequiredFields = toStringArray(parsed?.summary_required_fields);
207
- const summaryStatusEnum = toStringArray(parsed?.summary_status_enum);
208
- const completionRequirements = toStringArray(parsed?.completion_requirements);
209
- const canonicalTreeCompletion = isPlainObject(parsed?.canonical_tree_completion)
210
- ? {
211
- profileRef: toStringOrNull(parsed.canonical_tree_completion.profile_ref),
212
- generationInputsRef: toStringOrNull(parsed.canonical_tree_completion.generation_inputs_ref),
213
- auditContractRef: toStringOrNull(parsed.canonical_tree_completion.audit_contract_ref),
214
- auditRef: toStringOrNull(parsed.canonical_tree_completion.audit_ref),
215
- requiredTreeState: toStringOrNull(parsed.canonical_tree_completion.required_tree_state),
216
- requiredFilesValid: parsed.canonical_tree_completion.required_files_valid === true,
217
- }
218
- : null;
219
-
220
- const expectedSummaryFields = version === 2
221
- ? [...SPEC_RECONSTRUCTION_SUMMARY_REQUIRED_FIELDS.slice(0, 2), "placement_report_ref", ...SPEC_RECONSTRUCTION_SUMMARY_REQUIRED_FIELDS.slice(2)]
222
- : SPEC_RECONSTRUCTION_SUMMARY_REQUIRED_FIELDS;
223
- const expectedProfileRef = version === 2 ? ".nimi/contracts/surface-taxonomy.schema.yaml" : SPEC_TREE_MODEL_REF;
224
- const expectedInputsRef = version === 2 ? ".nimi/config/spec-generation-inputs.yaml" : SPEC_GENERATION_INPUTS_REF;
225
- const expectedAuditContractRef = version === 2 ? ".nimi/contracts/spec-generation-audit.schema.yaml" : SPEC_GENERATION_AUDIT_CONTRACT_REF;
226
- const expectedAuditRef = version === 2 ? ".nimi/local/state/spec-generation/spec-generation-audit.yaml" : SPEC_GENERATION_AUDIT_REF;
227
- const fileClassRequirement = version === 2
228
- ? "declared_surface_class_constraints_valid"
229
- : "declared_file_class_constraints_valid";
230
- const auditRequirement = version === 2
231
- ? "spec_generation_audit_present_and_valid_as_local_state"
232
- : "spec_generation_audit_present_and_valid";
233
-
234
- return {
235
- ok: [1, 2].includes(version)
236
- && arraysEqual(summaryRequiredFields, expectedSummaryFields)
237
- && arraysEqual(summaryStatusEnum, SPEC_RECONSTRUCTION_SUMMARY_STATUS)
238
- && completionRequirements.includes("canonical_tree_ready")
239
- && completionRequirements.includes("declared_profile_required_files_valid")
240
- && completionRequirements.includes(fileClassRequirement)
241
- && completionRequirements.includes(auditRequirement)
242
- && completionRequirements.includes("required_canonical_files_have_matching_audit_entries")
243
- && completionRequirements.includes("unresolved_gaps_must_remain_explicit")
244
- && completionRequirements.includes("semantic_and_structural_parity_when_blueprint_exists")
245
- && canonicalTreeCompletion?.profileRef === expectedProfileRef
246
- && canonicalTreeCompletion?.generationInputsRef === expectedInputsRef
247
- && canonicalTreeCompletion?.auditContractRef === expectedAuditContractRef
248
- && canonicalTreeCompletion?.auditRef === expectedAuditRef
249
- && canonicalTreeCompletion?.requiredTreeState === "canonical_tree_ready"
250
- && canonicalTreeCompletion?.requiredFilesValid === true,
251
- canonicalTreeCompletion,
252
- summaryRequiredFields,
253
- summaryStatusEnum,
254
- completionRequirements,
255
- };
40
+ function isAllowedAuthorityRoot(root) {
41
+ return typeof root === "string"
42
+ && (root === ".nimi/spec" || root.startsWith(".nimi/spec/"))
43
+ && !root.includes("..");
256
44
  }
257
45
 
258
46
  export function parseSpecGenerationAuditContract(text) {
259
47
  const parsed = parseYamlText(text);
260
- const version = parsed?.version ?? null;
261
48
  const requiredTopLevelFields = toStringArray(parsed?.required_top_level_fields);
262
49
  const requiredFileEntryFields = toStringArray(parsed?.required_file_entry_fields);
263
50
  const sourceBasisEnum = toStringArray(parsed?.source_basis_enum);
264
51
  const coverageStatusEnum = toStringArray(parsed?.coverage_status_enum);
265
52
  const hardConstraints = toStringArray(parsed?.hard_constraints);
266
-
267
- const expectedTopLevelFields = version === 2
268
- ? [...SPEC_GENERATION_AUDIT_REQUIRED_TOP_LEVEL_FIELDS.slice(0, 4), "placement_report_ref", ...SPEC_GENERATION_AUDIT_REQUIRED_TOP_LEVEL_FIELDS.slice(4)]
269
- : SPEC_GENERATION_AUDIT_REQUIRED_TOP_LEVEL_FIELDS;
270
- const expectedFileEntryFields = version === 2
271
- ? ["canonical_path", "surface_class", "source_refs", "source_basis", "coverage_status", "unresolved_items"]
272
- : SPEC_GENERATION_AUDIT_FILE_REQUIRED_FIELDS;
273
- const expectedTargetRef = version === 2 ? ".nimi/local/state/spec-generation/spec-generation-audit.yaml" : SPEC_GENERATION_AUDIT_REF;
274
- const sourceConstraint = version === 2
275
- ? "source_refs_must_stay_within_class_filtered_declared_inputs"
276
- : "source_refs_must_stay_within_declared_inputs_or_optional_benchmark_root";
53
+ const expectedTopLevelFields = [
54
+ ...SPEC_GENERATION_AUDIT_REQUIRED_TOP_LEVEL_FIELDS.slice(0, 4),
55
+ "placement_report_ref",
56
+ ...SPEC_GENERATION_AUDIT_REQUIRED_TOP_LEVEL_FIELDS.slice(4),
57
+ ];
58
+ const expectedFileEntryFields = [
59
+ "canonical_path",
60
+ "surface_class",
61
+ "source_refs",
62
+ "source_basis",
63
+ "coverage_status",
64
+ "unresolved_items",
65
+ ];
277
66
 
278
67
  return {
279
- ok: [1, 2].includes(version)
68
+ ok: parsed?.version === 2
280
69
  && String(parsed?.audit_contract?.id ?? "") === "canonical_spec_generation_audit"
281
- && String(parsed?.audit_contract?.target_ref ?? "") === expectedTargetRef
70
+ && String(parsed?.audit_contract?.target_ref ?? "") === ".nimi/local/state/spec-generation/spec-generation-audit.yaml"
282
71
  && arraysEqual(requiredTopLevelFields, expectedTopLevelFields)
283
72
  && arraysEqual(requiredFileEntryFields, expectedFileEntryFields)
284
73
  && arraysEqual(sourceBasisEnum, SPEC_GENERATION_AUDIT_SOURCE_BASIS_ENUM)
@@ -286,7 +75,7 @@ export function parseSpecGenerationAuditContract(text) {
286
75
  && hardConstraints.includes("every_generated_canonical_file_requires_a_matching_audit_entry")
287
76
  && hardConstraints.includes("required_canonical_files_must_not_be_placeholder_not_allowed")
288
77
  && hardConstraints.includes("unresolved_or_inferred_content_must_be_explicit")
289
- && hardConstraints.includes(sourceConstraint)
78
+ && hardConstraints.includes("source_refs_must_stay_within_class_filtered_declared_inputs")
290
79
  && hardConstraints.includes("no_empty_success_looking_audit_entries"),
291
80
  requiredTopLevelFields,
292
81
  requiredFileEntryFields,
@@ -303,39 +92,16 @@ export function parseSpecGenerationInputsContract(text) {
303
92
  const generationOrderEnum = toStringArray(parsed?.generation_order_enum);
304
93
  const hardConstraints = toStringArray(parsed?.hard_constraints);
305
94
 
306
- if (parsed?.version === 2) {
307
- return {
308
- ok: String(contract?.id ?? "") === "canonical_spec_generation_inputs"
309
- && String(contract?.owner ?? "") === "nimi-coding"
310
- && requiredFields.includes("mode")
311
- && requiredFields.includes("canonical_target_root")
312
- && requiredFields.includes("docs_inputs")
313
- && requiredFields.includes("forbidden_source_classes")
314
- && arraysEqual(toStringArray(parsed?.mode_enum), ["class_filtered"])
315
- && SPEC_GENERATION_ACCEPTANCE_MODE_ENUM.includes(toStringArray(parsed?.acceptance_mode_enum)[0])
316
- && generationOrderEnum.includes("classify_inputs")
317
- && generationOrderEnum.includes("validate_placement")
318
- && hardConstraints.includes("docs_roots_blanket_ingestion_is_forbidden")
319
- && hardConstraints.includes("each_input_file_must_have_an_accepted_surface_class_before_render"),
320
- requiredFields,
321
- generationOrderEnum,
322
- hardConstraints,
323
- };
324
- }
325
-
326
95
  return {
327
- ok: parsed?.version === 1
96
+ ok: parsed?.version === 3
328
97
  && String(contract?.id ?? "") === "canonical_spec_generation_inputs"
329
- && String(contract?.target_root ?? "") === ".nimi/spec"
330
- && arraysEqual(toStringArray(contract?.mode_enum), SPEC_GENERATION_MODE_ENUM)
331
- && arraysEqual(toStringArray(contract?.acceptance_mode_enum), SPEC_GENERATION_ACCEPTANCE_MODE_ENUM)
332
- && arraysEqual(generationOrderEnum, SPEC_GENERATION_ORDER_ENUM)
333
- && requiredFields.includes("mode")
334
- && requiredFields.includes("canonical_target_root")
335
- && requiredFields.includes("benchmark_blueprint_root")
336
- && hardConstraints.includes("canonical_target_root_must_be_.nimi/spec")
337
- && hardConstraints.includes("local_report_markdown_paths_must_use_topic_lifecycle_shape")
338
- && hardConstraints.includes("human_authored_topic_reports_must_use_.nimi/topics_as_canonical_root"),
98
+ && String(contract?.owner ?? "") === "nimi-coding"
99
+ && arraysEqual(toStringArray(parsed?.mode_enum), ["class_filtered"])
100
+ && arraysEqual(requiredFields, SPEC_GENERATION_INPUT_FIELDS)
101
+ && generationOrderEnum.includes("classify_inputs")
102
+ && generationOrderEnum.includes("validate_placement")
103
+ && hardConstraints.includes("docs_roots_blanket_ingestion_is_forbidden")
104
+ && hardConstraints.includes("each_input_file_must_have_an_accepted_surface_class_before_render"),
339
105
  requiredFields,
340
106
  generationOrderEnum,
341
107
  hardConstraints,
@@ -345,236 +111,51 @@ export function parseSpecGenerationInputsContract(text) {
345
111
  export function parseSpecGenerationInputsConfig(text) {
346
112
  const parsed = parseYamlText(text);
347
113
  const config = parsed?.spec_generation_inputs;
348
- const mode = toStringOrNull(config?.mode);
349
- const canonicalTargetRoot = toStringOrNull(config?.canonical_target_root);
350
- const codeRoots = toStringArray(config?.code_roots);
351
- const docsRoots = toStringArray(config?.docs_roots);
352
- const structureRoots = toStringArray(config?.structure_roots);
353
114
  const codeInputs = Array.isArray(config?.code_inputs) ? config.code_inputs : [];
354
115
  const docsInputs = Array.isArray(config?.docs_inputs) ? config.docs_inputs : [];
355
116
  const structureInputs = Array.isArray(config?.structure_inputs) ? config.structure_inputs : [];
356
- const topicInputs = Array.isArray(config?.topic_inputs) ? config.topic_inputs : [];
357
117
  const localInputs = Array.isArray(config?.local_inputs) ? config.local_inputs : [];
358
118
  const forbiddenSourceClasses = toStringArray(config?.forbidden_source_classes);
359
- const humanNotePaths = toStringArray(config?.human_note_paths);
360
- const benchmarkBlueprintRoot = typeof config?.benchmark_blueprint_root === "string"
361
- ? config.benchmark_blueprint_root
362
- : null;
363
- const benchmarkMode = toStringOrNull(config?.benchmark_mode);
364
- const acceptanceMode = toStringOrNull(config?.acceptance_mode);
365
119
  const generationOrder = toStringArray(config?.generation_order);
366
120
  const inferenceRules = toStringArray(config?.inference_rules);
367
-
368
- if (parsed?.version === 2) {
369
- const legacyRootsAbsent = !("code_roots" in config)
370
- && !("docs_roots" in config)
371
- && !("structure_roots" in config);
372
- return {
373
- ok: String(parsed?.contract_ref ?? "") === ".nimi/contracts/spec-generation-inputs.schema.yaml"
374
- && mode === "class_filtered"
375
- && canonicalTargetRoot === ".nimi/spec"
376
- && legacyRootsAbsent
377
- && Array.isArray(codeInputs)
378
- && docsInputs.length > 0
379
- && docsInputs.every((entry) => isPlainObject(entry)
380
- && typeof entry.root === "string"
381
- && isAllowedV2AuthorityDocsRoot(entry.root)
382
- && Array.isArray(entry.allowed_surface_classes)
383
- && Array.isArray(entry.forbidden_surface_classes)
384
- && entry.use_as_authority === true)
385
- && Array.isArray(structureInputs)
386
- && Array.isArray(topicInputs)
387
- && Array.isArray(localInputs)
388
- && forbiddenSourceClasses.length > 0
389
- && generationOrder.includes("classify_inputs")
390
- && generationOrder.includes("validate_placement")
391
- && inferenceRules.includes("no_blanket_docs_roots")
392
- && SPEC_GENERATION_ACCEPTANCE_MODE_ENUM.includes(acceptanceMode)
393
- && topicLifecycleMarkdownPathsAreSortable(humanNotePaths),
394
- mode,
395
- canonicalTargetRoot,
396
- codeRoots: codeInputs.map((entry) => String(entry.root ?? "")).filter(Boolean),
397
- docsRoots: docsInputs.map((entry) => String(entry.root ?? "")).filter(Boolean),
398
- structureRoots: structureInputs.map((entry) => String(entry.root ?? "")).filter(Boolean),
399
- humanNotePaths,
400
- benchmarkBlueprintRoot,
401
- benchmarkMode: benchmarkMode ?? "none",
402
- acceptanceMode,
403
- generationOrder,
404
- inferenceRules,
405
- };
406
- }
121
+ const acceptanceMode = toStringOrNull(config?.acceptance_mode);
407
122
 
408
123
  return {
409
- ok: parsed?.version === 1
410
- && String(parsed?.contract_ref ?? "") === SPEC_GENERATION_INPUTS_CONTRACT_REF
411
- && SPEC_GENERATION_MODE_ENUM.includes(mode)
412
- && canonicalTargetRoot === ".nimi/spec"
413
- && Array.isArray(codeRoots)
414
- && Array.isArray(docsRoots)
415
- && Array.isArray(structureRoots)
416
- && Array.isArray(humanNotePaths)
417
- && topicLifecycleMarkdownPathsAreSortable(humanNotePaths)
418
- && BLUEPRINT_MODE_ENUM.includes(benchmarkMode)
419
- && SPEC_GENERATION_ACCEPTANCE_MODE_ENUM.includes(acceptanceMode)
420
- && generationOrder.length > 0
421
- && generationOrder.every((entry) => SPEC_GENERATION_ORDER_ENUM.includes(entry))
422
- && inferenceRules.length > 0
423
- && (
424
- benchmarkMode === "none"
425
- ? benchmarkBlueprintRoot === null
426
- : typeof benchmarkBlueprintRoot === "string" && benchmarkBlueprintRoot.length > 0
427
- ),
428
- mode,
429
- canonicalTargetRoot,
430
- codeRoots,
431
- docsRoots,
432
- structureRoots,
433
- humanNotePaths,
434
- benchmarkBlueprintRoot,
435
- benchmarkMode,
124
+ ok: hasExactFields(parsed, SPEC_GENERATION_INPUT_DOCUMENT_FIELDS)
125
+ && hasExactFields(config, SPEC_GENERATION_INPUT_FIELDS)
126
+ && parsed.version === 3
127
+ && String(parsed?.contract_ref ?? "") === ".nimi/contracts/spec-generation-inputs.schema.yaml"
128
+ && config?.mode === "class_filtered"
129
+ && config?.canonical_target_root === ".nimi/spec"
130
+ && docsInputs.length > 0
131
+ && docsInputs.every((entry) => isPlainObject(entry)
132
+ && isAllowedAuthorityRoot(entry.root)
133
+ && Array.isArray(entry.allowed_surface_classes)
134
+ && Array.isArray(entry.forbidden_surface_classes)
135
+ && entry.use_as_authority === true)
136
+ && Array.isArray(codeInputs)
137
+ && Array.isArray(structureInputs)
138
+ && Array.isArray(localInputs)
139
+ && forbiddenSourceClasses.length > 0
140
+ && generationOrder.includes("classify_inputs")
141
+ && generationOrder.includes("validate_placement")
142
+ && inferenceRules.includes("no_blanket_docs_roots")
143
+ && ACCEPTANCE_MODES.includes(acceptanceMode),
144
+ mode: toStringOrNull(config?.mode),
145
+ canonicalTargetRoot: toStringOrNull(config?.canonical_target_root),
146
+ codeRoots: codeInputs.map((entry) => String(entry?.root ?? "")).filter(Boolean),
147
+ docsRoots: docsInputs.map((entry) => String(entry?.root ?? "")).filter(Boolean),
148
+ structureRoots: structureInputs.map((entry) => String(entry?.root ?? "")).filter(Boolean),
149
+ localRoots: localInputs.map((entry) => String(entry?.root ?? "")).filter(Boolean),
150
+ humanNotePaths: [],
151
+ benchmarkBlueprintRoot: null,
152
+ benchmarkMode: "none",
436
153
  acceptanceMode,
437
154
  generationOrder,
438
155
  inferenceRules,
439
156
  };
440
157
  }
441
158
 
442
- export function parseSpecTreeModel(text) {
443
- const parsed = parseYamlText(text);
444
- const model = parsed?.spec_tree_model;
445
- const profile = toStringOrNull(model?.profile);
446
- const canonicalRoot = toStringOrNull(model?.canonical_root) ?? toStringOrNull(model?.product_authority_root);
447
- const authorityMode = normalizeAuthorityModeValue(toStringOrNull(model?.authority_mode));
448
- const isV2 = parsed?.version === 2;
449
- const domains = Array.isArray(model?.domains)
450
- ? model.domains.map(isV2 ? normalizeV2SpecDomain : normalizeSpecDomain).filter(Boolean)
451
- : [];
452
- const normativeClassSource = isV2 ? model?.product_authority_classes : model?.normative_classes;
453
- const derivedClassSource = isV2
454
- ? (Array.isArray(model?.non_authority_classes) ? model.non_authority_classes.filter((entry) => entry?.id === "derived_view") : [])
455
- : model?.derived_classes;
456
- const normativeClasses = Array.isArray(normativeClassSource)
457
- ? normativeClassSource.map(isV2 ? normalizeV2PathClass : normalizePathClass).filter(Boolean)
458
- : [];
459
- const derivedClasses = Array.isArray(derivedClassSource)
460
- ? derivedClassSource.map(isV2 ? (entry) => ({
461
- id: toStringOrNull(entry.id),
462
- pathPatterns: toStringArray(entry.allowed_roots),
463
- excludedPathPatterns: [],
464
- allowedExtensions: [],
465
- generatorRefs: [],
466
- mustReferenceNormativeIds: false,
467
- normative: false,
468
- }) : normalizePathClass).filter(Boolean)
469
- : [];
470
- const guidanceClasses = Array.isArray(model?.guidance_classes)
471
- ? model.guidance_classes.map(isV2 ? normalizeV2PathClass : normalizePathClass).filter(Boolean)
472
- : [];
473
- const requiredFilesByProfile = SPEC_TREE_PROFILE_ENUM.reduce((acc, currentProfile) => {
474
- acc[currentProfile] = toStringArray(model?.required_files?.[currentProfile]);
475
- return acc;
476
- }, {});
477
- if (isV2 && requiredFilesByProfile.surface_taxonomy_v1.length === 0) {
478
- requiredFilesByProfile.surface_taxonomy_v1 = requiredFilesByProfile.minimal;
479
- }
480
- const generatedPipelines = Array.isArray(model?.generated_pipelines)
481
- ? model.generated_pipelines.map(normalizeGeneratedPipeline).filter(Boolean)
482
- : [];
483
- const failClosedRules = toStringArray(model?.fail_closed_rules);
484
- const blueprintSource = isPlainObject(model?.blueprint_source)
485
- ? {
486
- mode: toStringOrNull(model.blueprint_source.mode),
487
- root: toStringOrNull(model.blueprint_source.root),
488
- equivalenceContractRef: toStringOrNull(model.blueprint_source.equivalence_contract_ref),
489
- }
490
- : null;
491
-
492
- const canonicalRootValid = canonicalRoot === ".nimi/spec";
493
- const profileValid = SPEC_TREE_PROFILE_ENUM.includes(profile);
494
- const authorityModeValid = AUTHORITY_MODE_ENUM.includes(authorityMode);
495
- const domainRootsValid = domains.length > 0 && domains.every((domain) => (
496
- typeof domain.id === "string"
497
- && typeof domain.root === "string"
498
- && typeof domain.normativeRoot === "string"
499
- && typeof domain.tablesRoot === "string"
500
- && pathStartsWithRoot(domain.root, canonicalRoot)
501
- && pathStartsWithRoot(domain.normativeRoot, domain.root)
502
- && pathStartsWithRoot(domain.tablesRoot, domain.normativeRoot)
503
- && (!domain.generatedRoot || pathStartsWithRoot(domain.generatedRoot, domain.normativeRoot))
504
- && domain.guidePaths.every((guidePath) => pathStartsWithRoot(guidePath, domain.root))
505
- ));
506
- const profilesToCheck = isV2 ? [profile] : SPEC_TREE_PROFILE_ENUM.filter((entry) => entry !== "surface_taxonomy_v1");
507
- const requiredFilesValid = profilesToCheck.every((currentProfile) => (
508
- requiredFilesByProfile[currentProfile].length > 0
509
- && requiredFilesByProfile[currentProfile].every((requiredPath) => pathStartsWithRoot(requiredPath, canonicalRoot))
510
- ));
511
- const fileClassIdsPresent = normativeClasses.every((entry) => entry.id && entry.pathPatterns.length > 0)
512
- && derivedClasses.every((entry) => entry.id && entry.pathPatterns.length > 0)
513
- && guidanceClasses.every((entry) => entry.id && entry.pathPatterns.length > 0);
514
- const generatedPipelinesValid = generatedPipelines.every((entry) => (
515
- entry.id
516
- && entry.ownerSurface
517
- && entry.generateCommand
518
- && entry.inputRoots.length > 0
519
- && entry.outputRoots.length > 0
520
- ));
521
- const blueprintSourceValid = !blueprintSource || (
522
- typeof blueprintSource.mode === "string"
523
- && ["repo_spec_blueprint", "custom_blueprint"].includes(blueprintSource.mode)
524
- && typeof blueprintSource.root === "string"
525
- && typeof blueprintSource.equivalenceContractRef === "string"
526
- && isDatePrefixedTopicLifecycleMarkdownPath(blueprintSource.equivalenceContractRef)
527
- );
528
-
529
- return {
530
- ok: [1, 2].includes(parsed?.version)
531
- && profileValid
532
- && canonicalRootValid
533
- && authorityModeValid
534
- && domainRootsValid
535
- && requiredFilesValid
536
- && fileClassIdsPresent
537
- && generatedPipelinesValid
538
- && failClosedRules.length > 0
539
- && blueprintSourceValid,
540
- version: parsed?.version ?? null,
541
- profile,
542
- canonicalRoot,
543
- authorityMode,
544
- domains,
545
- normativeClasses,
546
- derivedClasses,
547
- guidanceClasses,
548
- requiredFilesByProfile,
549
- generatedPipelines,
550
- failClosedRules,
551
- blueprintSource,
552
- };
553
- }
554
-
555
- export function parseCommandGatingMatrix(text) {
556
- const parsed = parseYamlText(text);
557
- const entries = Array.isArray(parsed?.command_gating_matrix)
558
- ? parsed.command_gating_matrix
559
- .filter((entry) => isPlainObject(entry) && typeof entry.command === "string")
560
- .map((entry) => ({
561
- command: entry.command,
562
- skill: toStringOrNull(entry.skill),
563
- allowedTreeStates: toStringArray(entry.allowed_tree_states),
564
- allowedAuthorityModes: toStringArray(entry.allowed_authority_modes).map(normalizeAuthorityModeValue),
565
- completedRequires: isPlainObject(entry.completed_requires) ? entry.completed_requires : null,
566
- requires: isPlainObject(entry.requires) ? entry.requires : null,
567
- notes: toStringArray(entry.notes),
568
- reports: toStringArray(entry.reports),
569
- }))
570
- : [];
571
-
572
- return {
573
- ok: parsed?.version === 1 && entries.length > 0,
574
- entries,
575
- };
576
- }
577
-
578
159
  export function parseBlueprintReference(text) {
579
160
  if (!text) {
580
161
  return {
@@ -593,14 +174,15 @@ export function parseBlueprintReference(text) {
593
174
  const root = toStringOrNull(reference?.root);
594
175
  const canonicalTargetRoot = toStringOrNull(reference?.canonical_target_root);
595
176
  const equivalenceContractRef = toStringOrNull(reference?.equivalence_contract_ref);
177
+ const localRefValid = equivalenceContractRef === null
178
+ || (equivalenceContractRef.startsWith(".nimi/local/") && !equivalenceContractRef.includes(".."));
596
179
 
597
180
  return {
598
- ok: parsed?.version === 1
181
+ ok: parsed?.version === 2
599
182
  && ["repo_spec_blueprint", "custom_blueprint"].includes(mode)
600
183
  && typeof root === "string"
601
- && typeof canonicalTargetRoot === "string"
602
- && typeof equivalenceContractRef === "string"
603
- && isDatePrefixedTopicLifecycleMarkdownPath(equivalenceContractRef),
184
+ && canonicalTargetRoot === ".nimi/spec"
185
+ && localRefValid,
604
186
  present: true,
605
187
  mode,
606
188
  root,
@@ -608,21 +190,3 @@ export function parseBlueprintReference(text) {
608
190
  equivalenceContractRef,
609
191
  };
610
192
  }
611
-
612
- export function matchCommandGatingRule(commandGatingMatrix, command, skillId = null) {
613
- if (!commandGatingMatrix?.entries) {
614
- return null;
615
- }
616
-
617
- return commandGatingMatrix.entries.find((entry) => {
618
- if (entry.command !== command) {
619
- return false;
620
- }
621
-
622
- if (skillId === null) {
623
- return !entry.skill;
624
- }
625
-
626
- return entry.skill === skillId;
627
- }) ?? null;
628
- }