@deftai/directive-core 0.107.0 → 0.109.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/architecture/sor-preflight.js +2 -0
- package/dist/cache/operations.js +1 -1
- package/dist/check/cached-orchestrator.js +28 -3
- package/dist/check/gate-lists.d.ts +14 -0
- package/dist/check/gate-lists.js +26 -3
- package/dist/check/named-cause.js +18 -3
- package/dist/check/session-completed-ac.d.ts +1 -1
- package/dist/check/session-completed-ac.js +1 -1
- package/dist/codebase/provider.js +7 -1
- package/dist/consumer-check-contract/evaluate.d.ts +47 -0
- package/dist/consumer-check-contract/evaluate.js +181 -15
- package/dist/delivery-attempt/evaluate.d.ts +9 -1
- package/dist/delivery-attempt/evaluate.js +69 -0
- package/dist/delivery-attempt/handoff.js +1 -1
- package/dist/delivery-attempt/index.d.ts +1 -1
- package/dist/delivery-attempt/index.js +1 -1
- package/dist/deposit/live-procedure-exclusions.d.ts +18 -0
- package/dist/deposit/live-procedure-exclusions.js +110 -0
- package/dist/deposit/live-procedure-targets.d.ts +45 -0
- package/dist/deposit/live-procedure-targets.js +274 -0
- package/dist/deposit/python-free.d.ts +6 -0
- package/dist/deposit/python-free.js +15 -0
- package/dist/deposit/rewrite-deposit-links.d.ts +42 -0
- package/dist/deposit/rewrite-deposit-links.js +148 -0
- package/dist/deposit/run-stage-content-pack.d.ts +2 -0
- package/dist/deposit/run-stage-content-pack.js +3 -0
- package/dist/deposit/stage-content-pack.d.ts +17 -0
- package/dist/deposit/stage-content-pack.js +91 -0
- package/dist/design-critique/citation-grammar.d.ts +60 -0
- package/dist/design-critique/citation-grammar.js +303 -0
- package/dist/design-critique/completed-arc-record.d.ts +62 -0
- package/dist/design-critique/completed-arc-record.js +277 -0
- package/dist/freshness/bind.d.ts +32 -3
- package/dist/freshness/bind.js +58 -12
- package/dist/hooks/classify/host-session-identity.d.ts +89 -0
- package/dist/hooks/classify/host-session-identity.js +467 -0
- package/dist/hooks/classify/index.d.ts +3 -2
- package/dist/hooks/classify/index.js +3 -2
- package/dist/hooks/classify/paths.d.ts +9 -0
- package/dist/hooks/classify/paths.js +39 -0
- package/dist/hooks/classify/stdin.d.ts +5 -0
- package/dist/hooks/classify/stdin.js +94 -1
- package/dist/hooks/dest-form.d.ts +20 -1
- package/dist/hooks/dest-form.js +158 -21
- package/dist/hooks/dispatcher.d.ts +58 -3
- package/dist/hooks/dispatcher.js +762 -73
- package/dist/hooks/fixtures/cases.d.ts +22 -2
- package/dist/hooks/fixtures/cases.js +228 -0
- package/dist/hooks/git-destructive-log.d.ts +32 -0
- package/dist/hooks/git-destructive-log.js +46 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/scope.js +3 -1
- package/dist/hooks/shell-write-targets.d.ts +10 -0
- package/dist/hooks/shell-write-targets.js +274 -0
- package/dist/hooks/tools.d.ts +20 -2
- package/dist/hooks/tools.js +30 -1
- package/dist/init-deposit/agent-hooks.d.ts +2 -1
- package/dist/init-deposit/agent-hooks.js +8 -1
- package/dist/init-deposit/gitignore.d.ts +7 -0
- package/dist/init-deposit/gitignore.js +24 -0
- package/dist/init-deposit/hook-runtime-travel.d.ts +77 -0
- package/dist/init-deposit/hook-runtime-travel.js +269 -0
- package/dist/init-deposit/init-deposit.js +3 -0
- package/dist/init-deposit/refresh.js +7 -0
- package/dist/init-deposit/runtime-writers.d.ts +14 -0
- package/dist/init-deposit/runtime-writers.js +33 -0
- package/dist/intake/clause-derivation.js +9 -3
- package/dist/intake/issue-ingest.d.ts +6 -1
- package/dist/intake/issue-ingest.js +83 -4
- package/dist/intake/platform-capabilities.d.ts +9 -2
- package/dist/intake/platform-capabilities.js +38 -9
- package/dist/intake/reconcile-issues.js +13 -13
- package/dist/lifecycle/brief-envelope.d.ts +25 -0
- package/dist/lifecycle/brief-envelope.js +42 -0
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.js +1 -0
- package/dist/literal-acceptance/evaluate.js +14 -5
- package/dist/literal-acceptance/index.d.ts +1 -1
- package/dist/literal-acceptance/index.js +1 -1
- package/dist/literal-acceptance/run.d.ts +2 -0
- package/dist/literal-acceptance/run.js +19 -1
- package/dist/orphan-active/candidate-scope.d.ts +53 -0
- package/dist/orphan-active/candidate-scope.js +157 -0
- package/dist/orphan-active/evaluate.d.ts +52 -0
- package/dist/orphan-active/evaluate.js +250 -128
- package/dist/orphan-active/index.d.ts +2 -0
- package/dist/orphan-active/index.js +2 -0
- package/dist/orphan-active/issue-state.d.ts +121 -0
- package/dist/orphan-active/issue-state.js +278 -0
- package/dist/platform/cursor-managed-runtime.d.ts +95 -0
- package/dist/platform/cursor-managed-runtime.js +241 -0
- package/dist/platform/index.d.ts +1 -0
- package/dist/platform/index.js +1 -0
- package/dist/platform/platform-capabilities.d.ts +23 -1
- package/dist/platform/platform-capabilities.js +55 -15
- package/dist/policy/ceremony-dial.js +5 -9
- package/dist/policy/host-hooks.js +4 -9
- package/dist/policy/merge-approval-head.js +7 -6
- package/dist/policy/org-force-on-migration.js +5 -10
- package/dist/policy/plan-extensions.d.ts +14 -2
- package/dist/policy/plan-extensions.js +24 -3
- package/dist/policy/product-signal.js +5 -10
- package/dist/policy/require-human-merge.js +5 -9
- package/dist/policy/resolve.js +77 -16
- package/dist/policy/value-feedback.js +9 -18
- package/dist/pr-closeout-attestable/evaluate.d.ts +80 -0
- package/dist/pr-closeout-attestable/evaluate.js +306 -0
- package/dist/pr-closeout-attestable/index.d.ts +2 -0
- package/dist/pr-closeout-attestable/index.js +2 -0
- package/dist/pr-closing-keywords/gh.js +32 -9
- package/dist/pr-closing-keywords/main.d.ts +1 -0
- package/dist/pr-closing-keywords/main.js +68 -3
- package/dist/pr-closing-keywords/types.d.ts +2 -0
- package/dist/pr-merge-readiness/gh.js +32 -9
- package/dist/pr-protected-issues/gh.d.ts +6 -2
- package/dist/pr-protected-issues/gh.js +42 -11
- package/dist/pr-wait-mergeable/cascade.d.ts +9 -1
- package/dist/pr-wait-mergeable/cascade.js +21 -1
- package/dist/pr-wait-mergeable/types.d.ts +2 -0
- package/dist/pr-wait-mergeable/wrappers.d.ts +6 -0
- package/dist/pr-wait-mergeable/wrappers.js +14 -3
- package/dist/preflight/evaluate.d.ts +15 -0
- package/dist/preflight/evaluate.js +29 -3
- package/dist/product-first-done-gate/acceptance-resolver.d.ts +14 -2
- package/dist/product-first-done-gate/acceptance-resolver.js +13 -2
- package/dist/product-first-done-gate/evaluate.js +23 -9
- package/dist/product-first-done-gate/types.js +2 -0
- package/dist/release/cli-drift-report.d.ts +68 -0
- package/dist/release/cli-drift-report.js +189 -0
- package/dist/release/consumer-hard-stops.d.ts +48 -0
- package/dist/release/consumer-hard-stops.js +140 -0
- package/dist/release/consumer-readiness-disclosure.d.ts +18 -0
- package/dist/release/consumer-readiness-disclosure.js +51 -0
- package/dist/release/index.d.ts +3 -0
- package/dist/release/index.js +3 -0
- package/dist/release/issue-state-fetch.d.ts +5 -3
- package/dist/release/issue-state-fetch.js +86 -21
- package/dist/release/native-steps.js +1 -0
- package/dist/release/pipeline.js +74 -0
- package/dist/release/run-consumer-readiness.d.ts +15 -0
- package/dist/release/run-consumer-readiness.js +24 -0
- package/dist/release/types.d.ts +20 -0
- package/dist/render/constants.d.ts +4 -0
- package/dist/render/constants.js +11 -8
- package/dist/render/export-spec.js +31 -5
- package/dist/render/index.d.ts +1 -1
- package/dist/render/index.js +1 -1
- package/dist/render/prd-render.d.ts +4 -1
- package/dist/render/prd-render.js +82 -23
- package/dist/render/project-render.js +14 -7
- package/dist/render/scope-outlook.d.ts +2 -0
- package/dist/render/scope-outlook.js +3 -0
- package/dist/render/spec-render.js +2 -2
- package/dist/resolution/package-manager.d.ts +33 -4
- package/dist/resolution/package-manager.js +210 -9
- package/dist/review-monitor/constants.d.ts +7 -0
- package/dist/review-monitor/constants.js +7 -0
- package/dist/review-monitor/github-lease.d.ts +98 -1
- package/dist/review-monitor/github-lease.js +186 -4
- package/dist/review-monitor/lease-comment.d.ts +36 -0
- package/dist/review-monitor/lease-comment.js +103 -2
- package/dist/run-summary/types.d.ts +2 -2
- package/dist/scm/build-command.d.ts +2 -2
- package/dist/scm/build-command.js +2 -2
- package/dist/scm/call-shape.d.ts +25 -0
- package/dist/scm/call-shape.js +59 -0
- package/dist/scm/call.d.ts +7 -4
- package/dist/scm/call.js +48 -9
- package/dist/scm/design-critique-chip.d.ts +1 -0
- package/dist/scm/design-critique-chip.js +22 -6
- package/dist/scm/gh-rest.d.ts +34 -13
- package/dist/scm/gh-rest.js +168 -15
- package/dist/scm/index.d.ts +2 -0
- package/dist/scm/index.js +2 -0
- package/dist/scm/readiness.d.ts +2 -0
- package/dist/scm/readiness.js +28 -4
- package/dist/scm/spawn-status.d.ts +33 -0
- package/dist/scm/spawn-status.js +53 -0
- package/dist/scope/acceptance-evidence.d.ts +1 -1
- package/dist/scope/project-definition-sync.js +14 -7
- package/dist/scope/transition.js +4 -14
- package/dist/session/ac-pass-banking.d.ts +2 -2
- package/dist/session/ac-pass-banking.js +2 -2
- package/dist/session/git.d.ts +24 -0
- package/dist/session/git.js +138 -2
- package/dist/session/host-session-owner.d.ts +53 -0
- package/dist/session/host-session-owner.js +89 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.js +1 -0
- package/dist/session/occupancy.d.ts +259 -13
- package/dist/session/occupancy.js +877 -33
- package/dist/session/ritual-sentinel.d.ts +5 -0
- package/dist/session/ritual-sentinel.js +5 -0
- package/dist/session/session-ready.d.ts +5 -1
- package/dist/session/session-ready.js +98 -8
- package/dist/session/session-start.d.ts +5 -1
- package/dist/session/session-start.js +32 -17
- package/dist/session/toolchain-preflight.d.ts +13 -3
- package/dist/session/toolchain-preflight.js +93 -18
- package/dist/session/verify-ac-session-cache.d.ts +2 -2
- package/dist/session/verify-ac-session-cache.js +2 -2
- package/dist/session/verify-session-ritual.d.ts +11 -0
- package/dist/session/verify-session-ritual.js +60 -15
- package/dist/slice/constants.d.ts +1 -1
- package/dist/spec-authority/constants.d.ts +10 -2
- package/dist/spec-authority/constants.js +53 -8
- package/dist/spec-authority/resolver.d.ts +3 -0
- package/dist/spec-authority/resolver.js +55 -7
- package/dist/subprocess/max-buffer.d.ts +14 -0
- package/dist/subprocess/max-buffer.js +15 -0
- package/dist/swarm/complete-cohort.d.ts +2 -0
- package/dist/swarm/complete-cohort.js +21 -13
- package/dist/swarm/index.d.ts +1 -0
- package/dist/swarm/index.js +1 -0
- package/dist/swarm/launch-cli.js +53 -33
- package/dist/swarm/launch.d.ts +8 -0
- package/dist/swarm/launch.js +63 -43
- package/dist/swarm/pre-dispatch-cli.js +2 -1
- package/dist/swarm/pre-dispatch.js +10 -1
- package/dist/swarm/subagent-status-dir.d.ts +27 -0
- package/dist/swarm/subagent-status-dir.js +42 -0
- package/dist/swarm/worktrees.d.ts +17 -3
- package/dist/swarm/worktrees.js +48 -4
- package/dist/triage/evaluate/worktrees.js +153 -6
- package/dist/triage/scope/mutations-core.d.ts +2 -6
- package/dist/triage/scope/mutations-core.js +23 -55
- package/dist/triage/scope-drift/add-ignore.js +5 -39
- package/dist/triage/subscribe/index.d.ts +2 -6
- package/dist/triage/subscribe/index.js +15 -65
- package/dist/triage/welcome/writers.js +15 -74
- package/dist/umbrella-current-shape/index.d.ts +51 -3
- package/dist/umbrella-current-shape/index.js +106 -18
- package/dist/validate-content/deposit-required.d.ts +39 -0
- package/dist/validate-content/deposit-required.js +147 -0
- package/dist/validate-content/index.d.ts +1 -0
- package/dist/validate-content/index.js +1 -0
- package/dist/validate-content/validate-links.d.ts +2 -3
- package/dist/validate-content/validate-links.js +29 -2
- package/dist/vbrief-activate/activate.d.ts +7 -2
- package/dist/vbrief-activate/activate.js +26 -13
- package/dist/vbrief-build/index.d.ts +2 -1
- package/dist/vbrief-build/index.js +2 -1
- package/dist/vbrief-build/parity-scenarios.js +5 -5
- package/dist/vbrief-build/project-definition-io.d.ts +63 -3
- package/dist/vbrief-build/project-definition-io.js +357 -31
- package/dist/vbrief-build/project-definition-mutation.d.ts +32 -0
- package/dist/vbrief-build/project-definition-mutation.js +43 -0
- package/dist/vbrief-validate/conformance.d.ts +1 -0
- package/dist/vbrief-validate/conformance.js +85 -8
- package/dist/vbrief-validate/main.js +2 -0
- package/dist/vbrief-validate/precutover.js +5 -10
- package/dist/verify-ac/clauses.d.ts +62 -2
- package/dist/verify-ac/clauses.js +183 -111
- package/dist/verify-ac/evaluate.d.ts +9 -0
- package/dist/verify-ac/evaluate.js +32 -9
- package/dist/verify-ac/index.d.ts +1 -1
- package/dist/verify-ac/index.js +1 -1
- package/dist/verify-env/node-runtime.d.ts +8 -4
- package/dist/verify-env/node-runtime.js +9 -6
- package/dist/verify-env/toolchain-check.d.ts +35 -3
- package/dist/verify-env/toolchain-check.js +155 -36
- package/dist/verify-source/deposit-closure.d.ts +23 -0
- package/dist/verify-source/deposit-closure.js +162 -0
- package/dist/verify-source/index.d.ts +2 -0
- package/dist/verify-source/index.js +2 -0
- package/dist/verify-source/project-definition-mutation-boundary.d.ts +104 -0
- package/dist/verify-source/project-definition-mutation-boundary.js +326 -0
- package/dist/verify-source/semantic-single-source.d.ts +36 -0
- package/dist/verify-source/semantic-single-source.js +349 -0
- package/package.json +7 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { resolveLifecycleLayout } from "../layout/resolve.js";
|
|
4
|
+
import { ENV_PROJECT_PATH } from "../vbrief-build/project-definition-io.js";
|
|
4
5
|
import { evaluateConformance } from "./conformance.js";
|
|
5
6
|
import { USAGE } from "./constants.js";
|
|
6
7
|
import { validateAll } from "./validate-all.js";
|
|
@@ -130,6 +131,7 @@ export function runConformance(argv) {
|
|
|
130
131
|
const { exitCode, message } = evaluateConformance(resolve(projectRoot), {
|
|
131
132
|
mode,
|
|
132
133
|
allowListPath,
|
|
134
|
+
projectDefinitionPath: process.env[ENV_PROJECT_PATH] ?? null,
|
|
133
135
|
});
|
|
134
136
|
if (exitCode === 0) {
|
|
135
137
|
if (!quiet) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { resolveLifecycleLayout, resolveLifecycleRoot
|
|
4
|
-
import {
|
|
5
|
-
import { isFullSpecState, isGreenfieldSpecExport } from "../spec-authority/resolver.js";
|
|
3
|
+
import { resolveLifecycleLayout, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
4
|
+
import { GENERATED_SPEC_PURPOSE } from "../spec-authority/constants.js";
|
|
5
|
+
import { contentHasResolvedSpecSource, isFullSpecState, isGreenfieldSpecExport, } from "../spec-authority/resolver.js";
|
|
6
6
|
import { DEPRECATION_SENTINEL } from "../vbrief-build/constants.js";
|
|
7
7
|
export { DEPRECATION_SENTINEL as DEPRECATED_REDIRECT_SENTINEL };
|
|
8
8
|
const DEPRECATION_REDIRECT_PURPOSE = "<!-- Purpose: deprecation redirect -->";
|
|
@@ -27,15 +27,10 @@ export function isDeprecationRedirect(content) {
|
|
|
27
27
|
}
|
|
28
28
|
/** Full-spec generated export (layout-resolved specification artifact source line). */
|
|
29
29
|
export function isGeneratedSpecificationExport(projectRoot, content) {
|
|
30
|
-
if (!content.includes(GENERATED_SPEC_PURPOSE)
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
return existsSync(resolveSpecArtifactPath(projectRoot));
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
30
|
+
if (!content.includes(GENERATED_SPEC_PURPOSE)) {
|
|
37
31
|
return false;
|
|
38
32
|
}
|
|
33
|
+
return contentHasResolvedSpecSource(projectRoot, content);
|
|
39
34
|
}
|
|
40
35
|
/** Return true for a fully current generated spec export (full-spec or greenfield). */
|
|
41
36
|
export function isCurrentGeneratedSpecification(projectRoot, content) {
|
|
@@ -21,6 +21,24 @@ export interface ClauseWalkResult {
|
|
|
21
21
|
readonly artifact_path: string | null;
|
|
22
22
|
readonly outcome: ClauseOutcome;
|
|
23
23
|
readonly detail: string;
|
|
24
|
+
/**
|
|
25
|
+
* True when the walk had an oracle for this clause — a path the brief declared
|
|
26
|
+
* on `plan.metadata.swarm.file_scope`. An unbound or undeclared clause can only
|
|
27
|
+
* ever come back `unverifiable`, so it carries no weight either way (#3835).
|
|
28
|
+
*/
|
|
29
|
+
readonly adjudicable: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Read-scope for the walk. Empty means nothing is read (#3835). */
|
|
32
|
+
export interface ClauseWalkOptions {
|
|
33
|
+
/**
|
|
34
|
+
* The brief's declared artifact surface: `plan.metadata.swarm.file_scope`,
|
|
35
|
+
* which carries the #3145 approved-scope digest and `humanApproval` gate.
|
|
36
|
+
*
|
|
37
|
+
* Required rather than optional, and fail-closed when empty: the walk reads
|
|
38
|
+
* files, and a caller that forgets to pass a scope must read nothing rather
|
|
39
|
+
* than fall back to whatever path a clause happens to carry.
|
|
40
|
+
*/
|
|
41
|
+
readonly declaredScope: readonly string[];
|
|
24
42
|
}
|
|
25
43
|
export interface ClauseWalkReport {
|
|
26
44
|
readonly clauses: readonly ClauseWalkResult[];
|
|
@@ -30,8 +48,24 @@ export interface ClauseWalkReport {
|
|
|
30
48
|
readonly ok: boolean;
|
|
31
49
|
readonly message: string;
|
|
32
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Acceptance lines declared on `plan.items` (#3826).
|
|
53
|
+
*
|
|
54
|
+
* Prefers `item.narrative.Acceptance`, then `item.title` — criteria routinely live
|
|
55
|
+
* in the title with an empty `narrative`, which is how a declared acceptance
|
|
56
|
+
* surface stayed invisible to derivation on #3794 and #3819.
|
|
57
|
+
*/
|
|
58
|
+
export declare function collectPlanItemAcceptanceSurface(plan: Record<string, unknown>): string[];
|
|
59
|
+
export interface ClauseDerivationSources {
|
|
60
|
+
/**
|
|
61
|
+
* Declared acceptance lines from `plan.items`. When non-empty this IS the
|
|
62
|
+
* derived clause set; the statement extractors below are the path for a brief
|
|
63
|
+
* that declares no items (#3826).
|
|
64
|
+
*/
|
|
65
|
+
readonly itemSurface?: readonly string[];
|
|
66
|
+
}
|
|
33
67
|
/** Numbered independently testable clauses from the task statement (#3323). */
|
|
34
|
-
export declare function deriveAcceptanceClauses(taskStatement: string): AcceptanceClause[];
|
|
68
|
+
export declare function deriveAcceptanceClauses(taskStatement: string, sources?: ClauseDerivationSources): AcceptanceClause[];
|
|
35
69
|
export declare function readAcceptanceClauses(acceptance: unknown): AcceptanceClause[];
|
|
36
70
|
export declare function serializeAcceptanceClauses(clauses: readonly AcceptanceClause[]): Record<string, unknown>[];
|
|
37
71
|
/**
|
|
@@ -43,7 +77,33 @@ export declare function stampDerivedClausesOnAcceptance(plan: Record<string, unk
|
|
|
43
77
|
readonly clauses: readonly AcceptanceClause[];
|
|
44
78
|
};
|
|
45
79
|
export declare function isScratchArtifactPath(artifactPath: string): boolean;
|
|
46
|
-
|
|
80
|
+
/**
|
|
81
|
+
* The declared artifact surface for a brief: `plan.metadata.swarm.file_scope`.
|
|
82
|
+
*
|
|
83
|
+
* This is the only surface the walk reads from (#3835). It sits inside the
|
|
84
|
+
* xBRIEF, so a GitHub commenter cannot write it, and it is already gated by the
|
|
85
|
+
* #3145 approved-scope digest and `humanApproval` stamp.
|
|
86
|
+
*/
|
|
87
|
+
export declare function readDeclaredArtifactScope(plan: unknown): string[];
|
|
88
|
+
/** True when the clause binding is a declared entry or sits under a declared directory. */
|
|
89
|
+
export declare function isDeclaredArtifactPath(artifactPath: string, declaredScope: readonly string[]): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Clauses the walk had an oracle for — bound to a declared artifact path.
|
|
92
|
+
*
|
|
93
|
+
* A clause with no oracle can only ever be `unverifiable`, so requiring a positive
|
|
94
|
+
* `verified` from a set of them is unsatisfiable by correct work rather than a
|
|
95
|
+
* quality bar (#3826).
|
|
96
|
+
*/
|
|
97
|
+
export declare function countAdjudicableClauses(rows: readonly ClauseWalkResult[]): number;
|
|
98
|
+
/**
|
|
99
|
+
* Adjudicable clauses the walk did not verify.
|
|
100
|
+
*
|
|
101
|
+
* #3826 made `verified > 0` a *set* predicate excused by an empty oracle set, so
|
|
102
|
+
* one bound-and-verified clause re-armed the whole set and covered siblings with
|
|
103
|
+
* their own unmet oracle. Counting per clause is what removes that seam (#3835).
|
|
104
|
+
*/
|
|
105
|
+
export declare function countUnverifiedAdjudicableClauses(rows: readonly ClauseWalkResult[]): number;
|
|
106
|
+
export declare function walkAcceptanceClauses(clauses: readonly AcceptanceClause[], projectRoot: string, options: ClauseWalkOptions): ClauseWalkReport;
|
|
47
107
|
/** Done reports lead with failed/unverifiable; unverifiable is never dropped. */
|
|
48
108
|
export declare function formatClauseWalkMessage(report: Omit<ClauseWalkReport, "message"> & {
|
|
49
109
|
readonly message?: string;
|
|
@@ -133,14 +133,44 @@ function collectPathBearingLines(text) {
|
|
|
133
133
|
}
|
|
134
134
|
return items;
|
|
135
135
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Acceptance lines declared on `plan.items` (#3826).
|
|
138
|
+
*
|
|
139
|
+
* Prefers `item.narrative.Acceptance`, then `item.title` — criteria routinely live
|
|
140
|
+
* in the title with an empty `narrative`, which is how a declared acceptance
|
|
141
|
+
* surface stayed invisible to derivation on #3794 and #3819.
|
|
142
|
+
*/
|
|
143
|
+
export function collectPlanItemAcceptanceSurface(plan) {
|
|
144
|
+
if (!Array.isArray(plan.items)) {
|
|
140
145
|
return [];
|
|
141
146
|
}
|
|
142
|
-
const
|
|
147
|
+
const lines = [];
|
|
148
|
+
const seen = new Set();
|
|
149
|
+
for (const entry of plan.items) {
|
|
150
|
+
const item = asRecord(entry);
|
|
151
|
+
if (item === null) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const narrative = asRecord(item.narrative);
|
|
155
|
+
const declared = narrative === null ? undefined : narrative.Acceptance;
|
|
156
|
+
const source = isNonEmptyString(declared) ? declared : item.title;
|
|
157
|
+
if (!isNonEmptyString(source)) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const line = normalizeClauseText(source.replace(/\*\*/g, ""));
|
|
161
|
+
const key = line.toLowerCase();
|
|
162
|
+
if (line.length === 0 || isMetaClause(line) || seen.has(key)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
seen.add(key);
|
|
166
|
+
lines.push(line);
|
|
167
|
+
}
|
|
168
|
+
return lines;
|
|
169
|
+
}
|
|
170
|
+
/** Acceptance lines the statement itself declares, in extractor precedence order. */
|
|
171
|
+
function collectStatementSurface(text) {
|
|
143
172
|
const raw = [];
|
|
173
|
+
const acHeading = findAcHeading(text);
|
|
144
174
|
if (acHeading !== null) {
|
|
145
175
|
raw.push(...parseListItems(sliceAcSection(text, acHeading))
|
|
146
176
|
.map((item) => normalizeClauseText(item.title.replace(/\*\*/g, "")))
|
|
@@ -151,6 +181,22 @@ export function deriveAcceptanceClauses(taskStatement) {
|
|
|
151
181
|
if (raw.length === 0) {
|
|
152
182
|
raw.push(...collectPathBearingLines(text));
|
|
153
183
|
}
|
|
184
|
+
return raw;
|
|
185
|
+
}
|
|
186
|
+
/** Numbered independently testable clauses from the task statement (#3323). */
|
|
187
|
+
export function deriveAcceptanceClauses(taskStatement, sources = {}) {
|
|
188
|
+
const text = taskStatement.trim();
|
|
189
|
+
const itemSurface = (sources.itemSurface ?? [])
|
|
190
|
+
.map((line) => normalizeClauseText(line))
|
|
191
|
+
.filter((line) => line.length > 0 && !isMetaClause(line));
|
|
192
|
+
// #3826: `plan.items` is a declared, body-scoped acceptance surface, while the
|
|
193
|
+
// statement carries the whole untrusted issue comment thread. Preferring the
|
|
194
|
+
// declared surface is what keeps an acceptance-shaped heading buried in that
|
|
195
|
+
// thread from becoming the gate — the #3794 and #3819 mechanism.
|
|
196
|
+
let raw = itemSurface;
|
|
197
|
+
if (raw.length === 0) {
|
|
198
|
+
raw = text.length > 0 ? collectStatementSurface(text) : [];
|
|
199
|
+
}
|
|
154
200
|
const seen = new Set();
|
|
155
201
|
const clauses = [];
|
|
156
202
|
for (const line of raw) {
|
|
@@ -163,28 +209,20 @@ export function deriveAcceptanceClauses(taskStatement) {
|
|
|
163
209
|
}
|
|
164
210
|
return clauses;
|
|
165
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Clause text is untrusted: the statement is the issue body plus its whole
|
|
214
|
+
* comment thread, and anyone can comment on a public issue. Lifting a path out
|
|
215
|
+
* of it chose both the file `walkOne` read and the needle it matched, so a
|
|
216
|
+
* third-party comment could ask the gate a question about any in-root file and
|
|
217
|
+
* read the answer off the report (#3835).
|
|
218
|
+
*
|
|
219
|
+
* Derivation therefore binds no path at all. `walkOne` binds only what the brief
|
|
220
|
+
* declares on `plan.metadata.swarm.file_scope`. Measured across the six live
|
|
221
|
+
* briefs at filing, prose extraction bound two paths and verified zero clauses,
|
|
222
|
+
* so this costs no verification capability.
|
|
223
|
+
*/
|
|
166
224
|
function buildClause(id, text) {
|
|
167
|
-
|
|
168
|
-
if (paths.length <= 1) {
|
|
169
|
-
return {
|
|
170
|
-
id,
|
|
171
|
-
text,
|
|
172
|
-
artifact_path: paths[0] ?? null,
|
|
173
|
-
ambiguous: false,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
const readings = paths.map((artifact_path) => ({
|
|
177
|
-
text: `${text} [reading: ${artifact_path}]`,
|
|
178
|
-
artifact_path,
|
|
179
|
-
}));
|
|
180
|
-
return {
|
|
181
|
-
id,
|
|
182
|
-
text,
|
|
183
|
-
artifact_path: paths[0] ?? null,
|
|
184
|
-
ambiguous: true,
|
|
185
|
-
readings,
|
|
186
|
-
chosen_reading: 0,
|
|
187
|
-
};
|
|
225
|
+
return { id, text, artifact_path: null, ambiguous: false };
|
|
188
226
|
}
|
|
189
227
|
export function readAcceptanceClauses(acceptance) {
|
|
190
228
|
const rec = asRecord(acceptance);
|
|
@@ -273,7 +311,9 @@ export function stampDerivedClausesOnAcceptance(plan, taskStatement) {
|
|
|
273
311
|
if (Array.isArray(commands) && commands.length > 0) {
|
|
274
312
|
return { plan, clauses: [] };
|
|
275
313
|
}
|
|
276
|
-
const clauses = deriveAcceptanceClauses(taskStatement
|
|
314
|
+
const clauses = deriveAcceptanceClauses(taskStatement, {
|
|
315
|
+
itemSurface: collectPlanItemAcceptanceSurface(plan),
|
|
316
|
+
});
|
|
277
317
|
if (clauses.length === 0) {
|
|
278
318
|
return { plan, clauses: [] };
|
|
279
319
|
}
|
|
@@ -295,6 +335,57 @@ export function isScratchArtifactPath(artifactPath) {
|
|
|
295
335
|
const unified = artifactPath.replace(/\\/g, "/").toLowerCase();
|
|
296
336
|
return unified.split("/").some((seg) => SCRATCH_SEGMENTS.has(seg));
|
|
297
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Repo-relative comparison form: forward slashes, no `./` prefix, no trailing slash.
|
|
340
|
+
*
|
|
341
|
+
* Segment-split rather than regex-replaced: the inputs include clause text a
|
|
342
|
+
* commenter wrote, and the anchored slash-run patterns this replaced backtrack
|
|
343
|
+
* quadratically on a long run of separators (`js/polynomial-redos`).
|
|
344
|
+
*/
|
|
345
|
+
function normalizeScopePath(value) {
|
|
346
|
+
const unified = value.trim().split("\\").join("/");
|
|
347
|
+
const rooted = unified.startsWith("/") ? "/" : "";
|
|
348
|
+
const segments = unified.split("/").filter((segment) => segment.length > 0);
|
|
349
|
+
if (rooted.length === 0 && segments[0] === ".") {
|
|
350
|
+
segments.shift();
|
|
351
|
+
}
|
|
352
|
+
return rooted + segments.join("/");
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* The declared artifact surface for a brief: `plan.metadata.swarm.file_scope`.
|
|
356
|
+
*
|
|
357
|
+
* This is the only surface the walk reads from (#3835). It sits inside the
|
|
358
|
+
* xBRIEF, so a GitHub commenter cannot write it, and it is already gated by the
|
|
359
|
+
* #3145 approved-scope digest and `humanApproval` stamp.
|
|
360
|
+
*/
|
|
361
|
+
export function readDeclaredArtifactScope(plan) {
|
|
362
|
+
const swarm = asRecord(asRecord(asRecord(plan)?.metadata)?.swarm);
|
|
363
|
+
if (swarm === null || !Array.isArray(swarm.file_scope)) {
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
const declared = new Set();
|
|
367
|
+
for (const entry of swarm.file_scope) {
|
|
368
|
+
if (!isNonEmptyString(entry)) {
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
const normalized = normalizeScopePath(entry);
|
|
372
|
+
if (normalized.length > 0) {
|
|
373
|
+
declared.add(normalized);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return [...declared];
|
|
377
|
+
}
|
|
378
|
+
/** True when the clause binding is a declared entry or sits under a declared directory. */
|
|
379
|
+
export function isDeclaredArtifactPath(artifactPath, declaredScope) {
|
|
380
|
+
const candidate = normalizeScopePath(artifactPath);
|
|
381
|
+
if (candidate.length === 0 || candidate === ".." || candidate.startsWith("../")) {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
return declaredScope.some((raw) => {
|
|
385
|
+
const entry = normalizeScopePath(raw);
|
|
386
|
+
return entry.length > 0 && (candidate === entry || candidate.startsWith(`${entry}/`));
|
|
387
|
+
});
|
|
388
|
+
}
|
|
298
389
|
function isContained(root, child) {
|
|
299
390
|
const rel = relative(resolve(root), resolve(child));
|
|
300
391
|
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
@@ -318,7 +409,7 @@ function extractExpectedTokens(clause) {
|
|
|
318
409
|
}
|
|
319
410
|
return tokens;
|
|
320
411
|
}
|
|
321
|
-
function walkOne(clause, projectRoot) {
|
|
412
|
+
function walkOne(clause, projectRoot, declaredScope) {
|
|
322
413
|
const artifactPath = clause.artifact_path;
|
|
323
414
|
if (artifactPath === null || artifactPath.trim().length === 0) {
|
|
324
415
|
return {
|
|
@@ -327,73 +418,64 @@ function walkOne(clause, projectRoot) {
|
|
|
327
418
|
artifact_path: artifactPath,
|
|
328
419
|
outcome: "unverifiable",
|
|
329
420
|
detail: "no artifact path bound",
|
|
421
|
+
adjudicable: false,
|
|
330
422
|
};
|
|
331
423
|
}
|
|
332
|
-
|
|
424
|
+
// #3835: every filesystem touch below this line — existence, stat, and the
|
|
425
|
+
// token read — is gated here. A path the brief did not declare is refused
|
|
426
|
+
// before the walk learns anything about it, and the refusal detail is a
|
|
427
|
+
// function of the path alone, so a rejected clause reports the same thing
|
|
428
|
+
// whatever needle it carries. Filtering the shape of the path upstream was
|
|
429
|
+
// measured to narrow this by zero; this is the line that closes it.
|
|
430
|
+
if (!isDeclaredArtifactPath(artifactPath, declaredScope)) {
|
|
333
431
|
return {
|
|
334
432
|
id: clause.id,
|
|
335
433
|
text: clause.text,
|
|
336
434
|
artifact_path: artifactPath,
|
|
337
|
-
outcome: "
|
|
338
|
-
detail:
|
|
435
|
+
outcome: "unverifiable",
|
|
436
|
+
detail: `artifact path is not declared on plan.metadata.swarm.file_scope, so nothing ` +
|
|
437
|
+
`was read: ${artifactPath} (#3835)`,
|
|
438
|
+
adjudicable: false,
|
|
339
439
|
};
|
|
340
440
|
}
|
|
441
|
+
// Past the declared-scope gate the walk has an oracle, so every outcome below
|
|
442
|
+
// counts toward the `ok` predicate.
|
|
443
|
+
const bound = (outcome, detail) => ({
|
|
444
|
+
id: clause.id,
|
|
445
|
+
text: clause.text,
|
|
446
|
+
artifact_path: artifactPath,
|
|
447
|
+
outcome,
|
|
448
|
+
detail,
|
|
449
|
+
adjudicable: true,
|
|
450
|
+
});
|
|
451
|
+
if (isScratchArtifactPath(artifactPath)) {
|
|
452
|
+
return bound("failed", "artifact path is a buffer/scratch copy, not the shipped path");
|
|
453
|
+
}
|
|
341
454
|
const abs = resolve(projectRoot, artifactPath);
|
|
342
455
|
if (!isContained(projectRoot, abs)) {
|
|
343
|
-
return
|
|
344
|
-
id: clause.id,
|
|
345
|
-
text: clause.text,
|
|
346
|
-
artifact_path: artifactPath,
|
|
347
|
-
outcome: "failed",
|
|
348
|
-
detail: "artifact path escaped the project root",
|
|
349
|
-
};
|
|
456
|
+
return bound("failed", "artifact path escaped the project root");
|
|
350
457
|
}
|
|
351
458
|
if (!existsSync(abs)) {
|
|
352
459
|
if (NEGATED_EXISTENCE.test(clause.text)) {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
};
|
|
460
|
+
// #3826: absence is not evidence. The negation phrase is matched against the
|
|
461
|
+
// whole clause text, so on a derived clause it routinely refers to something
|
|
462
|
+
// other than the bound path — a bare `git.ts` in analysis prose passed here
|
|
463
|
+
// and was the sole `verified` row propping up the `ok` predicate on #3794.
|
|
464
|
+
return bound("unverifiable", `artifact absent at ${artifactPath}; a prose negation is not evidence ` +
|
|
465
|
+
`the clause requires this path to be absent (#3826)`);
|
|
360
466
|
}
|
|
361
|
-
return {
|
|
362
|
-
id: clause.id,
|
|
363
|
-
text: clause.text,
|
|
364
|
-
artifact_path: artifactPath,
|
|
365
|
-
outcome: "failed",
|
|
366
|
-
detail: `artifact missing at stated path ${artifactPath}`,
|
|
367
|
-
};
|
|
467
|
+
return bound("failed", `artifact missing at stated path ${artifactPath}`);
|
|
368
468
|
}
|
|
369
469
|
try {
|
|
370
470
|
if (!statSync(abs).isFile()) {
|
|
371
|
-
return {
|
|
372
|
-
id: clause.id,
|
|
373
|
-
text: clause.text,
|
|
374
|
-
artifact_path: artifactPath,
|
|
375
|
-
outcome: "failed",
|
|
376
|
-
detail: `stated path is not a shipped file: ${artifactPath}`,
|
|
377
|
-
};
|
|
471
|
+
return bound("failed", `stated path is not a shipped file: ${artifactPath}`);
|
|
378
472
|
}
|
|
379
473
|
}
|
|
380
474
|
catch {
|
|
381
|
-
return {
|
|
382
|
-
id: clause.id,
|
|
383
|
-
text: clause.text,
|
|
384
|
-
artifact_path: artifactPath,
|
|
385
|
-
outcome: "failed",
|
|
386
|
-
detail: `artifact unreadable at stated path ${artifactPath}`,
|
|
387
|
-
};
|
|
475
|
+
return bound("failed", `artifact unreadable at stated path ${artifactPath}`);
|
|
388
476
|
}
|
|
389
477
|
if (NEGATED_EXISTENCE.test(clause.text)) {
|
|
390
|
-
return {
|
|
391
|
-
id: clause.id,
|
|
392
|
-
text: clause.text,
|
|
393
|
-
artifact_path: artifactPath,
|
|
394
|
-
outcome: "failed",
|
|
395
|
-
detail: `artifact exists at ${artifactPath} but the clause requires absence`,
|
|
396
|
-
};
|
|
478
|
+
return bound("failed", `artifact exists at ${artifactPath} but the clause requires absence`);
|
|
397
479
|
}
|
|
398
480
|
const expected = extractExpectedTokens(clause);
|
|
399
481
|
if (expected.length > 0) {
|
|
@@ -402,55 +484,45 @@ function walkOne(clause, projectRoot) {
|
|
|
402
484
|
body = readFileSync(abs, "utf8");
|
|
403
485
|
}
|
|
404
486
|
catch {
|
|
405
|
-
return {
|
|
406
|
-
id: clause.id,
|
|
407
|
-
text: clause.text,
|
|
408
|
-
artifact_path: artifactPath,
|
|
409
|
-
outcome: "failed",
|
|
410
|
-
detail: `artifact unreadable at stated path ${artifactPath}`,
|
|
411
|
-
};
|
|
487
|
+
return bound("failed", `artifact unreadable at stated path ${artifactPath}`);
|
|
412
488
|
}
|
|
413
489
|
const missing = expected.filter((token) => !body.includes(token));
|
|
414
490
|
if (missing.length > 0) {
|
|
415
|
-
return {
|
|
416
|
-
id: clause.id,
|
|
417
|
-
text: clause.text,
|
|
418
|
-
artifact_path: artifactPath,
|
|
419
|
-
outcome: "failed",
|
|
420
|
-
detail: `expected token(s) missing from ${artifactPath}: ${missing.join(", ")}`,
|
|
421
|
-
};
|
|
491
|
+
return bound("failed", `expected token(s) missing from ${artifactPath}: ${missing.join(", ")}`);
|
|
422
492
|
}
|
|
423
|
-
return {
|
|
424
|
-
id: clause.id,
|
|
425
|
-
text: clause.text,
|
|
426
|
-
artifact_path: artifactPath,
|
|
427
|
-
outcome: "verified",
|
|
428
|
-
detail: `tokens present in shipped artifact ${artifactPath}`,
|
|
429
|
-
};
|
|
493
|
+
return bound("verified", `tokens present in shipped artifact ${artifactPath}`);
|
|
430
494
|
}
|
|
431
495
|
if (EXISTENCE_CLAIM.test(clause.text)) {
|
|
432
|
-
return {
|
|
433
|
-
id: clause.id,
|
|
434
|
-
text: clause.text,
|
|
435
|
-
artifact_path: artifactPath,
|
|
436
|
-
outcome: "verified",
|
|
437
|
-
detail: `shipped artifact exists at ${artifactPath}`,
|
|
438
|
-
};
|
|
496
|
+
return bound("verified", `shipped artifact exists at ${artifactPath}`);
|
|
439
497
|
}
|
|
440
|
-
return {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
498
|
+
return bound("unverifiable", `cannot evaluate behavioral claim against shipped artifact ${artifactPath}`);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Clauses the walk had an oracle for — bound to a declared artifact path.
|
|
502
|
+
*
|
|
503
|
+
* A clause with no oracle can only ever be `unverifiable`, so requiring a positive
|
|
504
|
+
* `verified` from a set of them is unsatisfiable by correct work rather than a
|
|
505
|
+
* quality bar (#3826).
|
|
506
|
+
*/
|
|
507
|
+
export function countAdjudicableClauses(rows) {
|
|
508
|
+
return rows.filter((row) => row.adjudicable).length;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Adjudicable clauses the walk did not verify.
|
|
512
|
+
*
|
|
513
|
+
* #3826 made `verified > 0` a *set* predicate excused by an empty oracle set, so
|
|
514
|
+
* one bound-and-verified clause re-armed the whole set and covered siblings with
|
|
515
|
+
* their own unmet oracle. Counting per clause is what removes that seam (#3835).
|
|
516
|
+
*/
|
|
517
|
+
export function countUnverifiedAdjudicableClauses(rows) {
|
|
518
|
+
return rows.filter((row) => row.adjudicable && row.outcome !== "verified").length;
|
|
447
519
|
}
|
|
448
|
-
export function walkAcceptanceClauses(clauses, projectRoot) {
|
|
449
|
-
const walked = clauses.map((clause) => walkOne(clause, projectRoot));
|
|
520
|
+
export function walkAcceptanceClauses(clauses, projectRoot, options) {
|
|
521
|
+
const walked = clauses.map((clause) => walkOne(clause, projectRoot, options.declaredScope));
|
|
450
522
|
const failed = walked.filter((row) => row.outcome === "failed");
|
|
451
523
|
const unverifiable = walked.filter((row) => row.outcome === "unverifiable");
|
|
452
524
|
const verified = walked.filter((row) => row.outcome === "verified");
|
|
453
|
-
const ok = failed.length === 0 && (
|
|
525
|
+
const ok = failed.length === 0 && countUnverifiedAdjudicableClauses(walked) === 0;
|
|
454
526
|
return {
|
|
455
527
|
clauses: walked,
|
|
456
528
|
failed,
|
|
@@ -44,6 +44,15 @@ export declare const VERIFY_AC_CHECK_ID_PREFIX = "verify:ac";
|
|
|
44
44
|
export declare function verifyAcCheckId(scopeKey?: string | null): string;
|
|
45
45
|
/** Test seam: isolate stdout-dest buffer across cases. */
|
|
46
46
|
export declare function resetInProcessVerificationBuffer(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Product-oracle outcome for one acceptance walk (#3615).
|
|
49
|
+
*
|
|
50
|
+
* A safety refusal is not a measurement. All-refused walks emit nothing.
|
|
51
|
+
* Mixed refused + executed-pass walks emit nothing (filtering refusals then
|
|
52
|
+
* classifying the remainder would be a false green). Any executed fail still
|
|
53
|
+
* emits fail. flag.ts is unchanged.
|
|
54
|
+
*/
|
|
55
|
+
export declare function productOracleOutcomeForWalk(runs: readonly LiteralAcceptanceRunResult[]): "pass" | "fail" | null;
|
|
47
56
|
/**
|
|
48
57
|
* Record one walk-level verification event for the executed command set (#3322 / #3397).
|
|
49
58
|
* Fail and pass use the same method_fingerprint shape (command list + cwd hash).
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
import { existsSync, readFileSync } from "node:fs";
|
|
12
12
|
import { resolve } from "node:path";
|
|
13
|
+
import { isSafetyRefusalRun } from "../literal-acceptance/run.js";
|
|
13
14
|
import { parseRunSummaryJsonl, RunSummaryEmitter, resolveRunSummaryDestination, } from "../run-summary/index.js";
|
|
14
15
|
import { flagPassAfterFailWithMethodChange, readVerificationAttempts, unresolvedMethodChangePasses, } from "./flag.js";
|
|
15
16
|
function formatUnresolved(flag) {
|
|
@@ -57,6 +58,25 @@ function inProcessVerificationText() {
|
|
|
57
58
|
}
|
|
58
59
|
return inProcessVerificationLines.join("\n");
|
|
59
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Product-oracle outcome for one acceptance walk (#3615).
|
|
63
|
+
*
|
|
64
|
+
* A safety refusal is not a measurement. All-refused walks emit nothing.
|
|
65
|
+
* Mixed refused + executed-pass walks emit nothing (filtering refusals then
|
|
66
|
+
* classifying the remainder would be a false green). Any executed fail still
|
|
67
|
+
* emits fail. flag.ts is unchanged.
|
|
68
|
+
*/
|
|
69
|
+
export function productOracleOutcomeForWalk(runs) {
|
|
70
|
+
const refused = runs.filter(isSafetyRefusalRun);
|
|
71
|
+
const executed = runs.filter((run) => !isSafetyRefusalRun(run));
|
|
72
|
+
if (executed.length === 0) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
if (refused.length > 0 && executed.every((run) => run.ok)) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return executed.every((run) => run.ok) ? "pass" : "fail";
|
|
79
|
+
}
|
|
60
80
|
/**
|
|
61
81
|
* Record one walk-level verification event for the executed command set (#3322 / #3397).
|
|
62
82
|
* Fail and pass use the same method_fingerprint shape (command list + cwd hash).
|
|
@@ -69,6 +89,10 @@ export function emitVerifyAcAttempts(options) {
|
|
|
69
89
|
if (options.runs.length === 0) {
|
|
70
90
|
return;
|
|
71
91
|
}
|
|
92
|
+
const outcome = productOracleOutcomeForWalk(options.runs);
|
|
93
|
+
if (outcome === null) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
72
96
|
try {
|
|
73
97
|
const env = options.env ?? process.env;
|
|
74
98
|
const projectRoot = resolve(options.projectRoot);
|
|
@@ -85,16 +109,15 @@ export function emitVerifyAcAttempts(options) {
|
|
|
85
109
|
component: "verify-ac",
|
|
86
110
|
writeStdout: options.writeStdout,
|
|
87
111
|
});
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const cwdKey =
|
|
112
|
+
// Method identity is the executed command set. Refused rows are not
|
|
113
|
+
// measurements; including them would make a later same-command product
|
|
114
|
+
// fix look like a method change (#3615 Greptile P1).
|
|
115
|
+
const executed = options.runs.filter((run) => !isSafetyRefusalRun(run));
|
|
116
|
+
const commands = executed.map((run) => run.command);
|
|
117
|
+
const firstCwd = executed[0]?.cwd ?? "";
|
|
118
|
+
const cwdKey = executed.every((run) => run.cwd === firstCwd)
|
|
95
119
|
? firstCwd
|
|
96
|
-
:
|
|
97
|
-
const outcome = options.runs.every((run) => run.ok) ? "pass" : "fail";
|
|
120
|
+
: executed.map((run) => run.cwd).join("\0");
|
|
98
121
|
const emitted = emitter.emitVerification({
|
|
99
122
|
check_id: checkId,
|
|
100
123
|
method_fingerprint: methodFingerprintForWalk(commands, cwdKey),
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Extends #3156: a red product verification may not be self-adjudicated
|
|
5
5
|
* by editing the comparison. Deterministic surface is the flagged event.
|
|
6
6
|
*/
|
|
7
|
-
export { type AcceptanceClause, type AcceptanceClauseReading, type ClauseOutcome, type ClauseWalkReport, type ClauseWalkResult, deriveAcceptanceClauses, formatClauseWalkMessage, isScratchArtifactPath, readAcceptanceClauses, serializeAcceptanceClauses, stampDerivedClausesOnAcceptance, walkAcceptanceClauses, } from "./clauses.js";
|
|
7
|
+
export { type AcceptanceClause, type AcceptanceClauseReading, type ClauseDerivationSources, type ClauseOutcome, type ClauseWalkOptions, type ClauseWalkReport, type ClauseWalkResult, collectPlanItemAcceptanceSurface, countAdjudicableClauses, countUnverifiedAdjudicableClauses, deriveAcceptanceClauses, formatClauseWalkMessage, isDeclaredArtifactPath, isScratchArtifactPath, readAcceptanceClauses, readDeclaredArtifactScope, serializeAcceptanceClauses, stampDerivedClausesOnAcceptance, walkAcceptanceClauses, } from "./clauses.js";
|
|
8
8
|
export { type EvaluateProductOracleIntegrityOptions, emitVerifyAcAttempts, evaluateProductOracleIntegrity, mergeOracleVerdict, methodFingerprintForWalk, type OracleIntegrityResultFields, type ProductOracleIntegrityVerdict, VERIFY_AC_CHECK_ID_PREFIX, verifyAcCheckId, } from "./evaluate.js";
|
|
9
9
|
export { commandCountFromFingerprint, type FlaggedMethodChangePass, flagPassAfterFailFromJsonl, flagPassAfterFailWithMethodChange, readVerificationAttempts, unresolvedMethodChangePasses, type VerificationAttempt, } from "./flag.js";
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/verify-ac/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Extends #3156: a red product verification may not be self-adjudicated
|
|
5
5
|
* by editing the comparison. Deterministic surface is the flagged event.
|
|
6
6
|
*/
|
|
7
|
-
export { deriveAcceptanceClauses, formatClauseWalkMessage, isScratchArtifactPath, readAcceptanceClauses, serializeAcceptanceClauses, stampDerivedClausesOnAcceptance, walkAcceptanceClauses, } from "./clauses.js";
|
|
7
|
+
export { collectPlanItemAcceptanceSurface, countAdjudicableClauses, countUnverifiedAdjudicableClauses, deriveAcceptanceClauses, formatClauseWalkMessage, isDeclaredArtifactPath, isScratchArtifactPath, readAcceptanceClauses, readDeclaredArtifactScope, serializeAcceptanceClauses, stampDerivedClausesOnAcceptance, walkAcceptanceClauses, } from "./clauses.js";
|
|
8
8
|
export { emitVerifyAcAttempts, evaluateProductOracleIntegrity, mergeOracleVerdict, methodFingerprintForWalk, VERIFY_AC_CHECK_ID_PREFIX, verifyAcCheckId, } from "./evaluate.js";
|
|
9
9
|
export { commandCountFromFingerprint, flagPassAfterFailFromJsonl, flagPassAfterFailWithMethodChange, readVerificationAttempts, unresolvedMethodChangePasses, } from "./flag.js";
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
/** Node/
|
|
2
|
-
|
|
1
|
+
/** Node/package-manager presence contract for TS-backed consumer gates. */
|
|
2
|
+
import type { PackageManager } from "../resolution/package-manager.js";
|
|
3
|
+
/** All supported Node/package-manager tool names across consumer projects. */
|
|
4
|
+
export declare const NODE_RUNTIME_TOOL_NAMES: readonly ["node", "npm", "pnpm"];
|
|
3
5
|
export declare const NODE_RUNTIME_REMEDIATION = "Node.js and pnpm are required for TS-backed deft gates. Install Node 20+ (see .nvmrc), then run: corepack enable && corepack prepare pnpm@latest --activate. See UPGRADING.md \u00A7 Node runtime.";
|
|
4
|
-
/**
|
|
5
|
-
export declare
|
|
6
|
+
/** npm ships with the supported Node distribution; Corepack/pnpm is not required. */
|
|
7
|
+
export declare const NPM_RUNTIME_REMEDIATION = "Node.js and npm are required for TS-backed deft gates. Install or repair Node 20+ (see .nvmrc; npm is bundled), then re-run the consumer check. See UPGRADING.md \u00A7 Node runtime.";
|
|
8
|
+
/** Append remediation lines for node or the package manager selected by the project. */
|
|
9
|
+
export declare function nodeRuntimeRemediationLines(failed: readonly string[], packageManager?: PackageManager): readonly string[];
|
|
6
10
|
//# sourceMappingURL=node-runtime.d.ts.map
|