audit-tools 0.28.7 → 0.28.9
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/audit-code-wrapper-install-hosts.mjs +133 -27
- package/dist/audit/cli/confirmIntentStep.d.ts +1 -0
- package/dist/audit/cli/confirmIntentStep.d.ts.map +1 -1
- package/dist/audit/cli/confirmIntentStep.js +14 -10
- package/dist/audit/cli/confirmIntentStep.js.map +1 -1
- package/dist/audit/cli/dispatch/quotaPool.d.ts.map +1 -1
- package/dist/audit/cli/dispatch/quotaPool.js +4 -3
- package/dist/audit/cli/dispatch/quotaPool.js.map +1 -1
- package/dist/audit/cli/dispatch.d.ts +15 -1
- package/dist/audit/cli/dispatch.d.ts.map +1 -1
- package/dist/audit/cli/dispatch.js +54 -19
- package/dist/audit/cli/dispatch.js.map +1 -1
- package/dist/audit/cli/hybridDispatch.d.ts +46 -0
- package/dist/audit/cli/hybridDispatch.d.ts.map +1 -0
- package/dist/audit/cli/hybridDispatch.js +77 -0
- package/dist/audit/cli/hybridDispatch.js.map +1 -0
- package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
- package/dist/audit/cli/nextStepHelpers.js +111 -2
- package/dist/audit/cli/nextStepHelpers.js.map +1 -1
- package/dist/audit/cli/quotaCommand.d.ts.map +1 -1
- package/dist/audit/cli/quotaCommand.js +20 -10
- package/dist/audit/cli/quotaCommand.js.map +1 -1
- package/dist/audit/cli/reviewRun.d.ts +8 -0
- package/dist/audit/cli/reviewRun.d.ts.map +1 -1
- package/dist/audit/cli/reviewRun.js +1 -1
- package/dist/audit/cli/reviewRun.js.map +1 -1
- package/dist/audit/cli/rollingAuditDispatch.d.ts +57 -4
- package/dist/audit/cli/rollingAuditDispatch.d.ts.map +1 -1
- package/dist/audit/cli/rollingAuditDispatch.js +137 -10
- package/dist/audit/cli/rollingAuditDispatch.js.map +1 -1
- package/dist/audit/cli/scoreAuditCommand.d.ts +16 -0
- package/dist/audit/cli/scoreAuditCommand.d.ts.map +1 -0
- package/dist/audit/cli/scoreAuditCommand.js +82 -0
- package/dist/audit/cli/scoreAuditCommand.js.map +1 -0
- package/dist/audit/cli/submitPacketCommand.d.ts.map +1 -1
- package/dist/audit/cli/submitPacketCommand.js +8 -1
- package/dist/audit/cli/submitPacketCommand.js.map +1 -1
- package/dist/audit/cli.d.ts.map +1 -1
- package/dist/audit/cli.js +5 -1
- package/dist/audit/cli.js.map +1 -1
- package/dist/audit/orchestrator/designReviewProjection.d.ts +9 -1
- package/dist/audit/orchestrator/designReviewProjection.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewProjection.js +19 -1
- package/dist/audit/orchestrator/designReviewProjection.js.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.d.ts +2 -0
- package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.js +11 -1
- package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -1
- package/dist/audit/orchestrator/executorRunners.js +1 -1
- package/dist/audit/orchestrator/executorRunners.js.map +1 -1
- package/dist/audit/orchestrator/intakeExecutors.d.ts +9 -1
- package/dist/audit/orchestrator/intakeExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/intakeExecutors.js +16 -3
- package/dist/audit/orchestrator/intakeExecutors.js.map +1 -1
- package/dist/audit/orchestrator/intentCheckpointExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/intentCheckpointExecutor.js +3 -0
- package/dist/audit/orchestrator/intentCheckpointExecutor.js.map +1 -1
- package/dist/audit/orchestrator/intentInterpreter.d.ts +21 -7
- package/dist/audit/orchestrator/intentInterpreter.d.ts.map +1 -1
- package/dist/audit/orchestrator/intentInterpreter.js +30 -11
- package/dist/audit/orchestrator/intentInterpreter.js.map +1 -1
- package/dist/audit/orchestrator/intentScopeDisposition.d.ts +49 -0
- package/dist/audit/orchestrator/intentScopeDisposition.d.ts.map +1 -0
- package/dist/audit/orchestrator/intentScopeDisposition.js +57 -0
- package/dist/audit/orchestrator/intentScopeDisposition.js.map +1 -0
- package/dist/audit/orchestrator/rollingDispatch.d.ts +9 -0
- package/dist/audit/orchestrator/rollingDispatch.d.ts.map +1 -1
- package/dist/audit/orchestrator/rollingDispatch.js +10 -0
- package/dist/audit/orchestrator/rollingDispatch.js.map +1 -1
- package/dist/audit/orchestrator/scope.d.ts +1 -0
- package/dist/audit/orchestrator/scope.d.ts.map +1 -1
- package/dist/audit/orchestrator/scope.js +2 -7
- package/dist/audit/orchestrator/scope.js.map +1 -1
- package/dist/audit/quota/index.d.ts +5 -0
- package/dist/audit/quota/index.d.ts.map +1 -1
- package/dist/audit/reporting/scoreAudit.d.ts +161 -0
- package/dist/audit/reporting/scoreAudit.d.ts.map +1 -0
- package/dist/audit/reporting/scoreAudit.js +224 -0
- package/dist/audit/reporting/scoreAudit.js.map +1 -0
- package/dist/audit/types/activeDispatch.d.ts +29 -1
- package/dist/audit/types/activeDispatch.d.ts.map +1 -1
- package/dist/audit/types/activeDispatch.js.map +1 -1
- package/dist/audit/types/analyzerCapability.d.ts +6 -6
- package/dist/audit/validation/auditResults.d.ts +13 -0
- package/dist/audit/validation/auditResults.d.ts.map +1 -1
- package/dist/audit/validation/auditResults.js +35 -12
- package/dist/audit/validation/auditResults.js.map +1 -1
- package/dist/remediate/contractPipeline/changeClassification.d.ts +146 -0
- package/dist/remediate/contractPipeline/changeClassification.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/changeClassification.js +398 -0
- package/dist/remediate/contractPipeline/changeClassification.js.map +1 -0
- package/dist/remediate/contractPipeline/derive.d.ts.map +1 -1
- package/dist/remediate/contractPipeline/derive.js +9 -0
- package/dist/remediate/contractPipeline/derive.js.map +1 -1
- package/dist/remediate/intent/intentOrdering.d.ts +51 -0
- package/dist/remediate/intent/intentOrdering.d.ts.map +1 -0
- package/dist/remediate/intent/intentOrdering.js +150 -0
- package/dist/remediate/intent/intentOrdering.js.map +1 -0
- package/dist/remediate/phases/plan.d.ts.map +1 -1
- package/dist/remediate/phases/plan.js +14 -1
- package/dist/remediate/phases/plan.js.map +1 -1
- package/dist/remediate/providers/index.d.ts +32 -0
- package/dist/remediate/providers/index.d.ts.map +1 -1
- package/dist/remediate/providers/index.js +28 -1
- package/dist/remediate/providers/index.js.map +1 -1
- package/dist/remediate/steps/contractPipeline.d.ts +15 -1
- package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipeline.js +282 -14
- package/dist/remediate/steps/contractPipeline.js.map +1 -1
- package/dist/remediate/steps/dispatch.d.ts +56 -1
- package/dist/remediate/steps/dispatch.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch.js +120 -29
- package/dist/remediate/steps/dispatch.js.map +1 -1
- package/dist/remediate/steps/nextStep.d.ts +53 -2
- package/dist/remediate/steps/nextStep.d.ts.map +1 -1
- package/dist/remediate/steps/nextStep.js +253 -81
- package/dist/remediate/steps/nextStep.js.map +1 -1
- package/dist/remediate/steps/providerNodeDispatch.d.ts +8 -1
- package/dist/remediate/steps/providerNodeDispatch.d.ts.map +1 -1
- package/dist/remediate/steps/providerNodeDispatch.js +7 -2
- package/dist/remediate/steps/providerNodeDispatch.js.map +1 -1
- package/dist/remediate/steps/rollingSession.d.ts +55 -1
- package/dist/remediate/steps/rollingSession.d.ts.map +1 -1
- package/dist/remediate/steps/rollingSession.js +128 -19
- package/dist/remediate/steps/rollingSession.js.map +1 -1
- package/dist/remediate/validation/contractPipelineGates.d.ts +23 -8
- package/dist/remediate/validation/contractPipelineGates.d.ts.map +1 -1
- package/dist/remediate/validation/contractPipelineGates.js +43 -38
- package/dist/remediate/validation/contractPipelineGates.js.map +1 -1
- package/dist/shared/dispatch/coordinator.d.ts +170 -0
- package/dist/shared/dispatch/coordinator.d.ts.map +1 -0
- package/dist/shared/dispatch/coordinator.js +177 -0
- package/dist/shared/dispatch/coordinator.js.map +1 -0
- package/dist/shared/dispatch/hybridDispatch.d.ts +74 -0
- package/dist/shared/dispatch/hybridDispatch.d.ts.map +1 -0
- package/dist/shared/dispatch/hybridDispatch.js +54 -0
- package/dist/shared/dispatch/hybridDispatch.js.map +1 -0
- package/dist/shared/dispatch/settledPools.d.ts +21 -0
- package/dist/shared/dispatch/settledPools.d.ts.map +1 -0
- package/dist/shared/dispatch/settledPools.js +34 -0
- package/dist/shared/dispatch/settledPools.js.map +1 -0
- package/dist/shared/index.d.ts +16 -6
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +15 -3
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/intent/clauseInterpreter.d.ts +19 -0
- package/dist/shared/intent/clauseInterpreter.d.ts.map +1 -1
- package/dist/shared/intent/clauseInterpreter.js +19 -0
- package/dist/shared/intent/clauseInterpreter.js.map +1 -1
- package/dist/shared/io/json.d.ts +25 -0
- package/dist/shared/io/json.d.ts.map +1 -1
- package/dist/shared/io/json.js +67 -0
- package/dist/shared/io/json.js.map +1 -1
- package/dist/shared/providers/opencodeProvider.d.ts.map +1 -1
- package/dist/shared/providers/opencodeProvider.js +12 -0
- package/dist/shared/providers/opencodeProvider.js.map +1 -1
- package/dist/shared/providers/providerConfirmation.d.ts.map +1 -1
- package/dist/shared/providers/providerConfirmation.js +9 -1
- package/dist/shared/providers/providerConfirmation.js.map +1 -1
- package/dist/shared/providers/providerFactory.d.ts +1 -0
- package/dist/shared/providers/providerFactory.d.ts.map +1 -1
- package/dist/shared/providers/providerFactory.js +10 -8
- package/dist/shared/providers/providerFactory.js.map +1 -1
- package/dist/shared/providers/sharedProviderConfirmation.d.ts +134 -0
- package/dist/shared/providers/sharedProviderConfirmation.d.ts.map +1 -0
- package/dist/shared/providers/sharedProviderConfirmation.js +244 -0
- package/dist/shared/providers/sharedProviderConfirmation.js.map +1 -0
- package/dist/shared/quota/apiPool.d.ts +67 -0
- package/dist/shared/quota/apiPool.d.ts.map +1 -0
- package/dist/shared/quota/apiPool.js +139 -0
- package/dist/shared/quota/apiPool.js.map +1 -0
- package/dist/shared/quota/capacity.d.ts +29 -1
- package/dist/shared/quota/capacity.d.ts.map +1 -1
- package/dist/shared/quota/capacity.js +5 -0
- package/dist/shared/quota/capacity.js.map +1 -1
- package/dist/shared/quota/claimRegistry.d.ts +64 -0
- package/dist/shared/quota/claimRegistry.d.ts.map +1 -0
- package/dist/shared/quota/claimRegistry.js +157 -0
- package/dist/shared/quota/claimRegistry.js.map +1 -0
- package/dist/shared/quota/compositeQuotaSource.d.ts +10 -1
- package/dist/shared/quota/compositeQuotaSource.d.ts.map +1 -1
- package/dist/shared/quota/compositeQuotaSource.js +34 -6
- package/dist/shared/quota/compositeQuotaSource.js.map +1 -1
- package/dist/shared/quota/httpQuotaSource.d.ts +9 -1
- package/dist/shared/quota/httpQuotaSource.d.ts.map +1 -1
- package/dist/shared/quota/httpQuotaSource.js +33 -8
- package/dist/shared/quota/httpQuotaSource.js.map +1 -1
- package/dist/shared/quota/learnedQuotaSource.d.ts +7 -1
- package/dist/shared/quota/learnedQuotaSource.d.ts.map +1 -1
- package/dist/shared/quota/learnedQuotaSource.js +18 -7
- package/dist/shared/quota/learnedQuotaSource.js.map +1 -1
- package/dist/shared/quota/quotaSource.d.ts +41 -0
- package/dist/shared/quota/quotaSource.d.ts.map +1 -1
- package/dist/shared/quota/quotaSource.js +19 -0
- package/dist/shared/quota/quotaSource.js.map +1 -1
- package/dist/shared/types/contractPipeline/obligations.d.ts +42 -0
- package/dist/shared/types/contractPipeline/obligations.d.ts.map +1 -1
- package/dist/shared/types/contractPipeline.d.ts +1 -1
- package/dist/shared/types/contractPipeline.d.ts.map +1 -1
- package/dist/shared/types/contractPipeline.js.map +1 -1
- package/dist/shared/types/intentCheckpoint.d.ts +14 -0
- package/dist/shared/types/intentCheckpoint.d.ts.map +1 -1
- package/dist/shared/types/intentCheckpoint.js +10 -0
- package/dist/shared/types/intentCheckpoint.js.map +1 -1
- package/dist/shared/types/sessionConfig.d.ts +60 -0
- package/dist/shared/types/sessionConfig.d.ts.map +1 -1
- package/dist/shared/types/sessionConfig.js +13 -0
- package/dist/shared/types/sessionConfig.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DC-5 — obligation change-vs-addition classification + paired/scoped negative
|
|
3
|
+
* test-spec gate (single source).
|
|
4
|
+
*
|
|
5
|
+
* Two latent failure modes this module closes:
|
|
6
|
+
*
|
|
7
|
+
* CE-013 (render-only misclassification): the paired-obligation gate used to
|
|
8
|
+
* force EVERY testable obligation to carry a positive+negative pair, with no
|
|
9
|
+
* notion of whether the obligation changes prior behavior or adds new
|
|
10
|
+
* behavior. A pure addition has no behavior to regress, so pairing it is
|
|
11
|
+
* burden without signal — and, worse, the "classification" lived only in the
|
|
12
|
+
* prompt prose (render-only), never as a recorded, checkable verdict. This
|
|
13
|
+
* module classifies each obligation *deterministically first* (does it touch
|
|
14
|
+
* a symbol/file that already exists?) and records the verdict on the ledger,
|
|
15
|
+
* so an LLM may confirm/override but the result is never silent.
|
|
16
|
+
*
|
|
17
|
+
* CE-006 (unscoped repo-wide-grep negative): a behavior-CHANGE obligation's
|
|
18
|
+
* negative half could be satisfied by an assertion that greps the whole repo
|
|
19
|
+
* ("no file anywhere contains X") — which rots immediately and proves nothing
|
|
20
|
+
* about the changed symbol. The negative must be SCOPED to the changed
|
|
21
|
+
* symbol/file. The scope check is a structural PREDICATE over the assertion
|
|
22
|
+
* (it must name an anchor AND must not be an unscoped global scan), not a
|
|
23
|
+
* keyword match — keyword matching alone is exactly what let the unscoped
|
|
24
|
+
* negative through.
|
|
25
|
+
*
|
|
26
|
+
* Single-source invariant (mirrors `derive.ts`): the deriver, the test-plan
|
|
27
|
+
* derivation gate (`validatePairedObligations`), and the `mergeImplementResults`
|
|
28
|
+
* verify gate ALL classify and pair through the helpers here. No parallel logic.
|
|
29
|
+
*/
|
|
30
|
+
import { isRecord } from "audit-tools/shared";
|
|
31
|
+
// ── Symbol extraction ─────────────────────────────────────────────────────────
|
|
32
|
+
/**
|
|
33
|
+
* Identifier-like tokens (camelCase / snake_case / dotted / path-ish) that name a
|
|
34
|
+
* code symbol or file. Length >= 3 so single letters and noise are ignored.
|
|
35
|
+
* Used both to pull candidate symbols out of an obligation description and to
|
|
36
|
+
* build the baseline corpus of pre-existing symbols.
|
|
37
|
+
*/
|
|
38
|
+
const SYMBOL_TOKEN_PATTERN = /[A-Za-z_$][A-Za-z0-9_$./-]{2,}/g;
|
|
39
|
+
/** Common English words that look identifier-ish but never name a symbol. */
|
|
40
|
+
const SYMBOL_STOPWORDS = new Set([
|
|
41
|
+
"the", "and", "for", "with", "that", "this", "must", "not", "its", "via",
|
|
42
|
+
"per", "into", "when", "then", "than", "from", "module", "function", "value",
|
|
43
|
+
"input", "output", "inputs", "outputs", "should", "shall", "handle", "failure",
|
|
44
|
+
"mode", "implement", "contract", "boundary", "validation", "every", "each",
|
|
45
|
+
"obligation", "behavior", "behaviour", "existing", "new", "add", "change",
|
|
46
|
+
]);
|
|
47
|
+
/** Extract candidate symbol/file tokens from free text (lowercased, de-noised). */
|
|
48
|
+
export function extractSymbolTokens(text) {
|
|
49
|
+
if (typeof text !== "string" || text.length === 0)
|
|
50
|
+
return [];
|
|
51
|
+
const out = new Set();
|
|
52
|
+
for (const raw of text.match(SYMBOL_TOKEN_PATTERN) ?? []) {
|
|
53
|
+
const token = raw.toLowerCase().replace(/^[./-]+|[./-]+$/g, "");
|
|
54
|
+
if (token.length < 3)
|
|
55
|
+
continue;
|
|
56
|
+
if (SYMBOL_STOPWORDS.has(token))
|
|
57
|
+
continue;
|
|
58
|
+
// A token must carry a "code-ish" shape — a case hump, an underscore, a dot,
|
|
59
|
+
// a slash, or a digit — so a plain prose word ("rejects") is not mistaken for
|
|
60
|
+
// a symbol while `writeRecord`, `flush_buffer`, `src/a.ts`, `O_1` are kept.
|
|
61
|
+
if (/[A-Z]/.test(raw.slice(1)) || /[_./\-0-9]/.test(token)) {
|
|
62
|
+
out.add(token);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return [...out];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build the baseline corpus of pre-existing symbol/file tokens from the finalized
|
|
69
|
+
* module contracts. A symbol present here already exists, so an obligation that
|
|
70
|
+
* references it is *changing* existing behavior rather than adding new behavior.
|
|
71
|
+
*
|
|
72
|
+
* The corpus is drawn from the declared interface surface (inputs / outputs /
|
|
73
|
+
* side_effects / validation_boundary) plus each module name — the things the
|
|
74
|
+
* contract says already exist at the seam.
|
|
75
|
+
*/
|
|
76
|
+
export function buildBaselineSymbolCorpus(finalizedModuleContracts) {
|
|
77
|
+
const corpus = new Set();
|
|
78
|
+
const record = isRecord(finalizedModuleContracts) ? finalizedModuleContracts : {};
|
|
79
|
+
const modules = Array.isArray(record.module_contracts) ? record.module_contracts : [];
|
|
80
|
+
for (const mod of modules) {
|
|
81
|
+
if (!isRecord(mod))
|
|
82
|
+
continue;
|
|
83
|
+
if (typeof mod.name === "string") {
|
|
84
|
+
for (const t of extractSymbolTokens(mod.name))
|
|
85
|
+
corpus.add(t);
|
|
86
|
+
}
|
|
87
|
+
for (const field of ["inputs", "outputs", "side_effects"]) {
|
|
88
|
+
if (!Array.isArray(mod[field]))
|
|
89
|
+
continue;
|
|
90
|
+
for (const entry of mod[field]) {
|
|
91
|
+
if (typeof entry !== "string")
|
|
92
|
+
continue;
|
|
93
|
+
for (const t of extractSymbolTokens(entry))
|
|
94
|
+
corpus.add(t);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (typeof mod.validation_boundary === "string") {
|
|
98
|
+
for (const t of extractSymbolTokens(mod.validation_boundary))
|
|
99
|
+
corpus.add(t);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return corpus;
|
|
103
|
+
}
|
|
104
|
+
// ── Deterministic classification (FIRST pass) ──────────────────────────────────
|
|
105
|
+
/**
|
|
106
|
+
* Classify one obligation change-vs-addition deterministically.
|
|
107
|
+
*
|
|
108
|
+
* Heuristic: the obligation *touches an existing symbol* when any symbol token in
|
|
109
|
+
* its description is present in the baseline corpus of pre-existing symbols. Such
|
|
110
|
+
* an obligation is a behavior CHANGE; otherwise it is a pure ADDITION.
|
|
111
|
+
*
|
|
112
|
+
* The matched tokens become `touched_symbols` — the scope anchors a paired
|
|
113
|
+
* negative assertion must name. This is the deterministic FIRST pass; an LLM may
|
|
114
|
+
* confirm or override it via `applyLlmConfirmation`, and the override is recorded.
|
|
115
|
+
*/
|
|
116
|
+
export function classifyObligationChange(description, baselineSymbols) {
|
|
117
|
+
const tokens = extractSymbolTokens(description);
|
|
118
|
+
const touched = tokens.filter((t) => baselineSymbols.has(t));
|
|
119
|
+
if (touched.length > 0) {
|
|
120
|
+
return {
|
|
121
|
+
change_kind: "change",
|
|
122
|
+
touched_symbols: touched,
|
|
123
|
+
determined_by: "touches_existing_symbol",
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
change_kind: "addition",
|
|
128
|
+
touched_symbols: [],
|
|
129
|
+
determined_by: "no_existing_symbol",
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Merge an LLM verdict onto the deterministic classification, recording the
|
|
134
|
+
* provenance. The LLM may CONFIRM (same verdict) or OVERRIDE (different verdict);
|
|
135
|
+
* either way the result is recorded so the classification is never silent. When
|
|
136
|
+
* the LLM overrides to a change but names no anchors, the deterministically
|
|
137
|
+
* extracted touched symbols are preserved (a change always needs an anchor set).
|
|
138
|
+
*/
|
|
139
|
+
export function applyLlmConfirmation(deterministic, llm) {
|
|
140
|
+
const confirmed = llm.change_kind === deterministic.change_kind;
|
|
141
|
+
const touched = llm.change_kind === "change"
|
|
142
|
+
? dedupe([
|
|
143
|
+
// Normalize LLM-provided anchors to the same lowercased form the
|
|
144
|
+
// deterministic extractor uses, so the recorded anchor set is consistent.
|
|
145
|
+
...(llm.touched_symbols ?? []).map((s) => typeof s === "string" ? s.toLowerCase() : s),
|
|
146
|
+
...deterministic.touched_symbols,
|
|
147
|
+
])
|
|
148
|
+
: [];
|
|
149
|
+
return {
|
|
150
|
+
change_kind: llm.change_kind,
|
|
151
|
+
touched_symbols: touched,
|
|
152
|
+
determined_by: confirmed ? "llm_confirmed" : "llm_override",
|
|
153
|
+
...(llm.rationale ? { rationale: llm.rationale } : {}),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// ── Anti-rot scope predicate (CE-006) ──────────────────────────────────────────
|
|
157
|
+
/**
|
|
158
|
+
* Markers of an UNSCOPED, repo-wide negative assertion — a grep/scan over the
|
|
159
|
+
* whole tree that names no specific symbol and rots the moment any unrelated file
|
|
160
|
+
* matches. Presence of one of these (without an offsetting scope anchor) is what
|
|
161
|
+
* the predicate rejects. This is a STRUCTURAL signal about the assertion's shape,
|
|
162
|
+
* distinct from polarity keywords.
|
|
163
|
+
*/
|
|
164
|
+
const UNSCOPED_GLOBAL_SCAN_PATTERN = /\b(?:repo[\s-]?wide|whole\s+repo|entire\s+(?:repo|codebase|tree)|across\s+the\s+(?:repo|codebase|tree)|any\s+file|no\s+file\s+(?:anywhere|in\s+the\s+repo)|anywhere\s+in\s+the\s+(?:repo|codebase|tree)|grep\s+(?:the\s+)?(?:repo|codebase|tree))\b/i;
|
|
165
|
+
/** Match a scope anchor as a whole word/path fragment inside an assertion. */
|
|
166
|
+
function assertionNamesAnchor(assertion, anchor) {
|
|
167
|
+
if (anchor.length < 3)
|
|
168
|
+
return false;
|
|
169
|
+
const escaped = anchor.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
170
|
+
// Word/path boundary: the anchor is not glued to surrounding identifier chars.
|
|
171
|
+
return new RegExp(`(?<![A-Za-z0-9_$])${escaped}(?![A-Za-z0-9_$])`, "i").test(assertion);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* A negative assertion for a behavior-CHANGE obligation is SCOPED when it names
|
|
175
|
+
* at least one of the change's anchors (the touched symbol/file) AND is not an
|
|
176
|
+
* unscoped repo-wide scan. Naming an anchor is necessary but not sufficient: an
|
|
177
|
+
* assertion that both names the symbol and says "grep the whole repo" is still
|
|
178
|
+
* rejected, because the scan, not the symbol, is what it actually checks.
|
|
179
|
+
*
|
|
180
|
+
* Returns true when the assertion is acceptably scoped to the change.
|
|
181
|
+
*/
|
|
182
|
+
export function negativeAssertionIsScoped(assertion, anchors) {
|
|
183
|
+
if (typeof assertion !== "string" || assertion.length === 0)
|
|
184
|
+
return false;
|
|
185
|
+
if (UNSCOPED_GLOBAL_SCAN_PATTERN.test(assertion))
|
|
186
|
+
return false;
|
|
187
|
+
return anchors.some((a) => assertionNamesAnchor(assertion, a));
|
|
188
|
+
}
|
|
189
|
+
// ── Polarity detection (shared with the legacy keyword gate) ───────────────────
|
|
190
|
+
/** Phrases that mark a negative/failure assertion (paired-obligation half). */
|
|
191
|
+
export const NEGATIVE_ASSERTION_PATTERN = /\b(rejects?|rejected|throws?|errors?|fails?|failure|invalid|disallows?|forbidden|refuses?|must not|does not|should not|cannot|never|negative|missing|absent|empty)\b/i;
|
|
192
|
+
/** Phrases that mark a positive/satisfied assertion (paired-obligation half). */
|
|
193
|
+
export const POSITIVE_ASSERTION_PATTERN = /\b(accept|accepted|allow|allowed|succeed|succeeds|returns?|produces?|valid|present|satisfies|satisfied|passes?|emits?|writes?|equal|equals|matches?)\b/i;
|
|
194
|
+
/**
|
|
195
|
+
* Classify one assertion's polarity. An explicit `POSITIVE:` / `NEGATIVE:` label
|
|
196
|
+
* is authoritative and skips the keyword fallback (so "POSITIVE: must not exceed
|
|
197
|
+
* N" counts only as positive). Unlabeled assertions fall through to the keyword
|
|
198
|
+
* regexes, which may match both polarities.
|
|
199
|
+
*/
|
|
200
|
+
export function assertionPolarity(assertion) {
|
|
201
|
+
const label = /^\s*(POSITIVE|NEGATIVE)\s*:/i.exec(assertion);
|
|
202
|
+
if (label) {
|
|
203
|
+
return label[1].toUpperCase() === "POSITIVE" ? "positive" : "negative";
|
|
204
|
+
}
|
|
205
|
+
const neg = NEGATIVE_ASSERTION_PATTERN.test(assertion);
|
|
206
|
+
const pos = POSITIVE_ASSERTION_PATTERN.test(assertion);
|
|
207
|
+
if (neg && pos)
|
|
208
|
+
return "both";
|
|
209
|
+
if (neg)
|
|
210
|
+
return "negative";
|
|
211
|
+
if (pos)
|
|
212
|
+
return "positive";
|
|
213
|
+
return "none";
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Evaluate the paired positive+scoped-negative requirement for a behavior-CHANGE
|
|
217
|
+
* obligation. `anchors` are the change's scope anchors (touched symbols/file).
|
|
218
|
+
*
|
|
219
|
+
* - A positive half is any assertion with positive polarity.
|
|
220
|
+
* - A negative half counts ONLY when it is scoped to the change (CE-006): an
|
|
221
|
+
* unscoped repo-wide negative does not satisfy the negative requirement.
|
|
222
|
+
* `negativeUnscoped` is reported when the sole negative(s) failed scoping, so
|
|
223
|
+
* the diagnostic distinguishes "no negative at all" from "negative not scoped".
|
|
224
|
+
*/
|
|
225
|
+
export function evaluatePairing(assertions, anchors) {
|
|
226
|
+
let hasPositive = false;
|
|
227
|
+
let hasScopedNegative = false;
|
|
228
|
+
let hasAnyNegative = false;
|
|
229
|
+
for (const assertion of assertions) {
|
|
230
|
+
if (typeof assertion !== "string")
|
|
231
|
+
continue;
|
|
232
|
+
const polarity = assertionPolarity(assertion);
|
|
233
|
+
if (polarity === "positive" || polarity === "both")
|
|
234
|
+
hasPositive = true;
|
|
235
|
+
if (polarity === "negative" || polarity === "both") {
|
|
236
|
+
hasAnyNegative = true;
|
|
237
|
+
if (negativeAssertionIsScoped(assertion, anchors))
|
|
238
|
+
hasScopedNegative = true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
ok: hasPositive && hasScopedNegative,
|
|
243
|
+
hasPositive,
|
|
244
|
+
hasNegative: hasScopedNegative,
|
|
245
|
+
negativeUnscoped: hasAnyNegative && !hasScopedNegative,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
// ── Defensive read + anchor derivation (used by the gates) ─────────────────────
|
|
249
|
+
/**
|
|
250
|
+
* Read an obligation's `change_classification` from a raw, untrusted payload.
|
|
251
|
+
* Returns the narrowed classification, or `undefined` when absent/malformed — the
|
|
252
|
+
* gates treat an unclassified TESTABLE obligation as a CHANGE (fail-closed), so a
|
|
253
|
+
* dropped or corrupt classification can never relax the paired-test requirement.
|
|
254
|
+
*/
|
|
255
|
+
export function readObligationChangeClassification(obligation) {
|
|
256
|
+
if (!isRecord(obligation))
|
|
257
|
+
return undefined;
|
|
258
|
+
const cls = obligation.change_classification;
|
|
259
|
+
if (!isRecord(cls))
|
|
260
|
+
return undefined;
|
|
261
|
+
if (cls.change_kind !== "change" && cls.change_kind !== "addition")
|
|
262
|
+
return undefined;
|
|
263
|
+
const touched = Array.isArray(cls.touched_symbols)
|
|
264
|
+
? cls.touched_symbols.filter((t) => typeof t === "string")
|
|
265
|
+
: [];
|
|
266
|
+
const determinedBy = cls.determined_by === "touches_existing_symbol" ||
|
|
267
|
+
cls.determined_by === "no_existing_symbol" ||
|
|
268
|
+
cls.determined_by === "llm_confirmed" ||
|
|
269
|
+
cls.determined_by === "llm_override"
|
|
270
|
+
? cls.determined_by
|
|
271
|
+
: "touches_existing_symbol";
|
|
272
|
+
return {
|
|
273
|
+
change_kind: cls.change_kind,
|
|
274
|
+
touched_symbols: touched,
|
|
275
|
+
determined_by: determinedBy,
|
|
276
|
+
...(typeof cls.rationale === "string" ? { rationale: cls.rationale } : {}),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* The scope anchors a paired negative must name for one obligation. Prefers the
|
|
281
|
+
* classification's recorded `touched_symbols`; falls back to the obligation id
|
|
282
|
+
* plus any symbol tokens in its description when the classification carries none
|
|
283
|
+
* (e.g. an unclassified obligation treated as a fail-closed change). Always
|
|
284
|
+
* non-empty when the id is a real id, so a fail-closed change still has a concrete
|
|
285
|
+
* anchor to scope against rather than vacuously accepting any negative.
|
|
286
|
+
*/
|
|
287
|
+
export function obligationScopeAnchors(obligationId, description, classification) {
|
|
288
|
+
if (classification && classification.touched_symbols.length > 0) {
|
|
289
|
+
return classification.touched_symbols;
|
|
290
|
+
}
|
|
291
|
+
const anchors = new Set();
|
|
292
|
+
if (typeof obligationId === "string" && obligationId.length >= 3) {
|
|
293
|
+
anchors.add(obligationId.toLowerCase());
|
|
294
|
+
}
|
|
295
|
+
for (const t of extractSymbolTokens(description))
|
|
296
|
+
anchors.add(t);
|
|
297
|
+
return [...anchors];
|
|
298
|
+
}
|
|
299
|
+
// ── Verify-gate enforcement (mergeImplementResults) ────────────────────────────
|
|
300
|
+
/** A test_validator_plan spec's assertions, indexed by obligation id. */
|
|
301
|
+
function assertionsByObligation(testValidatorPlanPayload) {
|
|
302
|
+
const byId = new Map();
|
|
303
|
+
const specs = isRecord(testValidatorPlanPayload) && Array.isArray(testValidatorPlanPayload.test_specs)
|
|
304
|
+
? testValidatorPlanPayload.test_specs
|
|
305
|
+
: [];
|
|
306
|
+
for (const spec of specs) {
|
|
307
|
+
if (!isRecord(spec) || typeof spec.obligation_id !== "string")
|
|
308
|
+
continue;
|
|
309
|
+
const list = byId.get(spec.obligation_id) ?? [];
|
|
310
|
+
if (Array.isArray(spec.assertions)) {
|
|
311
|
+
for (const a of spec.assertions) {
|
|
312
|
+
if (typeof a === "string")
|
|
313
|
+
list.push(a);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
byId.set(spec.obligation_id, list);
|
|
317
|
+
}
|
|
318
|
+
return byId;
|
|
319
|
+
}
|
|
320
|
+
/** True when an obligation has an inapplicable_claim opting it out, in the plan. */
|
|
321
|
+
function obligationOptedOut(testValidatorPlanPayload, obligationId) {
|
|
322
|
+
const specs = isRecord(testValidatorPlanPayload) && Array.isArray(testValidatorPlanPayload.test_specs)
|
|
323
|
+
? testValidatorPlanPayload.test_specs
|
|
324
|
+
: [];
|
|
325
|
+
return specs.some((spec) => isRecord(spec) &&
|
|
326
|
+
spec.obligation_id === obligationId &&
|
|
327
|
+
isRecord(spec.inapplicable_claim) &&
|
|
328
|
+
spec.inapplicable_claim.obligation_id === obligationId &&
|
|
329
|
+
typeof spec.inapplicable_claim.reason === "string" &&
|
|
330
|
+
spec.inapplicable_claim.reason.length > 0);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Verify-gate (DC-5): for the obligations a resolved finding covers, return a
|
|
334
|
+
* block reason when any behavior-CHANGE obligation's test specs are only one
|
|
335
|
+
* polarity — a positive without a SCOPED negative, or a negative-only set. A pure
|
|
336
|
+
* addition, an opted-out obligation, or one not present in the ledger is ignored.
|
|
337
|
+
*
|
|
338
|
+
* This is the SAME pairing/scoping evaluation the test-plan derivation gate uses
|
|
339
|
+
* (`evaluatePairing` + `obligationScopeAnchors`), so a node cannot self-report a
|
|
340
|
+
* change resolved while leaving the pair half-open: only-one-polarity → blocked.
|
|
341
|
+
* Returns `null` when every covered change obligation is fully paired.
|
|
342
|
+
*/
|
|
343
|
+
export function verifyPairingForFinding(obligationIds, obligationLedgerPayload, testValidatorPlanPayload) {
|
|
344
|
+
if (obligationIds.length === 0)
|
|
345
|
+
return null;
|
|
346
|
+
const obligations = isRecord(obligationLedgerPayload) && Array.isArray(obligationLedgerPayload.obligations)
|
|
347
|
+
? obligationLedgerPayload.obligations
|
|
348
|
+
: [];
|
|
349
|
+
if (obligations.length === 0)
|
|
350
|
+
return null;
|
|
351
|
+
const byId = new Map();
|
|
352
|
+
for (const obl of obligations) {
|
|
353
|
+
if (isRecord(obl) && typeof obl.id === "string")
|
|
354
|
+
byId.set(obl.id, obl);
|
|
355
|
+
}
|
|
356
|
+
const assertions = assertionsByObligation(testValidatorPlanPayload);
|
|
357
|
+
const reasons = [];
|
|
358
|
+
for (const oblId of obligationIds) {
|
|
359
|
+
const obl = byId.get(oblId);
|
|
360
|
+
if (!obl)
|
|
361
|
+
continue;
|
|
362
|
+
const kind = typeof obl.kind === "string" ? obl.kind : "";
|
|
363
|
+
if (kind !== "invariant" && kind !== "behavioral")
|
|
364
|
+
continue;
|
|
365
|
+
if (obligationOptedOut(testValidatorPlanPayload, oblId))
|
|
366
|
+
continue;
|
|
367
|
+
const classification = readObligationChangeClassification(obl);
|
|
368
|
+
// Pure addition never paired; only a change (or fail-closed unclassified)
|
|
369
|
+
// is gated here.
|
|
370
|
+
if (classification?.change_kind === "addition")
|
|
371
|
+
continue;
|
|
372
|
+
const description = typeof obl.description === "string" ? obl.description : "";
|
|
373
|
+
const anchors = obligationScopeAnchors(oblId, description, classification);
|
|
374
|
+
const verdict = evaluatePairing(assertions.get(oblId) ?? [], anchors);
|
|
375
|
+
if (verdict.ok)
|
|
376
|
+
continue;
|
|
377
|
+
if (!verdict.hasPositive && !verdict.hasNegative) {
|
|
378
|
+
reasons.push(`obligation "${oblId}" (behavior change) has no paired test spec — a change must assert both the satisfied path and a negative scoped to the changed symbol/file`);
|
|
379
|
+
}
|
|
380
|
+
else if (!verdict.hasNegative) {
|
|
381
|
+
reasons.push(verdict.negativeUnscoped
|
|
382
|
+
? `obligation "${oblId}" (behavior change) has only one polarity: its negative assertion is not scoped to the change (anchors: ${anchors.join(", ") || "none"}) — an unscoped repo-wide negative is rejected (CE-006)`
|
|
383
|
+
: `obligation "${oblId}" (behavior change) has only one polarity: a positive assertion without a scoped negative (failure-path) half`);
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
reasons.push(`obligation "${oblId}" (behavior change) has only one polarity: a negative assertion without a positive (satisfied-path) half`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (reasons.length === 0)
|
|
390
|
+
return null;
|
|
391
|
+
return (`DC-5 paired-test gate: ${reasons.join("; ")}. ` +
|
|
392
|
+
`A behavior-change obligation must carry a paired positive+scoped-negative test spec before it can be reported resolved.`);
|
|
393
|
+
}
|
|
394
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
395
|
+
function dedupe(values) {
|
|
396
|
+
return [...new Set(values.filter((v) => typeof v === "string" && v.length > 0))];
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=changeClassification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changeClassification.js","sourceRoot":"","sources":["../../../src/remediate/contractPipeline/changeClassification.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../../src/remediate/contractPipeline/derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../../src/remediate/contractPipeline/derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAqB5B,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,wBAAwB,EAAE,OAAO,EACjC,OAAO,GAAE,aAAkB,GAC1B,gBAAgB,CA2DlB;AAsBD,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,KAAK,CAAC;QAChB,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC,CAAC;CACJ;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,gBAAgB,GAAG,SAAS,GACnC,yBAAyB,CAY3B;AAED,MAAM,WAAW,6BAA6B;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2BAA2B,EAAE,MAAM,EAAE,CAAC;IACtC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,6BAA6B,EAAE,CAAC;IACvC,KAAK,EAAE,KAAK,EAAE,CAAC;CAChB;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,EAAE,CAgBxE;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,aAAa,EAAE,MAAM,EAAE,GACtB,yBAAyB,CAiC3B"}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* no parallel logic").
|
|
22
22
|
*/
|
|
23
23
|
import { buildObligationLedger, isRecord, mintUniqueId, } from "audit-tools/shared";
|
|
24
|
+
import { buildBaselineSymbolCorpus, classifyObligationChange, } from "./changeClassification.js";
|
|
24
25
|
/**
|
|
25
26
|
* Derive the obligation ledger deterministically from the finalized module
|
|
26
27
|
* contracts. Pure function of its input (modulo the `created_at` stamp): the
|
|
@@ -43,6 +44,12 @@ export function deriveObligationLedger(finalizedModuleContracts, options = {}) {
|
|
|
43
44
|
const finalized = readFinalizedContracts(finalizedModuleContracts);
|
|
44
45
|
const usedIds = new Set();
|
|
45
46
|
const obligations = [];
|
|
47
|
+
// DC-5: baseline corpus of pre-existing symbols, built once from the declared
|
|
48
|
+
// interface surface. A testable obligation that references a symbol in here is
|
|
49
|
+
// classified a behavior CHANGE (deterministic FIRST pass); otherwise an
|
|
50
|
+
// ADDITION. The verdict is recorded on each obligation so the paired-test gate
|
|
51
|
+
// is driven by data, not by render-only prose (CE-013).
|
|
52
|
+
const baselineSymbols = buildBaselineSymbolCorpus(finalizedModuleContracts);
|
|
46
53
|
for (const mod of finalized.module_contracts) {
|
|
47
54
|
const base = slug(mod.name) || "module";
|
|
48
55
|
// Contract-conformance obligation — represents the module even when it
|
|
@@ -65,6 +72,7 @@ export function deriveObligationLedger(finalizedModuleContracts, options = {}) {
|
|
|
65
72
|
depends_on: [],
|
|
66
73
|
status: "pending",
|
|
67
74
|
source: "design_spec",
|
|
75
|
+
change_classification: classifyObligationChange(invariant, baselineSymbols),
|
|
68
76
|
});
|
|
69
77
|
});
|
|
70
78
|
mod.failure_modes.forEach((failureMode, j) => {
|
|
@@ -75,6 +83,7 @@ export function deriveObligationLedger(finalizedModuleContracts, options = {}) {
|
|
|
75
83
|
depends_on: [],
|
|
76
84
|
status: "pending",
|
|
77
85
|
source: "design_spec",
|
|
86
|
+
change_classification: classifyObligationChange(failureMode, baselineSymbols),
|
|
78
87
|
});
|
|
79
88
|
});
|
|
80
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive.js","sourceRoot":"","sources":["../../../src/remediate/contractPipeline/derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EACL,qBAAqB,EACrB,QAAQ,EACR,YAAY,GAGb,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"derive.js","sourceRoot":"","sources":["../../../src/remediate/contractPipeline/derive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fold a confirmed checkpoint's structured `InterpretedIntent` into remediation
|
|
3
|
+
* block / finding ORDERING (DC-1, remediate half).
|
|
4
|
+
*
|
|
5
|
+
* The user's `free_form_intent` is interpreted ONCE, deterministically, by the
|
|
6
|
+
* single shared interpreter (`interpretFreeFormIntent`) into lens weights,
|
|
7
|
+
* priority signals, and scope emphases. This module consumes that structured
|
|
8
|
+
* signal to reorder the plan's findings (and the blocks that carry them) so the
|
|
9
|
+
* work the user emphasised is dispatched first.
|
|
10
|
+
*
|
|
11
|
+
* Hard boundaries (mirroring audit's planning boost):
|
|
12
|
+
* - ORDERING ONLY. Intent never drops, filters, or mutates a finding — dropping
|
|
13
|
+
* is the review/clarification gate's job (DC-1 tradeoff note). Every input
|
|
14
|
+
* finding/block is present in the output; only their order changes.
|
|
15
|
+
* - INV-S04: the verbatim `free_form_intent` string is never read here. Only the
|
|
16
|
+
* derived `InterpretedIntent` (lens weights / priority / scope) is consumed, so
|
|
17
|
+
* the raw directive can never leak into a worker prompt via the ordering path.
|
|
18
|
+
* - STABLE. Equal-weight findings keep their original relative order, so ordering
|
|
19
|
+
* is deterministic across runs.
|
|
20
|
+
*
|
|
21
|
+
* Pure and synchronous — no IO, no LLM.
|
|
22
|
+
*/
|
|
23
|
+
import type { InterpretedIntent } from "audit-tools/shared";
|
|
24
|
+
import type { Finding, RemediationBlock } from "../state/types.js";
|
|
25
|
+
/**
|
|
26
|
+
* The intent-derived ordering weight for a single finding: its severity base
|
|
27
|
+
* plus boosts for an emphasised lens, an emphasised scope path, and any priority
|
|
28
|
+
* signal. Higher weight sorts earlier. When the intent is empty (no lens
|
|
29
|
+
* weights, scope, or priority), this collapses to the severity base, so an
|
|
30
|
+
* absent/empty `free_form_intent` leaves ordering driven purely by severity.
|
|
31
|
+
*/
|
|
32
|
+
export declare function findingIntentWeight(finding: Finding, intent: InterpretedIntent, needles?: string[]): number;
|
|
33
|
+
export interface IntentOrderingResult {
|
|
34
|
+
findings: Finding[];
|
|
35
|
+
blocks: RemediationBlock[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Reorder `findings` and `blocks` by intent-derived weight (descending), stably.
|
|
39
|
+
*
|
|
40
|
+
* - Findings sort by `findingIntentWeight` desc, ties broken by original index.
|
|
41
|
+
* - Blocks sort by the MAX intent weight of their member findings (so a block
|
|
42
|
+
* carrying an emphasised finding is dispatched first), ties broken by original
|
|
43
|
+
* index. A block's internal item order is left untouched.
|
|
44
|
+
* - When the intent carries no signal, both arrays are returned UNCHANGED (no
|
|
45
|
+
* reordering, no severity-shuffle) so behaviour is a strict no-op without a
|
|
46
|
+
* `free_form_intent`.
|
|
47
|
+
*
|
|
48
|
+
* Never adds, drops, or mutates a finding/block — ordering only.
|
|
49
|
+
*/
|
|
50
|
+
export declare function applyIntentOrdering(findings: Finding[], blocks: RemediationBlock[], intent: InterpretedIntent): IntentOrderingResult;
|
|
51
|
+
//# sourceMappingURL=intentOrdering.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intentOrdering.d.ts","sourceRoot":"","sources":["../../../src/remediate/intent/intentOrdering.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAyDnE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,MAAM,EAAyB,GACvC,MAAM,CAaR;AAWD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,gBAAgB,EAAE,EAC1B,MAAM,EAAE,iBAAiB,GACxB,oBAAoB,CAmCtB"}
|