@nimiplatform/nimi-coding 0.4.0 → 0.6.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 (70) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +92 -55
  4. package/README.zh-CN.md +93 -56
  5. package/cli/commands/authority.mjs +80 -125
  6. package/cli/commands/clear.mjs +3 -2
  7. package/cli/commands/code.mjs +225 -0
  8. package/cli/commands/start.mjs +3 -2
  9. package/cli/constants.mjs +2 -1
  10. package/cli/dev/check-authority-surface.mjs +17 -8
  11. package/cli/dev/check-product-conformance.mjs +4 -32
  12. package/cli/dev/run-cli-smoke.mjs +6 -0
  13. package/cli/help.mjs +8 -3
  14. package/cli/index.mjs +3 -2
  15. package/cli/lib/authority/audit.mjs +262 -185
  16. package/cli/lib/authority/change-candidates.mjs +807 -0
  17. package/cli/lib/authority/closed-sets.mjs +7 -8
  18. package/cli/lib/authority/compile.mjs +6 -24
  19. package/cli/lib/authority/compiled-snapshot.mjs +143 -0
  20. package/cli/lib/authority/consumers.mjs +69 -19
  21. package/cli/lib/authority/diagnostics.mjs +10 -2
  22. package/cli/lib/authority/diff.mjs +77 -54
  23. package/cli/lib/authority/format.mjs +4 -32
  24. package/cli/lib/authority/git-snapshot.mjs +34 -379
  25. package/cli/lib/authority/graph.mjs +10 -10
  26. package/cli/lib/authority/impact.mjs +17 -144
  27. package/cli/lib/authority/review.mjs +33 -43
  28. package/cli/lib/authority/sarif.mjs +1 -8
  29. package/cli/lib/authority/source-yaml.mjs +0 -4
  30. package/cli/lib/authority/surface.mjs +19 -1
  31. package/cli/lib/authority/terms.mjs +10 -9
  32. package/cli/lib/authority/validate.mjs +6 -14
  33. package/cli/lib/code/authority-annotation-response.mjs +43 -0
  34. package/cli/lib/code/authority-annotation-scan.mjs +162 -0
  35. package/cli/lib/code/authority-annotations.mjs +293 -0
  36. package/cli/lib/code/context.mjs +710 -0
  37. package/cli/lib/code/response.mjs +165 -0
  38. package/cli/lib/doctor.mjs +3 -2
  39. package/cli/lib/entrypoints.mjs +13 -5
  40. package/cli/seeds/seed-policy.yaml +2 -2
  41. package/contracts/authority-source.schema.yaml +0 -6
  42. package/contracts/authority-verifier-bindings.schema.yaml +21 -10
  43. package/methodology/authority-authoring.yaml +68 -70
  44. package/methodology/core.yaml +10 -6
  45. package/package.json +5 -3
  46. package/spec/authority-audit.yaml +56 -52
  47. package/spec/authority-authoring.yaml +3 -16
  48. package/spec/authority-change-candidates.yaml +146 -0
  49. package/spec/authority-consumers.yaml +7 -0
  50. package/spec/authority-discovery.yaml +2 -2
  51. package/spec/authority-graph.yaml +1 -1
  52. package/spec/authority-impact.yaml +16 -39
  53. package/spec/authority-review.yaml +29 -47
  54. package/spec/authority-terms.yaml +5 -1
  55. package/spec/code-authority-annotations.yaml +42 -0
  56. package/spec/code-context.yaml +38 -0
  57. package/spec/product-scope.yaml +15 -9
  58. package/cli/commands/validate-ai-governance.mjs +0 -335
  59. package/cli/lib/authority/evidence-snapshot.mjs +0 -1
  60. package/cli/lib/authority/evidence.mjs +0 -1432
  61. package/cli/lib/internal/governance/ai/ai-context-budget-core.mjs +0 -377
  62. package/cli/lib/internal/governance/ai/ai-structure-budget-core.mjs +0 -376
  63. package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +0 -155
  64. package/cli/lib/internal/governance/ai/check-high-risk-doc-metadata-core.mjs +0 -173
  65. package/cli/lib/internal/governance/config.mjs +0 -114
  66. package/cli/lib/internal/governance/shared/read-yaml-with-fragments.mjs +0 -49
  67. package/contracts/authority-evidence-bindings.schema.yaml +0 -53
  68. package/contracts/authority-evidence-probe-results.schema.yaml +0 -38
  69. package/contracts/authority-impact-dispositions.schema.yaml +0 -13
  70. package/spec/authority-evidence.yaml +0 -200
@@ -0,0 +1,42 @@
1
+ version: 1
2
+ spec:
3
+ id: nimicoding.code-authority-annotations.v1
4
+ owner: nimi-coding
5
+ status: experimental
6
+ product_claim: exact_standalone_markers_link_selected_tracked_current_source_to_current_canonical_authority_lifecycle
7
+ command: nimicoding code authority --repo <exact-git-worktree-root> (--authority <exact-id>|--source <repo-relative-.ts-.tsx-or-.go-path>|--audit) --max-files <integer> --max-bytes <integer>=512
8
+ markers:
9
+ authority: "// nimi-authority: <exact-authority-id>"
10
+ deprecated: "// nimi-deprecated: <exact-authority-id>"
11
+ optional: true
12
+ attachment: source_file_with_exact_marker_and_bounded_nearby_source_only
13
+ declaration_ownership: not_evaluated
14
+ deprecated_pairing: not_evaluated
15
+ scan:
16
+ authority_corpus: complete_repository_.nimi/spec
17
+ source_inventory: Git_tracked_current_filesystem
18
+ source_languages: [TypeScript, TSX, Go]
19
+ persistent_index_or_cache: none
20
+ ordering: deterministic
21
+ operations:
22
+ authority_to_code: all_exact_marker_occurrences_in_the_complete_admitted_source_scan
23
+ code_to_authority: exact_marker_occurrences_in_one_tracked_source_file
24
+ lifecycle_audit: [active-reference, explicit-deprecated, removed-reference, superseded-reference, missing-reference, invalid-annotation]
25
+ response:
26
+ format: nimicoding.code-authority-response/v1
27
+ transport: one_compact_JSON_object_on_stdout_with_terminating_newline
28
+ stderr: empty_for_recognized_code_operations
29
+ statuses: [completed, findings, refused]
30
+ public_budgets: [max-files, max-bytes]
31
+ minimum_valid_max_bytes: 512
32
+ partial_results: forbidden
33
+ boundaries:
34
+ annotation_is_authority: false
35
+ annotation_proves_conformance: false
36
+ unannotated_source: not_evaluated
37
+ active_authority_statement_drift: not_evaluated
38
+ automatic_legacy_detection: false
39
+ annotation_coverage_gate: false
40
+ scope_binding_dependency: none
41
+ writes_repository: false
42
+ workflow_task_or_completion_state: none
@@ -0,0 +1,38 @@
1
+ version: 1
2
+ spec:
3
+ id: nimicoding.code-context.v1
4
+ owner: nimi-coding
5
+ status: experimental
6
+ product_claim: explicit_TypeScript_root_returns_one_bounded_root_direct_static_outbound_projection_or_fails
7
+ command: nimicoding code context <repo-relative-.ts-or-.tsx-path> --repo <exact-git-worktree-root> --symbol <top-level-identifier> --tsconfig <repo-relative-tsconfig> --max-bytes <integer>=512
8
+ compiler:
9
+ language: TypeScript_TSX
10
+ version: 5.9.3
11
+ source: nearest_repo_contained_tsconfig_owner_package
12
+ program: fresh_complete_selected_config_without_project_references
13
+ root:
14
+ selector: one_exact_top_level_Identifier
15
+ admitted: [function, class, interface, type_alias, single_declarator_variable_statement]
16
+ merged_overloaded_nested_member_namespace_enum_or_declaration_root: refused
17
+ projection:
18
+ scope: selected_root_AST_only
19
+ relations: [static_value_binding, static_type_binding, static_constructor_binding, static_JSX_binding]
20
+ target: complete_nonempty_portable_declaration_set
21
+ target_source: optional_single_repository_declaration_syntactic_slice
22
+ runtime_dispatch: not_evaluated
23
+ response:
24
+ format: nimicoding.code-context-response/v1
25
+ transport: one_compact_JSON_object_on_stdout_with_terminating_newline
26
+ stderr: empty_for_recognized_code_operations
27
+ statuses: [completed, partial, refused]
28
+ public_budget: complete_UTF-8_response_max_bytes
29
+ minimum_valid_max_bytes: 512
30
+ partial: deterministic_longest_atomic_prefix_with_first_missing_frontier
31
+ boundaries:
32
+ writes_repository: false
33
+ persistent_index_or_cache: none
34
+ authority_association: not_claimed
35
+ source_location_or_inbound_impact: not_admitted
36
+ structural_advice: not_admitted
37
+ task_workflow_verification_or_completion: not_admitted
38
+ other_languages: not_admitted
@@ -1,18 +1,19 @@
1
- version: 7
1
+ version: 11
2
2
  product:
3
3
  package_name: "@nimiplatform/nimi-coding"
4
- mission: canonical_authority_methodology_formatter_compiler_primitives_and_deterministic_gates
4
+ mission: canonical_authority_products_bounded_read_only_code_context_and_explicit_code_authority_marker_lookup
5
5
  owned_surfaces:
6
6
  - compact_authority_authoring_methodology
7
7
  - exact_authority_guide_projection_and_managed_instruction_blocks
8
8
  - canonical_authority_format_and_complete_root_check
9
9
  - private_compile_bounded_filtered_lexical_discovery_with_field_snippets_optional_direct_authored_relation_preview_exact_query_and_declared_outgoing_context
10
+ - immutable_per_invocation_compiler_snapshots_with_transient_exact_indexes_and_change_derived_candidate_recall
10
11
  - semantic_diff_and_declared_review_impact
11
12
  - bounded_direct_references_exact_relation_paths_and_local_subgraphs
12
- - project_bound_deterministic_authority_audit_and_SARIF_projection
13
+ - project_bound_deterministic_graph_and_exact_lexical_authority_audit_and_SARIF_projection
13
14
  - git_aware_exact_read_only_authority_change_review
14
- - stable_current_worktree_authority_to_package_script_target_evidence
15
- - optional_L3_repository_governance_not_authority_admission
15
+ - explicit_TypeScript_5_9_3_root_direct_bounded_code_context
16
+ - transient_exact_code_authority_marker_lookup_and_lifecycle_audit_for_tracked_current_TypeScript_TSX_and_Go_source
16
17
  canonical_boundary:
17
18
  host_product_authority: .nimi/spec/**/*.authority.{yaml,md}
18
19
  sole_conformance_gate: nimicoding_authority_check_complete_.nimi/spec
@@ -29,12 +30,17 @@ out_of_scope:
29
30
  - profile_specific_authority_validation
30
31
  - planning_task_lifecycle_delegation_execution_review_or_approval
31
32
  - host_workflow_command_aggregation
33
+ - external_probe_result_attestation_test_execution_or_proof_packet_aggregation
32
34
  - sqlite_cache_incremental_embedding_semantic_search_visualization_AI_execution_or_Atlas
35
+ - code_location_inbound_impact_structural_advice_other_semantic_languages_or_task_completeness
36
+ - annotation_coverage_ownership_conformance_inference_or_unannotated_legacy_detection
33
37
  claims:
34
38
  discovery: bounded_deterministic_exact_filtered_lexical_candidates_with_SourceMapped_field_snippets_and_optional_M1_direct_authored_relation_preview_not_semantic_search_selection_context_or_absence_proof
39
+ change_candidates: complete_union_of_caller_requested_exact_channels_with_raw_fields_modality_and_reasons_not_semantic_relevance_conflict_retirement_absence_or_conformance
35
40
  context: complete_declared_outgoing_interpretation_closure_not_complete_task_context
36
- impact: declared_review_obligation_not_sync_or_completion_proof
41
+ impact: declared_relation_impact_and_host_follow_up_targets_not_workflow_state_sync_or_completion_proof
37
42
  graph: complete_bounded_explicit_relation_navigation_not_semantic_inference_or_raw_IR
38
- audit: governance_bound_verifier_results_not_prose_predicate_inference_or_plugin_execution
39
- review: immutable_base_OID_and_stable_worktree_exact_snapshots_composed_through_existing_compiler_diff_impact_and_current_audit_oracles
40
- evidence: exact_identity_bound_package_script_target_reachability_and_external_supplied_observations_not_command_execution_test_success_runtime_reachability_or_conformance_attestation
43
+ audit: configured_graph_and_exact_case_sensitive_lexical_results_not_prose_predicate_inference_semantic_synonym_or_plugin_execution
44
+ review: immutable_base_OID_and_stable_worktree_exact_snapshots_composed_through_existing_compiler_diff_impact_and_current_audit_oracles_with_business_and_implementation_status_not_evaluated
45
+ code_context: complete_selected_TypeScript_Program_root_direct_static_outbound_projection_with_output_budget_and_explicit_frontier_not_location_impact_runtime_dispatch_or_task_context
46
+ code_authority: complete_transient_scan_of_selected_tracked_current_source_scope_for_exact_authored_markers_and_current_canonical_lifecycle_not_attachment_ownership_conformance_or_unannotated_semantics
@@ -1,335 +0,0 @@
1
- import { localize } from "../lib/ui.mjs";
2
- import { loadGovernanceConfig, requireProfile } from "../lib/internal/governance/config.mjs";
3
- import { evaluateAiContextBudget, formatBytes } from "../lib/internal/governance/ai/ai-context-budget-core.mjs";
4
- import { evaluateAiStructureBudget } from "../lib/internal/governance/ai/ai-structure-budget-core.mjs";
5
- import { evaluateHighRiskDocMetadata } from "../lib/internal/governance/ai/check-high-risk-doc-metadata-core.mjs";
6
- import {
7
- evaluateAgentsFreshnessCheck,
8
- runAgentsFreshnessCheck,
9
- } from "../lib/internal/governance/ai/check-agents-freshness.mjs";
10
-
11
- const SCOPES = new Set([
12
- "agents-freshness",
13
- "context-budget",
14
- "structure-budget",
15
- "high-risk-doc-metadata",
16
- ]);
17
-
18
- function parseOptions(args) {
19
- const options = {
20
- profile: null,
21
- scope: "all",
22
- json: false,
23
- };
24
-
25
- for (let index = 0; index < args.length; index += 1) {
26
- const arg = args[index];
27
-
28
- if (arg === "--profile") {
29
- const value = args[index + 1];
30
- if (!value || value.startsWith("--")) {
31
- return { ok: false, error: "nimicoding validate-ai-governance refused: --profile requires a value.\n" };
32
- }
33
- options.profile = value;
34
- index += 1;
35
- continue;
36
- }
37
-
38
- if (arg === "--scope") {
39
- const value = args[index + 1];
40
- if (!value || value.startsWith("--")) {
41
- return { ok: false, error: "nimicoding validate-ai-governance refused: --scope requires a value.\n" };
42
- }
43
- options.scope = value;
44
- index += 1;
45
- continue;
46
- }
47
-
48
- if (arg === "--json") {
49
- options.json = true;
50
- continue;
51
- }
52
-
53
- return {
54
- ok: false,
55
- error: `nimicoding validate-ai-governance refused: unknown option ${arg}.\n`,
56
- };
57
- }
58
-
59
- if (options.scope !== "all" && !SCOPES.has(options.scope)) {
60
- return {
61
- ok: false,
62
- error: `nimicoding validate-ai-governance refused: unsupported --scope value ${options.scope}.\n`,
63
- };
64
- }
65
-
66
- return { ok: true, options };
67
- }
68
-
69
- function writeJson(payload) {
70
- process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
71
- }
72
-
73
- function buildContextBudgetReport(governanceConfig) {
74
- const report = evaluateAiContextBudget({
75
- cwd: process.cwd(),
76
- config: governanceConfig.aiGovernance.contextBudget,
77
- configPathLabel: ".nimi/config/governance.yaml#ai_governance.context_budget",
78
- });
79
- const exitCode = report.invalidWaivers.length > 0 || report.expiredWaivers.length > 0 || report.errors.length > 0
80
- ? 1
81
- : 0;
82
- return { exitCode, report };
83
- }
84
-
85
- function buildStructureBudgetReport(governanceConfig) {
86
- const report = evaluateAiStructureBudget({
87
- cwd: process.cwd(),
88
- config: governanceConfig.aiGovernance.structureBudget,
89
- configPathLabel: ".nimi/config/governance.yaml#ai_governance.structure_budget",
90
- });
91
- const exitCode = report.errors.length > 0 || report.expiredWaivers.length > 0 ? 1 : 0;
92
- return { exitCode, report };
93
- }
94
-
95
- function buildHighRiskDocMetadataReport(governanceConfig) {
96
- const config = governanceConfig.aiGovernance.highRiskDocMetadata;
97
- const report = evaluateHighRiskDocMetadata({
98
- repoRoot: process.cwd(),
99
- docRoots: Array.isArray(config.doc_roots) ? config.doc_roots : [".local"],
100
- exemptPaths: Array.isArray(config.exempt_paths) ? config.exempt_paths : [],
101
- namePatterns: Array.isArray(config.name_patterns) ? config.name_patterns : [],
102
- requiredMetadataKeys: Array.isArray(config.required_metadata_keys)
103
- ? config.required_metadata_keys
104
- : [],
105
- });
106
- return {
107
- exitCode: report.failures.length > 0 ? 1 : 0,
108
- report: {
109
- ...report,
110
- exemptPaths: [...report.exemptPaths],
111
- },
112
- };
113
- }
114
-
115
- function buildAgentsFreshnessReport(governanceConfig) {
116
- const report = evaluateAgentsFreshnessCheck({
117
- projectRoot: process.cwd(),
118
- config: governanceConfig.aiGovernance.agentsFreshness,
119
- });
120
- return {
121
- exitCode: report.failures.length > 0 ? 1 : 0,
122
- report,
123
- };
124
- }
125
-
126
- function formatStructureRow(row) {
127
- if (row.check === "depth") {
128
- return `${row.file} [rule=${row.ruleId}] depth=${row.depth} base=${row.depthBase} subject=${row.depthSubject} (threshold warn>=${row.warningDepth} error>=${row.errorDepth})`;
129
- }
130
- return `${row.file} [rule=${row.ruleId}] basename=${row.basename} (forwarding shell outside allowed basename set)`;
131
- }
132
-
133
- function formatContextBudgetRow(row, thresholdPrefix) {
134
- return `${row.file} [${row.profile}] lines=${row.lines} bytes=${formatBytes(row.bytes)} max-line=${formatBytes(row.maxLineBytes)} avg-line=${formatBytes(Math.round(row.averageLineBytes))} `
135
- + `(${thresholdPrefix} lines>=${row[`${thresholdPrefix}Lines`] ?? "-"} bytes>=${row[`${thresholdPrefix}Bytes`] ?? "-"} max-line>=${row[`${thresholdPrefix}MaxLineBytes`] ?? "-"} avg-line>=${row[`${thresholdPrefix}AverageLineBytes`] ?? "-"})`;
136
- }
137
-
138
- async function runContextBudget(governanceConfig) {
139
- const { exitCode, report } = buildContextBudgetReport(governanceConfig);
140
-
141
- process.stdout.write(`ai-context-budget: config=${report.configPath}\n`);
142
- process.stdout.write(`ai-context-budget: tracked=${report.totalTrackedFiles}, analyzed=${report.analyzedFiles}\n`);
143
-
144
- for (const row of report.warnings) {
145
- process.stderr.write(`WARN: ${formatContextBudgetRow(row, "warning")}\n`);
146
- }
147
- for (const row of report.waivedErrors) {
148
- const until = row.waiver?.until ? row.waiver.until.toISOString().slice(0, 10) : "n/a";
149
- const reason = row.waiver?.reason || "no reason";
150
- process.stderr.write(`WARN: WAIVED error for ${formatContextBudgetRow(row, "error")} until=${until} reason=${reason}\n`);
151
- }
152
- for (const row of report.expiredWaivers) {
153
- process.stderr.write(`ERROR: waiver expired for ${formatContextBudgetRow(row, "error")}\n`);
154
- }
155
- for (const row of report.invalidWaivers) {
156
- process.stderr.write(`ERROR: invalid waiver for ${row.file}: ${row.detail}\n`);
157
- }
158
- for (const row of report.errors) {
159
- process.stderr.write(`ERROR: ${formatContextBudgetRow(row, "error")}\n`);
160
- }
161
-
162
- if (exitCode !== 0) {
163
- return exitCode;
164
- }
165
-
166
- process.stdout.write("ai-context-budget: OK\n");
167
- return 0;
168
- }
169
-
170
- async function runStructureBudget(governanceConfig) {
171
- const { exitCode, report } = buildStructureBudgetReport(governanceConfig);
172
-
173
- process.stdout.write(`ai-structure-budget: config=${report.configPath}\n`);
174
- process.stdout.write(`ai-structure-budget: tracked=${report.totalTrackedFiles}, analyzed=${report.analyzedFiles}\n`);
175
- for (const row of report.warnings) {
176
- process.stderr.write(`WARN: ${formatStructureRow(row)}\n`);
177
- }
178
- for (const row of report.waivedErrors) {
179
- const until = row.waiver?.untilDate ? row.waiver.untilDate.toISOString().slice(0, 10) : "n/a";
180
- const reason = row.waiver?.reason || "no reason";
181
- process.stderr.write(`WARN: WAIVED error for ${formatStructureRow(row)} until=${until} reason=${reason}\n`);
182
- }
183
- for (const row of report.expiredWaivers) {
184
- process.stderr.write(`ERROR: expired waiver for ${formatStructureRow(row)}\n`);
185
- }
186
- for (const row of report.errors) {
187
- process.stderr.write(`ERROR: ${formatStructureRow(row)}\n`);
188
- }
189
- if (exitCode !== 0) {
190
- return exitCode;
191
- }
192
-
193
- process.stdout.write("ai-structure-budget: OK\n");
194
- return 0;
195
- }
196
-
197
- async function runHighRiskDocMetadata(governanceConfig) {
198
- const { exitCode, report } = buildHighRiskDocMetadataReport(governanceConfig);
199
-
200
- if (exitCode !== 0) {
201
- process.stderr.write("high-risk doc metadata check failed:\n");
202
- for (const failure of report.failures) {
203
- process.stderr.write(`- ${failure}\n`);
204
- }
205
- return exitCode;
206
- }
207
-
208
- process.stdout.write(`high-risk doc metadata check passed (${report.scanned.length} file(s) scanned)\n`);
209
- return 0;
210
- }
211
-
212
- function runJsonScope(governanceConfig, scope) {
213
- if (scope === "agents-freshness") {
214
- return buildAgentsFreshnessReport(governanceConfig);
215
- }
216
- if (scope === "context-budget") {
217
- return buildContextBudgetReport(governanceConfig);
218
- }
219
- if (scope === "structure-budget") {
220
- return buildStructureBudgetReport(governanceConfig);
221
- }
222
- if (scope === "high-risk-doc-metadata") {
223
- return buildHighRiskDocMetadataReport(governanceConfig);
224
- }
225
- return {
226
- exitCode: 2,
227
- report: { error: `unsupported scope: ${scope}` },
228
- };
229
- }
230
-
231
- export async function runValidateAiGovernance(args) {
232
- const wantsJson = args.includes("--json");
233
- const parsed = parseOptions(args);
234
- if (!parsed.ok) {
235
- if (wantsJson) {
236
- writeJson({
237
- ok: false,
238
- command: "validate-ai-governance",
239
- error: parsed.error.trim(),
240
- });
241
- } else {
242
- process.stderr.write(localize(parsed.error, parsed.error));
243
- }
244
- return 2;
245
- }
246
-
247
- const governance = await loadGovernanceConfig(process.cwd());
248
- if (!governance.ok) {
249
- const error = `nimicoding validate-ai-governance refused: ${governance.reason} at ${governance.path}.`;
250
- if (parsed.options.json) {
251
- writeJson({
252
- ok: false,
253
- command: "validate-ai-governance",
254
- error,
255
- governancePath: governance.path,
256
- });
257
- } else {
258
- process.stderr.write(localize(
259
- `${error}\n`,
260
- `nimicoding validate-ai-governance 已拒绝:${governance.path} 的治理配置不可用。\n`,
261
- ));
262
- }
263
- return 2;
264
- }
265
-
266
- const profileCheck = requireProfile(governance.config, parsed.options.profile);
267
- if (!profileCheck.ok) {
268
- const error = `nimicoding validate-ai-governance refused: ${profileCheck.error}.`;
269
- if (parsed.options.json) {
270
- writeJson({
271
- ok: false,
272
- command: "validate-ai-governance",
273
- error,
274
- profile: profileCheck.profile,
275
- });
276
- } else {
277
- process.stderr.write(localize(
278
- `${error}\n`,
279
- `nimicoding validate-ai-governance 已拒绝:${profileCheck.error}。\n`,
280
- ));
281
- }
282
- return 2;
283
- }
284
-
285
- const scopes = parsed.options.scope === "all"
286
- ? ["agents-freshness", "context-budget", "structure-budget", "high-risk-doc-metadata"]
287
- : [parsed.options.scope];
288
-
289
- if (parsed.options.json) {
290
- const results = [];
291
- let exitCode = 0;
292
- for (const scope of scopes) {
293
- const result = runJsonScope(governance.config, scope);
294
- if (exitCode === 0 && result.exitCode !== 0) {
295
- exitCode = result.exitCode;
296
- }
297
- results.push({
298
- scope,
299
- ok: result.exitCode === 0,
300
- exitCode: result.exitCode,
301
- report: result.report,
302
- });
303
- }
304
- writeJson({
305
- ok: exitCode === 0,
306
- command: "validate-ai-governance",
307
- profile: profileCheck.profile,
308
- scope: parsed.options.scope,
309
- scopes: results,
310
- });
311
- return exitCode;
312
- }
313
-
314
- for (const scope of scopes) {
315
- let exitCode = 0;
316
- if (scope === "agents-freshness") {
317
- exitCode = runAgentsFreshnessCheck({
318
- projectRoot: process.cwd(),
319
- config: governance.config.aiGovernance.agentsFreshness,
320
- });
321
- } else if (scope === "context-budget") {
322
- exitCode = await runContextBudget(governance.config);
323
- } else if (scope === "structure-budget") {
324
- exitCode = await runStructureBudget(governance.config);
325
- } else if (scope === "high-risk-doc-metadata") {
326
- exitCode = await runHighRiskDocMetadata(governance.config);
327
- }
328
-
329
- if (exitCode !== 0) {
330
- return exitCode;
331
- }
332
- }
333
-
334
- return 0;
335
- }
@@ -1 +0,0 @@
1
- export { withGitEvidenceSnapshot } from "./git-snapshot.mjs";