@neurcode-ai/cli 0.9.64 → 0.9.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/commands/bootstrap-policy.d.ts +29 -0
- package/dist/commands/bootstrap-policy.d.ts.map +1 -0
- package/dist/commands/bootstrap-policy.js +334 -0
- package/dist/commands/bootstrap-policy.js.map +1 -0
- package/dist/commands/brain.d.ts.map +1 -1
- package/dist/commands/brain.js +273 -0
- package/dist/commands/brain.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +82 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/pilot-report.d.ts +9 -0
- package/dist/commands/pilot-report.d.ts.map +1 -0
- package/dist/commands/pilot-report.js +176 -0
- package/dist/commands/pilot-report.js.map +1 -0
- package/dist/commands/quickstart.d.ts +21 -0
- package/dist/commands/quickstart.d.ts.map +1 -0
- package/dist/commands/quickstart.js +178 -0
- package/dist/commands/quickstart.js.map +1 -0
- package/dist/commands/remediate-export.d.ts +31 -0
- package/dist/commands/remediate-export.d.ts.map +1 -0
- package/dist/commands/remediate-export.js +283 -0
- package/dist/commands/remediate-export.js.map +1 -0
- package/dist/commands/remediate-governance.d.ts +54 -0
- package/dist/commands/remediate-governance.d.ts.map +1 -0
- package/dist/commands/remediate-governance.js +375 -0
- package/dist/commands/remediate-governance.js.map +1 -0
- package/dist/commands/remediate.d.ts.map +1 -1
- package/dist/commands/remediate.js.map +1 -1
- package/dist/commands/replay.d.ts.map +1 -1
- package/dist/commands/replay.js +30 -0
- package/dist/commands/replay.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +409 -30
- package/dist/commands/verify.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +1078 -0
- package/dist/daemon/server.js.map +1 -1
- package/dist/explainability/DeterminismClassifier.d.ts +34 -0
- package/dist/explainability/DeterminismClassifier.d.ts.map +1 -0
- package/dist/explainability/DeterminismClassifier.js +104 -0
- package/dist/explainability/DeterminismClassifier.js.map +1 -0
- package/dist/explainability/ViolationFormatter.d.ts +32 -0
- package/dist/explainability/ViolationFormatter.d.ts.map +1 -0
- package/dist/explainability/ViolationFormatter.js +252 -0
- package/dist/explainability/ViolationFormatter.js.map +1 -0
- package/dist/explainability/index.d.ts +15 -0
- package/dist/explainability/index.d.ts.map +1 -0
- package/dist/explainability/index.js +94 -0
- package/dist/explainability/index.js.map +1 -0
- package/dist/explainability/types.d.ts +37 -0
- package/dist/explainability/types.d.ts.map +1 -0
- package/dist/explainability/types.js +3 -0
- package/dist/explainability/types.js.map +1 -0
- package/dist/governance/canonical-invariants.d.ts +88 -0
- package/dist/governance/canonical-invariants.d.ts.map +1 -0
- package/dist/governance/canonical-invariants.js +197 -0
- package/dist/governance/canonical-invariants.js.map +1 -0
- package/dist/governance/canonical-ordering.d.ts +76 -0
- package/dist/governance/canonical-ordering.d.ts.map +1 -0
- package/dist/governance/canonical-ordering.js +189 -0
- package/dist/governance/canonical-ordering.js.map +1 -0
- package/dist/governance/canonical-pipeline.d.ts +45 -0
- package/dist/governance/canonical-pipeline.d.ts.map +1 -0
- package/dist/governance/canonical-pipeline.js +616 -0
- package/dist/governance/canonical-pipeline.js.map +1 -0
- package/dist/governance/diff-line-provenance.d.ts +59 -0
- package/dist/governance/diff-line-provenance.d.ts.map +1 -0
- package/dist/governance/diff-line-provenance.js +118 -0
- package/dist/governance/diff-line-provenance.js.map +1 -0
- package/dist/governance/pilot-readiness.d.ts +34 -0
- package/dist/governance/pilot-readiness.d.ts.map +1 -0
- package/dist/governance/pilot-readiness.js +226 -0
- package/dist/governance/pilot-readiness.js.map +1 -0
- package/dist/governance/policy-parity-validator.d.ts +62 -0
- package/dist/governance/policy-parity-validator.d.ts.map +1 -0
- package/dist/governance/policy-parity-validator.js +137 -0
- package/dist/governance/policy-parity-validator.js.map +1 -0
- package/dist/governance/remediation-boundary.d.ts +55 -0
- package/dist/governance/remediation-boundary.d.ts.map +1 -0
- package/dist/governance/remediation-boundary.js +120 -0
- package/dist/governance/remediation-boundary.js.map +1 -0
- package/dist/governance/structural-cache.d.ts +103 -0
- package/dist/governance/structural-cache.d.ts.map +1 -0
- package/dist/governance/structural-cache.js +240 -0
- package/dist/governance/structural-cache.js.map +1 -0
- package/dist/governance/structural-on-diff.d.ts +33 -0
- package/dist/governance/structural-on-diff.d.ts.map +1 -0
- package/dist/governance/structural-on-diff.js +67 -0
- package/dist/governance/structural-on-diff.js.map +1 -0
- package/dist/governance/structural-policy-merge.d.ts +22 -0
- package/dist/governance/structural-policy-merge.d.ts.map +1 -0
- package/dist/governance/structural-policy-merge.js +32 -0
- package/dist/governance/structural-policy-merge.js.map +1 -0
- package/dist/governance/verify-runtime-guard.d.ts +99 -0
- package/dist/governance/verify-runtime-guard.d.ts.map +1 -0
- package/dist/governance/verify-runtime-guard.js +129 -0
- package/dist/governance/verify-runtime-guard.js.map +1 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/review-compression/index.d.ts +50 -0
- package/dist/integrations/review-compression/index.d.ts.map +1 -0
- package/dist/integrations/review-compression/index.js +158 -0
- package/dist/integrations/review-compression/index.js.map +1 -0
- package/dist/intent-engine/domain-taxonomy.d.ts +42 -0
- package/dist/intent-engine/domain-taxonomy.d.ts.map +1 -0
- package/dist/intent-engine/domain-taxonomy.js +534 -0
- package/dist/intent-engine/domain-taxonomy.js.map +1 -0
- package/dist/intent-engine/index.d.ts +1 -0
- package/dist/intent-engine/index.d.ts.map +1 -1
- package/dist/intent-engine/index.js +6 -1
- package/dist/intent-engine/index.js.map +1 -1
- package/dist/intent-engine/parser.d.ts.map +1 -1
- package/dist/intent-engine/parser.js +47 -0
- package/dist/intent-engine/parser.js.map +1 -1
- package/dist/intent-engine/repo-classifier.d.ts +64 -0
- package/dist/intent-engine/repo-classifier.d.ts.map +1 -0
- package/dist/intent-engine/repo-classifier.js +178 -0
- package/dist/intent-engine/repo-classifier.js.map +1 -0
- package/dist/intent-engine/semantic-expander.d.ts +104 -0
- package/dist/intent-engine/semantic-expander.d.ts.map +1 -0
- package/dist/intent-engine/semantic-expander.js +480 -0
- package/dist/intent-engine/semantic-expander.js.map +1 -0
- package/dist/patch-engine/patterns.d.ts.map +1 -1
- package/dist/patch-engine/patterns.js +8 -4
- package/dist/patch-engine/patterns.js.map +1 -1
- package/dist/semantic/index.d.ts +14 -0
- package/dist/semantic/index.d.ts.map +1 -0
- package/dist/semantic/index.js +30 -0
- package/dist/semantic/index.js.map +1 -0
- package/dist/semantic/tfidf-engine.d.ts +81 -0
- package/dist/semantic/tfidf-engine.d.ts.map +1 -0
- package/dist/semantic/tfidf-engine.js +278 -0
- package/dist/semantic/tfidf-engine.js.map +1 -0
- package/dist/semantic/vector-store.d.ts +108 -0
- package/dist/semantic/vector-store.d.ts.map +1 -0
- package/dist/semantic/vector-store.js +321 -0
- package/dist/semantic/vector-store.js.map +1 -0
- package/dist/structural-rules/context-severity.d.ts +46 -0
- package/dist/structural-rules/context-severity.d.ts.map +1 -0
- package/dist/structural-rules/context-severity.js +115 -0
- package/dist/structural-rules/context-severity.js.map +1 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.d.ts +11 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.d.ts.map +1 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.js +212 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.js.map +1 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.d.ts +11 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.d.ts.map +1 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.js +213 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.js.map +1 -0
- package/dist/structural-rules/distributed/index.d.ts +3 -0
- package/dist/structural-rules/distributed/index.d.ts.map +1 -0
- package/dist/structural-rules/distributed/index.js +8 -0
- package/dist/structural-rules/distributed/index.js.map +1 -0
- package/dist/structural-rules/engine.d.ts +25 -0
- package/dist/structural-rules/engine.d.ts.map +1 -0
- package/dist/structural-rules/engine.js +90 -0
- package/dist/structural-rules/engine.js.map +1 -0
- package/dist/structural-rules/index.d.ts +45 -0
- package/dist/structural-rules/index.d.ts.map +1 -0
- package/dist/structural-rules/index.js +158 -0
- package/dist/structural-rules/index.js.map +1 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.d.ts +11 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.d.ts.map +1 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.js +66 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.js.map +1 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.d.ts +11 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.d.ts.map +1 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.js +135 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.js.map +1 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.d.ts +32 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.d.ts.map +1 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.js +277 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.js.map +1 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.d.ts +11 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.d.ts.map +1 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.js +167 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.js.map +1 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.d.ts +11 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.d.ts.map +1 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.js +154 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.js.map +1 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.d.ts +11 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.d.ts.map +1 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.js +130 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.js.map +1 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.d.ts +11 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.d.ts.map +1 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.js +93 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.js.map +1 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.d.ts +11 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.d.ts.map +1 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.js +154 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.js.map +1 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.d.ts +11 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.d.ts.map +1 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.js +133 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.js.map +1 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.d.ts +11 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.d.ts.map +1 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.js +80 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.js.map +1 -0
- package/dist/structural-rules/python/PY011-thread-lifecycle.d.ts +11 -0
- package/dist/structural-rules/python/PY011-thread-lifecycle.d.ts.map +1 -0
- package/dist/structural-rules/python/PY011-thread-lifecycle.js +97 -0
- package/dist/structural-rules/python/PY011-thread-lifecycle.js.map +1 -0
- package/dist/structural-rules/python/PY012-asyncio-run-misuse.d.ts +11 -0
- package/dist/structural-rules/python/PY012-asyncio-run-misuse.d.ts.map +1 -0
- package/dist/structural-rules/python/PY012-asyncio-run-misuse.js +83 -0
- package/dist/structural-rules/python/PY012-asyncio-run-misuse.js.map +1 -0
- package/dist/structural-rules/python/PY013-mutable-default-arg.d.ts +11 -0
- package/dist/structural-rules/python/PY013-mutable-default-arg.d.ts.map +1 -0
- package/dist/structural-rules/python/PY013-mutable-default-arg.js +73 -0
- package/dist/structural-rules/python/PY013-mutable-default-arg.js.map +1 -0
- package/dist/structural-rules/python/PY014-fixed-sleep-retry.d.ts +11 -0
- package/dist/structural-rules/python/PY014-fixed-sleep-retry.d.ts.map +1 -0
- package/dist/structural-rules/python/PY014-fixed-sleep-retry.js +115 -0
- package/dist/structural-rules/python/PY014-fixed-sleep-retry.js.map +1 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.d.ts +11 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.js +145 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.js.map +1 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.d.ts +11 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.js +196 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.js.map +1 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.d.ts +11 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.js +148 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.js.map +1 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.d.ts +11 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.js +162 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.js.map +1 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.d.ts +11 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.js +150 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.js.map +1 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.d.ts +11 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.js +161 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.js.map +1 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.d.ts +11 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.js +175 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.js.map +1 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.d.ts +11 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.js +176 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.js.map +1 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.d.ts +11 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.js +168 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.js.map +1 -0
- package/dist/structural-rules/rules/SR010-retry-storm.d.ts +11 -0
- package/dist/structural-rules/rules/SR010-retry-storm.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR010-retry-storm.js +181 -0
- package/dist/structural-rules/rules/SR010-retry-storm.js.map +1 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.d.ts +11 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.js +208 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.js.map +1 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.d.ts +11 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.js +191 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.js.map +1 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.d.ts +11 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.js +219 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.js.map +1 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.d.ts +11 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.js +208 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.js.map +1 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.d.ts +11 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.js +190 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.js.map +1 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.d.ts +11 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.js +187 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.js.map +1 -0
- package/dist/structural-rules/suppressions.d.ts +43 -0
- package/dist/structural-rules/suppressions.d.ts.map +1 -0
- package/dist/structural-rules/suppressions.js +115 -0
- package/dist/structural-rules/suppressions.js.map +1 -0
- package/dist/structural-rules/types.d.ts +55 -0
- package/dist/structural-rules/types.d.ts.map +1 -0
- package/dist/structural-rules/types.js +3 -0
- package/dist/structural-rules/types.js.map +1 -0
- package/dist/utils/brain-cache.d.ts +100 -0
- package/dist/utils/brain-cache.d.ts.map +1 -0
- package/dist/utils/brain-cache.js +346 -0
- package/dist/utils/brain-cache.js.map +1 -0
- package/dist/utils/governance-provenance.d.ts +95 -0
- package/dist/utils/governance-provenance.d.ts.map +1 -0
- package/dist/utils/governance-provenance.js +187 -0
- package/dist/utils/governance-provenance.js.map +1 -0
- package/dist/utils/pilot-metrics.d.ts +46 -0
- package/dist/utils/pilot-metrics.d.ts.map +1 -0
- package/dist/utils/pilot-metrics.js +240 -0
- package/dist/utils/pilot-metrics.js.map +1 -0
- package/dist/utils/replay-runtime.d.ts +34 -0
- package/dist/utils/replay-runtime.d.ts.map +1 -1
- package/dist/utils/replay-runtime.js +207 -0
- package/dist/utils/replay-runtime.js.map +1 -1
- package/dist/utils/verify-runtime-stability.d.ts +142 -0
- package/dist/utils/verify-runtime-stability.d.ts.map +1 -0
- package/dist/utils/verify-runtime-stability.js +230 -0
- package/dist/utils/verify-runtime-stability.js.map +1 -0
- package/dist/workspace/cross-repo-graph.d.ts +111 -0
- package/dist/workspace/cross-repo-graph.d.ts.map +1 -0
- package/dist/workspace/cross-repo-graph.js +450 -0
- package/dist/workspace/cross-repo-graph.js.map +1 -0
- package/dist/workspace/federated-context.d.ts +144 -0
- package/dist/workspace/federated-context.d.ts.map +1 -0
- package/dist/workspace/federated-context.js +347 -0
- package/dist/workspace/federated-context.js.map +1 -0
- package/dist/workspace/index.d.ts +38 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +48 -0
- package/dist/workspace/index.js.map +1 -0
- package/package.json +9 -9
package/dist/commands/verify.js
CHANGED
|
@@ -67,11 +67,24 @@ const policy_compiler_1 = require("../utils/policy-compiler");
|
|
|
67
67
|
const change_contract_1 = require("../utils/change-contract");
|
|
68
68
|
const diff_symbols_1 = require("../utils/diff-symbols");
|
|
69
69
|
const advisory_signals_1 = require("../utils/advisory-signals");
|
|
70
|
+
const structural_rules_1 = require("../structural-rules");
|
|
71
|
+
const canonical_pipeline_1 = require("../governance/canonical-pipeline");
|
|
72
|
+
const canonical_invariants_1 = require("../governance/canonical-invariants");
|
|
73
|
+
const structural_on_diff_1 = require("../governance/structural-on-diff");
|
|
74
|
+
// NOTE: mergeStructuralIntoPolicyViolations is intentionally NOT imported.
|
|
75
|
+
// Structural violations flow exclusively through payload.structuralViolations
|
|
76
|
+
// into the canonical pipeline. Merging them into policyViolations caused
|
|
77
|
+
// duplicate GovernanceFinding objects (fixed in Phase 1 canonical graph hardening).
|
|
78
|
+
const telemetry_1 = require("@neurcode-ai/telemetry");
|
|
79
|
+
const governance_provenance_1 = require("../utils/governance-provenance");
|
|
80
|
+
const pilot_metrics_1 = require("../utils/pilot-metrics");
|
|
81
|
+
const explainability_1 = require("../explainability");
|
|
70
82
|
const runtime_guard_1 = require("../utils/runtime-guard");
|
|
71
83
|
const artifact_signature_1 = require("../utils/artifact-signature");
|
|
72
84
|
const policy_1 = require("@neurcode-ai/policy");
|
|
73
85
|
const ai_debt_budget_1 = require("../utils/ai-debt-budget");
|
|
74
86
|
const verification_evidence_1 = require("../utils/verification-evidence");
|
|
87
|
+
const verify_runtime_stability_1 = require("../utils/verify-runtime-stability");
|
|
75
88
|
// Import chalk with fallback
|
|
76
89
|
let chalk;
|
|
77
90
|
try {
|
|
@@ -92,6 +105,38 @@ catch {
|
|
|
92
105
|
white: (str) => str,
|
|
93
106
|
};
|
|
94
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Structured CI explainability for `neurcode verify --ci` / `--policy-only` human output.
|
|
110
|
+
* Keeps logs short — no JSON dumps — and separates merge-blocking vs advisory signals.
|
|
111
|
+
*/
|
|
112
|
+
function logCiPolicyOnlyOutcomeExplainability(params) {
|
|
113
|
+
if (!params.ciModeEnabled || params.json) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const modeLine = params.source === 'ci'
|
|
117
|
+
? '`verify --ci` uses deterministic local governance (compiled/custom policy + structural rules). Remote plan-verify API is not used.'
|
|
118
|
+
: '`--policy-only` — local policy + structural governance without plan adherence.';
|
|
119
|
+
const sev = (s) => String(s || '').toLowerCase();
|
|
120
|
+
const sBlock = params.structuralViolations.filter((v) => v.severity === 'BLOCKING').length;
|
|
121
|
+
const sAdv = params.structuralViolations.length - sBlock;
|
|
122
|
+
const pBlock = params.policyViolations.filter((v) => sev(v.severity) === 'block').length;
|
|
123
|
+
const pWarn = params.policyViolations.filter((v) => sev(v.severity) === 'warn').length;
|
|
124
|
+
if (params.verdict === 'PASS') {
|
|
125
|
+
console.log(chalk.dim('\n── CI verify contract ──'));
|
|
126
|
+
console.log(chalk.dim(` ${modeLine}`));
|
|
127
|
+
console.log(chalk.dim(' Exit 0: no blocking severities. Replay checksum (JSON) anchors structural findings for audit parity.'));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
console.log(chalk.bold.red('\n── CI failure explainability ──'));
|
|
131
|
+
console.log(chalk.dim(` ${modeLine}`));
|
|
132
|
+
console.log(chalk.red(` Merge-blocking rows: structural BLOCKING ${sBlock}; policy/custom severity=block ${pBlock}`));
|
|
133
|
+
console.log(chalk.yellow(` Non-blocking (warn/advisory-class): structural advisory ${sAdv}; policy warn ${pWarn} — does not fail CI unless your gate maps warns to failure`));
|
|
134
|
+
console.log(chalk.dim(' Offline / structural-only: set NEURCODE_VERIFY_LOCAL_ONLY=1 or `--local-only` to skip API compatibility probes (AST gates still run).'));
|
|
135
|
+
if (params.replayChecksum) {
|
|
136
|
+
console.log(chalk.dim(` Structural replay checksum: ${params.replayChecksum.slice(0, 16)}… · mode ${params.replayMode ?? 'local-structural'}`));
|
|
137
|
+
}
|
|
138
|
+
console.log(chalk.dim(' Next: resolve BLOCKING first → `neurcode remediate-export` (optional) → re-run `neurcode verify --ci`.\n'));
|
|
139
|
+
}
|
|
95
140
|
;
|
|
96
141
|
function toArtifactSignatureSummary(status) {
|
|
97
142
|
return {
|
|
@@ -1080,10 +1125,17 @@ function toCanonicalVerifyOutput(payload) {
|
|
|
1080
1125
|
'policyDecision',
|
|
1081
1126
|
'policyPack',
|
|
1082
1127
|
'changeContractViolations',
|
|
1128
|
+
'governanceVerification',
|
|
1129
|
+
'governanceFindings',
|
|
1130
|
+
'structuralViolations',
|
|
1131
|
+
'structuralRulesApplied',
|
|
1132
|
+
'structuralSuppressedCount',
|
|
1083
1133
|
];
|
|
1134
|
+
const canonicalMutable = canonical;
|
|
1084
1135
|
for (const key of passthroughKeys) {
|
|
1085
|
-
|
|
1086
|
-
|
|
1136
|
+
const v = payload[key];
|
|
1137
|
+
if (Object.prototype.hasOwnProperty.call(payload, key) && v !== undefined && v !== null) {
|
|
1138
|
+
canonicalMutable[key] = v;
|
|
1087
1139
|
}
|
|
1088
1140
|
}
|
|
1089
1141
|
// Backward-compatibility alias: older integrations and tests expect `rule`
|
|
@@ -1099,7 +1151,7 @@ function toCanonicalVerifyOutput(payload) {
|
|
|
1099
1151
|
return canonical;
|
|
1100
1152
|
}
|
|
1101
1153
|
function emitCanonicalVerifyJson(payload, onEmit) {
|
|
1102
|
-
const canonical = toCanonicalVerifyOutput(payload);
|
|
1154
|
+
const canonical = toCanonicalVerifyOutput((0, canonical_pipeline_1.attachCanonicalGovernance)(payload));
|
|
1103
1155
|
onEmit?.(canonical);
|
|
1104
1156
|
// Use sync stdout write so immediate process.exit paths do not truncate JSON.
|
|
1105
1157
|
const serialized = Buffer.from(`${JSON.stringify(canonical, null, 2)}\n`, 'utf-8');
|
|
@@ -1916,6 +1968,10 @@ async function executePolicyOnlyMode(options, diffFiles, ignoreFilter, projectRo
|
|
|
1916
1968
|
message: `Policy audit chain is invalid: ${auditIntegrityStatus.issues.join('; ') || 'unknown issue'}`,
|
|
1917
1969
|
});
|
|
1918
1970
|
}
|
|
1971
|
+
const policyOnlyStructural = (0, structural_on_diff_1.runStructuralOnDiffFiles)(projectRoot, diffFilesForPolicy);
|
|
1972
|
+
// Structural violations are passed to the canonical pipeline via payload.structuralViolations
|
|
1973
|
+
// (see line ~2584). Do NOT merge them into policyViolations — that would create structural:*
|
|
1974
|
+
// duplicates that contaminate the canonical finding graph.
|
|
1919
1975
|
policyDecision = resolvePolicyDecisionFromViolations(policyViolations);
|
|
1920
1976
|
const effectiveVerdict = policyDecision === 'block' ? 'FAIL' : policyDecision === 'warn' ? 'WARN' : 'PASS';
|
|
1921
1977
|
const grade = effectiveVerdict === 'PASS' ? 'A' : effectiveVerdict === 'WARN' ? 'C' : 'F';
|
|
@@ -1972,6 +2028,11 @@ async function executePolicyOnlyMode(options, diffFiles, ignoreFilter, projectRo
|
|
|
1972
2028
|
eventCount: auditIntegrity.count,
|
|
1973
2029
|
},
|
|
1974
2030
|
};
|
|
2031
|
+
// Phase 4: Compute replay checksum from structural findings so replayChecksum
|
|
2032
|
+
// is populated in --policy-only and --local-only CI/daemonless modes.
|
|
2033
|
+
// This closes the N/A gap identified in the Apache Airflow benchmark.
|
|
2034
|
+
const policyOnlyStructuralFindings = policyOnlyStructural.violations.map(canonical_pipeline_1.findingFromStructural);
|
|
2035
|
+
const policyOnlyReplayChecksum = (0, canonical_invariants_1.computeCanonicalFindingChecksum)(policyOnlyStructuralFindings);
|
|
1975
2036
|
const policyOnlyPayload = {
|
|
1976
2037
|
grade,
|
|
1977
2038
|
score,
|
|
@@ -1984,9 +2045,14 @@ async function executePolicyOnlyMode(options, diffFiles, ignoreFilter, projectRo
|
|
|
1984
2045
|
plannedFilesModified: 0,
|
|
1985
2046
|
totalPlannedFiles: 0,
|
|
1986
2047
|
adherenceScore: score,
|
|
2048
|
+
structuralViolations: policyOnlyStructural.violations,
|
|
2049
|
+
structuralRulesApplied: policyOnlyStructural.rulesApplied,
|
|
2050
|
+
structuralSuppressedCount: policyOnlyStructural.suppressedCount,
|
|
1987
2051
|
mode: 'policy_only',
|
|
1988
2052
|
policyOnly: true,
|
|
1989
2053
|
policyOnlySource: source,
|
|
2054
|
+
replayChecksum: policyOnlyReplayChecksum,
|
|
2055
|
+
replayMode: 'local-structural',
|
|
1990
2056
|
...governancePayload,
|
|
1991
2057
|
policyLock: {
|
|
1992
2058
|
enforced: policyLockEvaluation.enforced,
|
|
@@ -2037,6 +2103,16 @@ async function executePolicyOnlyMode(options, diffFiles, ignoreFilter, projectRo
|
|
|
2037
2103
|
}
|
|
2038
2104
|
displayGovernanceInsights(governanceAnalysis, { explain: options.explain });
|
|
2039
2105
|
console.log(chalk.dim(`\n${message}`));
|
|
2106
|
+
logCiPolicyOnlyOutcomeExplainability({
|
|
2107
|
+
ciModeEnabled,
|
|
2108
|
+
json: Boolean(options.json),
|
|
2109
|
+
verdict: effectiveVerdict,
|
|
2110
|
+
source,
|
|
2111
|
+
structuralViolations: policyOnlyStructural.violations,
|
|
2112
|
+
policyViolations,
|
|
2113
|
+
replayChecksum: policyOnlyReplayChecksum,
|
|
2114
|
+
replayMode: 'local-structural',
|
|
2115
|
+
});
|
|
2040
2116
|
}
|
|
2041
2117
|
await recordPolicyOnlyVerification({
|
|
2042
2118
|
grade,
|
|
@@ -2067,9 +2143,18 @@ async function verifyCommand(options) {
|
|
|
2067
2143
|
const evidenceEnabled = options.evidence === true || isEnabledFlag(process.env.NEURCODE_VERIFY_EVIDENCE);
|
|
2068
2144
|
const verifyStartedAtMs = Date.now();
|
|
2069
2145
|
const evidenceCiContext = collectCIContext();
|
|
2146
|
+
/** Set when provenance is written (human path); JSON early-exit may leave null. */
|
|
2147
|
+
let lastProvenanceRunId = null;
|
|
2070
2148
|
let lastCanonicalOutput = null;
|
|
2071
2149
|
let lastEvidenceFallbackOutput = null;
|
|
2072
2150
|
let evidenceFinalizeAttempted = false;
|
|
2151
|
+
// ── Phase 1 Runtime Stability: create context early so all subsystems share it ──
|
|
2152
|
+
// Structural governance is NEVER gated by this context — it always runs.
|
|
2153
|
+
const runtimeCtx = (0, verify_runtime_stability_1.createVerifyRuntimeContext)(ciModeEnabled);
|
|
2154
|
+
// Large repo detection: sets largeRepoMode and emits cache-build recommendation.
|
|
2155
|
+
(0, verify_runtime_stability_1.applyLargeRepoProtection)(runtimeCtx, projectRoot);
|
|
2156
|
+
// Initial memory pressure check at entry.
|
|
2157
|
+
(0, verify_runtime_stability_1.applyMemoryPressureDegradation)(runtimeCtx);
|
|
2073
2158
|
if (ciModeEnabled) {
|
|
2074
2159
|
options.policyOnly = true;
|
|
2075
2160
|
options.requirePlan = false;
|
|
@@ -2120,6 +2205,12 @@ async function verifyCommand(options) {
|
|
|
2120
2205
|
};
|
|
2121
2206
|
const exitWithEvidence = (exitCode) => {
|
|
2122
2207
|
finalizeEvidence(exitCode);
|
|
2208
|
+
try {
|
|
2209
|
+
(0, telemetry_1.appendVerifyCompletedFromCanonical)(projectRoot, lastCanonicalOutput, lastProvenanceRunId);
|
|
2210
|
+
}
|
|
2211
|
+
catch {
|
|
2212
|
+
// calibration must never affect exit
|
|
2213
|
+
}
|
|
2123
2214
|
process.exit(exitCode);
|
|
2124
2215
|
};
|
|
2125
2216
|
exitWithEvidenceFromTry = exitWithEvidence;
|
|
@@ -2130,7 +2221,14 @@ async function verifyCommand(options) {
|
|
|
2130
2221
|
let intentEngineSummary = null;
|
|
2131
2222
|
let intentEngineFlowIssues = [];
|
|
2132
2223
|
let intentEngineRegressions = [];
|
|
2224
|
+
// Structural rule engine results — AST-level deterministic violations
|
|
2225
|
+
let structuralViolations = [];
|
|
2226
|
+
let structuralRulesApplied = [];
|
|
2227
|
+
let structuralSuppressedCount = 0;
|
|
2133
2228
|
const emitVerifyJson = (payload) => {
|
|
2229
|
+
// Check memory pressure immediately before emission (may have changed during long verify)
|
|
2230
|
+
(0, verify_runtime_stability_1.applyMemoryPressureDegradation)(runtimeCtx);
|
|
2231
|
+
const runtimeStabilityReport = (0, verify_runtime_stability_1.buildVerifyRuntimeReport)(runtimeCtx);
|
|
2134
2232
|
const enrichedPayload = {
|
|
2135
2233
|
...payload,
|
|
2136
2234
|
ciMode: payload.ciMode ?? ciModeEnabled,
|
|
@@ -2143,6 +2241,11 @@ async function verifyCommand(options) {
|
|
|
2143
2241
|
flowIssues: payload.flowIssues ?? intentEngineFlowIssues,
|
|
2144
2242
|
// V6: regressions always injected
|
|
2145
2243
|
regressions: payload.regressions ?? intentEngineRegressions,
|
|
2244
|
+
structuralViolations: payload.structuralViolations ?? structuralViolations,
|
|
2245
|
+
structuralRulesApplied: payload.structuralRulesApplied ?? structuralRulesApplied,
|
|
2246
|
+
structuralSuppressedCount: payload.structuralSuppressedCount ?? structuralSuppressedCount,
|
|
2247
|
+
// Runtime stability transparency — always present
|
|
2248
|
+
runtimeStabilityReport,
|
|
2146
2249
|
};
|
|
2147
2250
|
lastEvidenceFallbackOutput = enrichedPayload;
|
|
2148
2251
|
emitCanonicalVerifyJson(enrichedPayload, (canonical) => {
|
|
@@ -2461,10 +2564,14 @@ async function verifyCommand(options) {
|
|
|
2461
2564
|
console.log(chalk.dim(' CI mode: deterministic local verification enabled (policy-only, non-interactive).'));
|
|
2462
2565
|
}
|
|
2463
2566
|
}
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
||
|
|
2467
|
-
|
|
2567
|
+
// NEURCODE_VERIFY_LOCAL_ONLY=1 or --local-only: skip API entirely, run structural-only
|
|
2568
|
+
const localOnlyMode = isEnabledFlag(process.env.NEURCODE_VERIFY_LOCAL_ONLY)
|
|
2569
|
+
|| options.localOnly === true;
|
|
2570
|
+
const enforceCompatibilityHandshake = !localOnlyMode
|
|
2571
|
+
&& (isEnabledFlag(process.env.NEURCODE_VERIFY_ENFORCE_COMPAT_HANDSHAKE)
|
|
2572
|
+
|| strictArtifactMode
|
|
2573
|
+
|| (process.env.CI === 'true' && Boolean(config.apiKey)));
|
|
2574
|
+
if (!localOnlyMode && config.apiKey && config.apiUrl) {
|
|
2468
2575
|
const compatibilityProbe = await probeApiRuntimeCompatibility(config.apiUrl);
|
|
2469
2576
|
if (compatibilityProbe.status !== 'ok' && enforceCompatibilityHandshake) {
|
|
2470
2577
|
const failureMessages = compatibilityProbe.messages.length > 0
|
|
@@ -2493,6 +2600,7 @@ async function verifyCommand(options) {
|
|
|
2493
2600
|
mode: 'runtime_compatibility_failed',
|
|
2494
2601
|
policyOnly: options.policyOnly === true,
|
|
2495
2602
|
changeContract: changeContractSummary,
|
|
2603
|
+
offlineFallbackHint: 'Run with NEURCODE_VERIFY_LOCAL_ONLY=1 or --local-only for offline structural verification.',
|
|
2496
2604
|
...(compiledPolicyMetadata ? { policyCompilation: compiledPolicyMetadata } : {}),
|
|
2497
2605
|
});
|
|
2498
2606
|
}
|
|
@@ -2507,6 +2615,7 @@ async function verifyCommand(options) {
|
|
|
2507
2615
|
}
|
|
2508
2616
|
console.log(chalk.dim(` CLI version: ${CLI_COMPONENT_VERSION}`));
|
|
2509
2617
|
console.log(chalk.dim(' Upgrade/downgrade CLI, Action, or API to satisfy the runtime compatibility contract before running verify.\n'));
|
|
2618
|
+
console.log(chalk.dim(' Tip: Use --local-only to run offline deterministic structural verification without the API.\n'));
|
|
2510
2619
|
}
|
|
2511
2620
|
exitWithEvidence(2);
|
|
2512
2621
|
}
|
|
@@ -2581,8 +2690,19 @@ async function verifyCommand(options) {
|
|
|
2581
2690
|
try {
|
|
2582
2691
|
let contextNote = note;
|
|
2583
2692
|
if (Array.isArray(changedFiles) && changedFiles.length > 0) {
|
|
2584
|
-
|
|
2585
|
-
|
|
2693
|
+
// Runtime stability: skip brain context refresh if semantic layer is degraded
|
|
2694
|
+
// (memory pressure or time pressure). Structural verification is unaffected.
|
|
2695
|
+
if ((0, verify_runtime_stability_1.shouldSkipSemanticLayer)(runtimeCtx)) {
|
|
2696
|
+
contextNote = `${contextNote};semantic_skipped=runtime_pressure`;
|
|
2697
|
+
if (!ciModeEnabled && runtimeCtx.degradationReasons.length > 0) {
|
|
2698
|
+
console.log(chalk.yellow(`\n⚠️ Brain context refresh skipped: ${runtimeCtx.degradationReasons[runtimeCtx.degradationReasons.length - 1]}`));
|
|
2699
|
+
console.log(chalk.dim(' Deterministic structural governance continues unaffected.\n'));
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
else {
|
|
2703
|
+
const refreshed = (0, brain_context_1.refreshBrainContextForFiles)(projectRoot, brainScope, changedFiles);
|
|
2704
|
+
contextNote = `${contextNote};indexed=${refreshed.indexed};removed=${refreshed.removed};skipped=${refreshed.skipped}`;
|
|
2705
|
+
}
|
|
2586
2706
|
}
|
|
2587
2707
|
(0, brain_context_1.recordBrainProgressEvent)(projectRoot, brainScope, {
|
|
2588
2708
|
type: 'verify',
|
|
@@ -2726,6 +2846,64 @@ async function verifyCommand(options) {
|
|
|
2726
2846
|
const excludeOldPath = file.oldPath ? isExcludedFile(file.oldPath) : false;
|
|
2727
2847
|
return !excludePath && !excludeOldPath;
|
|
2728
2848
|
});
|
|
2849
|
+
// ── Local-only mode (Part 8): run structural analysis and exit, no API calls ──
|
|
2850
|
+
// Triggered by NEURCODE_VERIFY_LOCAL_ONLY=1 or --local-only.
|
|
2851
|
+
// Deterministic structural governance MUST work offline, with zero API dependency.
|
|
2852
|
+
if (localOnlyMode) {
|
|
2853
|
+
if (!options.json) {
|
|
2854
|
+
console.log(chalk.cyan('\n🔍 Local-only mode: deterministic structural verification (no API required)...'));
|
|
2855
|
+
}
|
|
2856
|
+
const localStructural = (0, structural_on_diff_1.runStructuralOnDiffFiles)(projectRoot, diffFiles);
|
|
2857
|
+
const blockingViolations = localStructural.violations.filter((v) => v.severity === 'BLOCKING');
|
|
2858
|
+
const localVerdict = blockingViolations.length > 0 ? 'FAIL' : 'PASS';
|
|
2859
|
+
const localGrade = blockingViolations.length > 0 ? 'F' : 'B';
|
|
2860
|
+
const localScore = blockingViolations.length > 0 ? 0 : 70;
|
|
2861
|
+
if (options.json) {
|
|
2862
|
+
emitVerifyJson({
|
|
2863
|
+
grade: localGrade,
|
|
2864
|
+
score: localScore,
|
|
2865
|
+
verdict: localVerdict,
|
|
2866
|
+
violations: localStructural.violations.map((v) => ({
|
|
2867
|
+
file: v.filePath,
|
|
2868
|
+
rule: v.ruleId,
|
|
2869
|
+
severity: v.severity === 'BLOCKING' ? 'block' : 'warn',
|
|
2870
|
+
message: `${v.ruleName}: ${v.evidence.slice(0, 120)}`,
|
|
2871
|
+
})),
|
|
2872
|
+
adherenceScore: localScore,
|
|
2873
|
+
bloatCount: 0,
|
|
2874
|
+
bloatFiles: [],
|
|
2875
|
+
plannedFilesModified: 0,
|
|
2876
|
+
totalPlannedFiles: 0,
|
|
2877
|
+
message: `Local-only structural verification: ${localStructural.violations.length} finding(s), ${blockingViolations.length} blocking.`,
|
|
2878
|
+
scopeGuardPassed: true,
|
|
2879
|
+
mode: 'local_only_structural',
|
|
2880
|
+
policyOnly: true,
|
|
2881
|
+
structuralViolations: localStructural.violations,
|
|
2882
|
+
structuralBlockingCount: blockingViolations.length,
|
|
2883
|
+
structuralRulesApplied: localStructural.rulesApplied,
|
|
2884
|
+
changeContract: changeContractSummary,
|
|
2885
|
+
});
|
|
2886
|
+
}
|
|
2887
|
+
else {
|
|
2888
|
+
if (localStructural.violations.length === 0) {
|
|
2889
|
+
console.log(chalk.green('\n✅ No structural violations found (local-only mode).'));
|
|
2890
|
+
}
|
|
2891
|
+
else {
|
|
2892
|
+
localStructural.violations.forEach((v) => {
|
|
2893
|
+
const prefix = v.severity === 'BLOCKING' ? chalk.red(' ⛔ BLOCKING') : chalk.yellow(' ⚠ ADVISORY');
|
|
2894
|
+
console.log(`${prefix} ${v.ruleId} — ${v.filePath}:${v.line}`);
|
|
2895
|
+
console.log(chalk.dim(` ${v.ruleName}`));
|
|
2896
|
+
console.log(chalk.dim(` ${v.evidence.slice(0, 100)}`));
|
|
2897
|
+
});
|
|
2898
|
+
}
|
|
2899
|
+
console.log(chalk.dim(`\n[Local-only] ${localStructural.violations.length} finding(s), ${blockingViolations.length} blocking. ` +
|
|
2900
|
+
`Structural analysis ran on this checkout only (no verify API).\n`));
|
|
2901
|
+
console.log(chalk.dim(' Replay: same commit + same flags → same structural findings.\n' +
|
|
2902
|
+
' Full plan/adherence + remote verify: drop --local-only when policy allows network/API.\n'));
|
|
2903
|
+
}
|
|
2904
|
+
recordVerifyEvent(localVerdict, `local_only;structural=${localStructural.violations.length}`, diffFiles.map((f) => f.path));
|
|
2905
|
+
exitWithEvidence(blockingViolations.length > 0 ? 2 : 0);
|
|
2906
|
+
}
|
|
2729
2907
|
const summary = (0, diff_parser_1.getDiffSummary)(diffFiles);
|
|
2730
2908
|
if (diffFiles.length === 0) {
|
|
2731
2909
|
if (!options.json) {
|
|
@@ -3119,20 +3297,59 @@ async function verifyCommand(options) {
|
|
|
3119
3297
|
}
|
|
3120
3298
|
const message = 'No plan linked yet. Ran advisory verification for quick first-run experience. ' +
|
|
3121
3299
|
'Use `neurcode plan` and `neurcode contract import --auto-detect --write-change-contract` for full enforcement.';
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3300
|
+
// Runtime stability: skip advisory signals if advisory layer is degraded.
|
|
3301
|
+
// Structural rules always run regardless.
|
|
3302
|
+
const advisorySignals = (0, verify_runtime_stability_1.shouldSkipAdvisoryLayer)(runtimeCtx)
|
|
3303
|
+
? []
|
|
3304
|
+
: (0, advisory_signals_1.evaluateAdvisorySignals)({ diffFiles, summary });
|
|
3305
|
+
if ((0, verify_runtime_stability_1.shouldSkipAdvisoryLayer)(runtimeCtx) && !options.json) {
|
|
3306
|
+
console.log(chalk.dim(' Advisory signals skipped (runtime pressure — structural governance unaffected).'));
|
|
3307
|
+
}
|
|
3126
3308
|
const advisoryWarnCount = advisorySignals.filter((item) => item.severity === 'warn').length;
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3309
|
+
// ── Advisory-first: always run structural rules, downgrade scope issues to advisory ──
|
|
3310
|
+
// Structural rules are deterministic and local — they MUST always run regardless of plan.
|
|
3311
|
+
let advisoryStructuralViolations = [];
|
|
3312
|
+
let advisoryStructuralBlockingCount = 0;
|
|
3313
|
+
try {
|
|
3314
|
+
if (!options.json) {
|
|
3315
|
+
console.log(chalk.cyan('🔍 Running deterministic structural analysis (advisory mode — no plan)...'));
|
|
3316
|
+
}
|
|
3317
|
+
const structuralResult = (0, structural_on_diff_1.runStructuralOnDiffFiles)(projectRoot, diffFiles);
|
|
3318
|
+
advisoryStructuralViolations = structuralResult.violations;
|
|
3319
|
+
// In advisory mode (no plan), BLOCKING structural violations are downgraded to advisory warnings.
|
|
3320
|
+
// They are still surfaced — engineers must review them — but they do not block the verify exit.
|
|
3321
|
+
advisoryStructuralBlockingCount = structuralResult.violations.filter((v) => v.severity === 'BLOCKING').length;
|
|
3322
|
+
if (!options.json && advisoryStructuralViolations.length > 0) {
|
|
3323
|
+
console.log(chalk.yellow(`\n⚠ Structural findings (advisory — link a plan to enable enforcement):`));
|
|
3324
|
+
advisoryStructuralViolations.forEach((v) => {
|
|
3325
|
+
const prefix = v.severity === 'BLOCKING' ? chalk.yellow(' ⚠ BLOCKING (advisory)') : chalk.dim(' ℹ ADVISORY');
|
|
3326
|
+
console.log(`${prefix} ${v.ruleId} — ${v.filePath}:${v.line}`);
|
|
3327
|
+
console.log(chalk.dim(` ${v.ruleName}`));
|
|
3328
|
+
console.log(chalk.dim(` ${v.evidence.slice(0, 100)}`));
|
|
3329
|
+
});
|
|
3330
|
+
console.log(chalk.dim(`\n To enforce these findings: run \`neurcode plan "<intent>"\` to link a plan.\n`));
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
3333
|
+
catch {
|
|
3334
|
+
// Structural engine failure must never block advisory verify
|
|
3335
|
+
}
|
|
3336
|
+
const advisoryVerdict = advisoryWarnCount > 0 || advisoryStructuralBlockingCount > 0 ? 'WARN' : 'PASS';
|
|
3337
|
+
const advisoryGrade = advisoryWarnCount > 0 || advisoryStructuralBlockingCount > 0 ? 'C' : 'B';
|
|
3338
|
+
const advisoryScore = advisoryWarnCount > 0 || advisoryStructuralBlockingCount > 0 ? 60 : 70;
|
|
3339
|
+
const advisoryViolations = [
|
|
3340
|
+
...advisorySignals.map((item) => ({
|
|
3341
|
+
file: item.files[0] || '.',
|
|
3342
|
+
rule: `advisory:${item.code.toLowerCase()}`,
|
|
3343
|
+
severity: item.severity === 'warn' ? 'warn' : 'allow',
|
|
3344
|
+
message: `${item.title}: ${item.detail}`,
|
|
3345
|
+
})),
|
|
3346
|
+
...advisoryStructuralViolations.map((v) => ({
|
|
3347
|
+
file: v.filePath,
|
|
3348
|
+
rule: `structural-advisory:${v.ruleId.toLowerCase()}`,
|
|
3349
|
+
severity: 'warn',
|
|
3350
|
+
message: `${v.ruleId} ${v.ruleName}: ${v.evidence.slice(0, 100)} (advisory — link plan to enforce)`,
|
|
3351
|
+
})),
|
|
3352
|
+
];
|
|
3136
3353
|
recordVerifyEvent(advisoryVerdict, `advisory_missing_plan;signals=${advisorySignals.length};warn=${advisoryWarnCount}`, diffFiles.map((f) => f.path));
|
|
3137
3354
|
if (options.json) {
|
|
3138
3355
|
emitVerifyJson({
|
|
@@ -3150,6 +3367,11 @@ async function verifyCommand(options) {
|
|
|
3150
3367
|
mode: 'advisory_missing_plan',
|
|
3151
3368
|
advisoryMode: true,
|
|
3152
3369
|
advisorySignals,
|
|
3370
|
+
structuralViolations: advisoryStructuralViolations,
|
|
3371
|
+
structuralBlockingCount: advisoryStructuralBlockingCount,
|
|
3372
|
+
structuralNote: advisoryStructuralBlockingCount > 0
|
|
3373
|
+
? `${advisoryStructuralBlockingCount} structural finding(s) surfaced in advisory mode. Link a plan to enforce.`
|
|
3374
|
+
: undefined,
|
|
3153
3375
|
policyOnly: true,
|
|
3154
3376
|
policyOnlySource: 'fallback_missing_plan',
|
|
3155
3377
|
...(autoContractPath
|
|
@@ -3255,6 +3477,36 @@ async function verifyCommand(options) {
|
|
|
3255
3477
|
// Non-fatal: intent engine errors must never break verification
|
|
3256
3478
|
}
|
|
3257
3479
|
}
|
|
3480
|
+
// ── Structural Rule Engine ──────────────────────────────────────────────
|
|
3481
|
+
// AST-level deterministic analysis against changed files.
|
|
3482
|
+
// Reads file contents from disk; never throws — errors are isolated per file.
|
|
3483
|
+
if (diffFiles.length > 0) {
|
|
3484
|
+
try {
|
|
3485
|
+
const structuralEngine = (0, structural_rules_1.createDefaultStructuralRuleEngine)();
|
|
3486
|
+
const filesToAnalyze = [];
|
|
3487
|
+
for (const df of diffFiles) {
|
|
3488
|
+
const absPath = (0, path_1.join)(projectRoot, df.path);
|
|
3489
|
+
if ((0, fs_1.existsSync)(absPath)) {
|
|
3490
|
+
try {
|
|
3491
|
+
const sourceText = (0, fs_1.readFileSync)(absPath, 'utf-8');
|
|
3492
|
+
filesToAnalyze.push({ filePath: df.path, sourceText });
|
|
3493
|
+
}
|
|
3494
|
+
catch {
|
|
3495
|
+
// Skip unreadable files
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
if (filesToAnalyze.length > 0) {
|
|
3500
|
+
const structuralResult = structuralEngine.analyze(filesToAnalyze);
|
|
3501
|
+
structuralViolations = structuralResult.violations;
|
|
3502
|
+
structuralRulesApplied = structuralResult.rulesApplied;
|
|
3503
|
+
structuralSuppressedCount = structuralResult.suppressedCount;
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
catch {
|
|
3507
|
+
// Non-fatal: structural engine errors must never break verification
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3258
3510
|
governanceResult = (0, governance_1.evaluateGovernance)({
|
|
3259
3511
|
projectRoot,
|
|
3260
3512
|
task: governanceTask,
|
|
@@ -3804,6 +4056,9 @@ async function verifyCommand(options) {
|
|
|
3804
4056
|
message: `Policy audit chain is invalid: ${auditIntegrityStatus.issues.join('; ') || 'unknown issue'}`,
|
|
3805
4057
|
});
|
|
3806
4058
|
}
|
|
4059
|
+
// Structural violations are passed to the canonical pipeline via payload.structuralViolations
|
|
4060
|
+
// (see line ~5281). Do NOT merge them into policyViolations — that would create structural:*
|
|
4061
|
+
// duplicates that contaminate the canonical finding graph.
|
|
3807
4062
|
policyDecision = resolvePolicyDecisionFromViolations(policyViolations);
|
|
3808
4063
|
const policyExceptionsSummary = {
|
|
3809
4064
|
sourceMode: policyExceptionResolution.mode,
|
|
@@ -4251,6 +4506,9 @@ async function verifyCommand(options) {
|
|
|
4251
4506
|
plannedFilesModified: verifyResult.plannedFilesModified,
|
|
4252
4507
|
totalPlannedFiles: verifyResult.totalPlannedFiles,
|
|
4253
4508
|
verificationSource: verifySource,
|
|
4509
|
+
structuralViolations,
|
|
4510
|
+
structuralRulesApplied,
|
|
4511
|
+
structuralSuppressedCount,
|
|
4254
4512
|
mode: 'plan_enforced',
|
|
4255
4513
|
policyOnly: false,
|
|
4256
4514
|
aiDebt: aiDebtSummary,
|
|
@@ -4322,7 +4580,7 @@ async function verifyCommand(options) {
|
|
|
4322
4580
|
message: effectiveMessage,
|
|
4323
4581
|
bloatFiles: displayBloatFiles,
|
|
4324
4582
|
bloatCount: displayBloatFiles.length,
|
|
4325
|
-
}, policyViolations, expediteModeEnabled, intentEngineIssues, intentEngineSummary, intentEngineFlowIssues, intentEngineRegressions);
|
|
4583
|
+
}, policyViolations, expediteModeEnabled, intentEngineIssues, intentEngineSummary, intentEngineFlowIssues, intentEngineRegressions, structuralViolations);
|
|
4326
4584
|
if (governanceResult) {
|
|
4327
4585
|
displayGovernanceInsights(governanceResult, { explain: options.explain });
|
|
4328
4586
|
}
|
|
@@ -4385,6 +4643,67 @@ async function verifyCommand(options) {
|
|
|
4385
4643
|
console.log(chalk.dim(' Intent proof repo scan reached configured file/byte limit (truncated).'));
|
|
4386
4644
|
}
|
|
4387
4645
|
}
|
|
4646
|
+
console.log(chalk.dim('\n── Verification contract (this run) ──'));
|
|
4647
|
+
console.log(chalk.dim(` Verify source: ${verifySource === 'local_fallback'
|
|
4648
|
+
? 'local deterministic fallback (verify API unavailable)'
|
|
4649
|
+
: 'verify API'}`));
|
|
4650
|
+
console.log(chalk.dim(` Structural findings: ${structuralViolations.length} ` +
|
|
4651
|
+
`(${structuralViolations.filter((v) => v.severity === 'BLOCKING').length} blocking, ` +
|
|
4652
|
+
`${structuralViolations.filter((v) => v.severity !== 'BLOCKING').length} advisory)`));
|
|
4653
|
+
console.log(chalk.dim(' Merge gates follow rule severity + policy: blocking structural findings are reproducible on this tree.'));
|
|
4654
|
+
console.log(chalk.dim(' Evidence trail: see `.neurcode/` on success (provenance, telemetry) — use `neurcode replay` / dashboard for audit parity.'));
|
|
4655
|
+
}
|
|
4656
|
+
// ── Governance Provenance Chain + Pilot Metrics ───────────────────────
|
|
4657
|
+
// Best-effort: never throws, never changes the verification outcome.
|
|
4658
|
+
try {
|
|
4659
|
+
const structuralBlocking = structuralViolations.filter(v => v.severity === 'BLOCKING').length;
|
|
4660
|
+
const structuralAdvisory = structuralViolations.filter(v => v.severity === 'ADVISORY').length;
|
|
4661
|
+
const deterministicSigs = structuralViolations.filter(v => v.determinism === 'deterministic-structural').length;
|
|
4662
|
+
const heuristicSigs = structuralViolations.filter(v => v.determinism === 'heuristic-advisory').length;
|
|
4663
|
+
const trustScore = structuralViolations.length > 0
|
|
4664
|
+
? Math.round((deterministicSigs / structuralViolations.length) * 100)
|
|
4665
|
+
: 100;
|
|
4666
|
+
const prov = (0, governance_provenance_1.buildProvenanceRecord)({
|
|
4667
|
+
repoRoot: projectRoot,
|
|
4668
|
+
filesAnalyzed: diffFiles.length,
|
|
4669
|
+
diffContext: `${options.base || 'HEAD'} vs working tree`,
|
|
4670
|
+
planId: finalPlanId || null,
|
|
4671
|
+
intentHash: null,
|
|
4672
|
+
policyHash: null,
|
|
4673
|
+
ruleIds: structuralRulesApplied,
|
|
4674
|
+
blockingCount: policyViolations.filter((v) => v.severity === 'block').length + structuralBlocking,
|
|
4675
|
+
advisoryCount: policyViolations.filter((v) => v.severity !== 'block').length + structuralAdvisory,
|
|
4676
|
+
suppressedCount: structuralSuppressedCount,
|
|
4677
|
+
structuralBlockingCount: structuralBlocking,
|
|
4678
|
+
structuralAdvisoryCount: structuralAdvisory,
|
|
4679
|
+
deterministicSignals: deterministicSigs,
|
|
4680
|
+
heuristicSignals: heuristicSigs,
|
|
4681
|
+
overallTrustScore: trustScore,
|
|
4682
|
+
verdict: effectiveVerdict,
|
|
4683
|
+
governanceDecision: governanceResult?.governanceDecision?.summary || 'automatic',
|
|
4684
|
+
});
|
|
4685
|
+
(0, governance_provenance_1.saveProvenanceRecord)(projectRoot, prov);
|
|
4686
|
+
lastProvenanceRunId = prov.runId;
|
|
4687
|
+
// Tally per-rule counts for pilot metrics
|
|
4688
|
+
const ruleCounts = {};
|
|
4689
|
+
for (const v of structuralViolations) {
|
|
4690
|
+
ruleCounts[v.ruleId] = (ruleCounts[v.ruleId] ?? 0) + 1;
|
|
4691
|
+
}
|
|
4692
|
+
(0, pilot_metrics_1.recordVerifyRun)(projectRoot, {
|
|
4693
|
+
planCount: 0,
|
|
4694
|
+
verifyCount: 1,
|
|
4695
|
+
passCount: effectiveVerdict === 'PASS' ? 1 : 0,
|
|
4696
|
+
failCount: effectiveVerdict === 'FAIL' ? 1 : 0,
|
|
4697
|
+
blockingCaught: prov.blockingCount,
|
|
4698
|
+
advisoryCaught: prov.advisoryCount,
|
|
4699
|
+
suppressions: structuralSuppressedCount,
|
|
4700
|
+
structuralCaught: structuralViolations.length,
|
|
4701
|
+
aiDebtDelta: aiDebtSummary?.score ?? 0,
|
|
4702
|
+
ruleCounts,
|
|
4703
|
+
});
|
|
4704
|
+
}
|
|
4705
|
+
catch {
|
|
4706
|
+
// Never break verification
|
|
4388
4707
|
}
|
|
4389
4708
|
// Report to Neurcode Cloud if --record flag is set
|
|
4390
4709
|
const filteredBloatForReport = (verifyResult.bloatFiles || []).filter((f) => !shouldIgnore(f));
|
|
@@ -4855,7 +5174,7 @@ function displayChangeContractDrift(summary, options = { advisory: false }) {
|
|
|
4855
5174
|
/**
|
|
4856
5175
|
* Display verification results in a formatted report card
|
|
4857
5176
|
*/
|
|
4858
|
-
function displayVerifyResults(result, policyViolations, expediteModeUsed = false, intentIssuesForDisplay = [], intentSummaryForDisplay = null, flowIssuesForDisplay = [], regressionsForDisplay = []) {
|
|
5177
|
+
function displayVerifyResults(result, policyViolations, expediteModeUsed = false, intentIssuesForDisplay = [], intentSummaryForDisplay = null, flowIssuesForDisplay = [], regressionsForDisplay = [], structuralViolationsForDisplay = []) {
|
|
4859
5178
|
// ── Header ────────────────────────────────────────────────────────────────
|
|
4860
5179
|
const headerLabel = result.verdict === 'PASS'
|
|
4861
5180
|
? chalk.bold.green('\n✅ VERIFICATION PASSED')
|
|
@@ -4937,6 +5256,19 @@ function displayVerifyResults(result, policyViolations, expediteModeUsed = false
|
|
|
4937
5256
|
policy: item.rule || 'policy_violation',
|
|
4938
5257
|
severity: item.severity,
|
|
4939
5258
|
}));
|
|
5259
|
+
// Structural rule violations — split by severity
|
|
5260
|
+
const structuralBlocking = structuralViolationsForDisplay
|
|
5261
|
+
.filter((v) => v.severity === 'BLOCKING')
|
|
5262
|
+
.map((v) => ({
|
|
5263
|
+
file: v.filePath,
|
|
5264
|
+
message: `${v.ruleId} · ${v.ruleName} (line ${v.line}) — ${v.operationalRisk}`,
|
|
5265
|
+
}));
|
|
5266
|
+
const structuralAdvisory = structuralViolationsForDisplay
|
|
5267
|
+
.filter((v) => v.severity === 'ADVISORY')
|
|
5268
|
+
.map((v) => ({
|
|
5269
|
+
file: v.filePath,
|
|
5270
|
+
message: `${v.ruleId} · ${v.ruleName} (line ${v.line}) — ${v.operationalRisk}`,
|
|
5271
|
+
}));
|
|
4940
5272
|
let blockingItems = [
|
|
4941
5273
|
...scopeItems.map((item) => ({
|
|
4942
5274
|
file: item.file,
|
|
@@ -4948,13 +5280,17 @@ function displayVerifyResults(result, policyViolations, expediteModeUsed = false
|
|
|
4948
5280
|
file: item.file,
|
|
4949
5281
|
message: item.message,
|
|
4950
5282
|
})),
|
|
5283
|
+
...structuralBlocking,
|
|
5284
|
+
];
|
|
5285
|
+
let advisoryItems = [
|
|
5286
|
+
...policyTriageItems
|
|
5287
|
+
.filter((item) => !isBlockingSeverity(item.severity))
|
|
5288
|
+
.map((item) => ({
|
|
5289
|
+
file: item.file,
|
|
5290
|
+
message: item.message,
|
|
5291
|
+
})),
|
|
5292
|
+
...structuralAdvisory,
|
|
4951
5293
|
];
|
|
4952
|
-
let advisoryItems = policyTriageItems
|
|
4953
|
-
.filter((item) => !isBlockingSeverity(item.severity))
|
|
4954
|
-
.map((item) => ({
|
|
4955
|
-
file: item.file,
|
|
4956
|
-
message: item.message,
|
|
4957
|
-
}));
|
|
4958
5294
|
let expediteItems = [];
|
|
4959
5295
|
if (expediteModeUsed) {
|
|
4960
5296
|
blockingItems = [
|
|
@@ -5066,6 +5402,49 @@ function displayVerifyResults(result, policyViolations, expediteModeUsed = false
|
|
|
5066
5402
|
});
|
|
5067
5403
|
console.log(chalk.bold.red('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
5068
5404
|
}
|
|
5405
|
+
// ── Structural Rule Engine ─────────────────────────────────────────────────
|
|
5406
|
+
// Display detailed structural violations with AST evidence and determinism labels.
|
|
5407
|
+
if (structuralViolationsForDisplay.length > 0) {
|
|
5408
|
+
try {
|
|
5409
|
+
const report = (0, explainability_1.buildViolationReport)(structuralViolationsForDisplay, '');
|
|
5410
|
+
const formatter = new explainability_1.ViolationFormatter();
|
|
5411
|
+
const blocking = report.blocking;
|
|
5412
|
+
const advisory = report.advisory;
|
|
5413
|
+
if (blocking.length > 0 || advisory.length > 0) {
|
|
5414
|
+
console.log(chalk.bold('\n━━━ STRUCTURAL ANALYSIS ━━━━━━━━━━━━━━━━━'));
|
|
5415
|
+
blocking.slice(0, 5).forEach((v) => {
|
|
5416
|
+
const detLabel = v.determinism === 'deterministic-structural'
|
|
5417
|
+
? chalk.cyan('⚙ AST-verified')
|
|
5418
|
+
: chalk.yellow('⚡ heuristic');
|
|
5419
|
+
console.log(chalk.red(`\n ● ${v.ruleId} [BLOCKING] ${detLabel} · confidence ${Math.round(v.confidence * 100)}%`));
|
|
5420
|
+
console.log(chalk.bold(` ${v.filePath}:${v.line}`));
|
|
5421
|
+
console.log(chalk.dim(` Pattern: ${v.evidence.matchReason}`));
|
|
5422
|
+
if (v.evidence.codeSnippet) {
|
|
5423
|
+
console.log(chalk.dim(` Code: ${v.evidence.codeSnippet.slice(0, 100)}`));
|
|
5424
|
+
}
|
|
5425
|
+
console.log(chalk.yellow(` Risk: ${v.operationalRisk}`));
|
|
5426
|
+
console.log(chalk.green(` Fix: ${v.remediation}`));
|
|
5427
|
+
});
|
|
5428
|
+
if (blocking.length > 5) {
|
|
5429
|
+
console.log(chalk.dim(`\n ... ${blocking.length - 5} more blocking structural violations`));
|
|
5430
|
+
}
|
|
5431
|
+
advisory.slice(0, 3).forEach((v) => {
|
|
5432
|
+
console.log(chalk.yellow(`\n ○ ${v.ruleId} [ADVISORY] ⚡ heuristic · confidence ${Math.round(v.confidence * 100)}%`));
|
|
5433
|
+
console.log(chalk.dim(` ${v.filePath}:${v.line} — ${v.operationalRisk}`));
|
|
5434
|
+
});
|
|
5435
|
+
if (advisory.length > 3) {
|
|
5436
|
+
console.log(chalk.dim(` ... ${advisory.length - 3} more advisory structural violations`));
|
|
5437
|
+
}
|
|
5438
|
+
const deterministicCount = report.deterministicCount;
|
|
5439
|
+
const heuristicCount = report.heuristicCount;
|
|
5440
|
+
console.log(chalk.dim(`\n Determinism: ${deterministicCount} AST-verified · ${heuristicCount} heuristic`));
|
|
5441
|
+
console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
5442
|
+
}
|
|
5443
|
+
}
|
|
5444
|
+
catch {
|
|
5445
|
+
// Non-fatal: explainability rendering must never break verification display
|
|
5446
|
+
}
|
|
5447
|
+
}
|
|
5069
5448
|
const hasAnyIssue = blockingItems.length > 0 ||
|
|
5070
5449
|
advisoryItems.length > 0 ||
|
|
5071
5450
|
expediteItems.length > 0 ||
|