@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.
Files changed (271) hide show
  1. package/dist/architecture/sor-preflight.js +2 -0
  2. package/dist/cache/operations.js +1 -1
  3. package/dist/check/cached-orchestrator.js +28 -3
  4. package/dist/check/gate-lists.d.ts +14 -0
  5. package/dist/check/gate-lists.js +26 -3
  6. package/dist/check/named-cause.js +18 -3
  7. package/dist/check/session-completed-ac.d.ts +1 -1
  8. package/dist/check/session-completed-ac.js +1 -1
  9. package/dist/codebase/provider.js +7 -1
  10. package/dist/consumer-check-contract/evaluate.d.ts +47 -0
  11. package/dist/consumer-check-contract/evaluate.js +181 -15
  12. package/dist/delivery-attempt/evaluate.d.ts +9 -1
  13. package/dist/delivery-attempt/evaluate.js +69 -0
  14. package/dist/delivery-attempt/handoff.js +1 -1
  15. package/dist/delivery-attempt/index.d.ts +1 -1
  16. package/dist/delivery-attempt/index.js +1 -1
  17. package/dist/deposit/live-procedure-exclusions.d.ts +18 -0
  18. package/dist/deposit/live-procedure-exclusions.js +110 -0
  19. package/dist/deposit/live-procedure-targets.d.ts +45 -0
  20. package/dist/deposit/live-procedure-targets.js +274 -0
  21. package/dist/deposit/python-free.d.ts +6 -0
  22. package/dist/deposit/python-free.js +15 -0
  23. package/dist/deposit/rewrite-deposit-links.d.ts +42 -0
  24. package/dist/deposit/rewrite-deposit-links.js +148 -0
  25. package/dist/deposit/run-stage-content-pack.d.ts +2 -0
  26. package/dist/deposit/run-stage-content-pack.js +3 -0
  27. package/dist/deposit/stage-content-pack.d.ts +17 -0
  28. package/dist/deposit/stage-content-pack.js +91 -0
  29. package/dist/design-critique/citation-grammar.d.ts +60 -0
  30. package/dist/design-critique/citation-grammar.js +303 -0
  31. package/dist/design-critique/completed-arc-record.d.ts +62 -0
  32. package/dist/design-critique/completed-arc-record.js +277 -0
  33. package/dist/freshness/bind.d.ts +32 -3
  34. package/dist/freshness/bind.js +58 -12
  35. package/dist/hooks/classify/host-session-identity.d.ts +89 -0
  36. package/dist/hooks/classify/host-session-identity.js +467 -0
  37. package/dist/hooks/classify/index.d.ts +3 -2
  38. package/dist/hooks/classify/index.js +3 -2
  39. package/dist/hooks/classify/paths.d.ts +9 -0
  40. package/dist/hooks/classify/paths.js +39 -0
  41. package/dist/hooks/classify/stdin.d.ts +5 -0
  42. package/dist/hooks/classify/stdin.js +94 -1
  43. package/dist/hooks/dest-form.d.ts +20 -1
  44. package/dist/hooks/dest-form.js +158 -21
  45. package/dist/hooks/dispatcher.d.ts +58 -3
  46. package/dist/hooks/dispatcher.js +762 -73
  47. package/dist/hooks/fixtures/cases.d.ts +22 -2
  48. package/dist/hooks/fixtures/cases.js +228 -0
  49. package/dist/hooks/git-destructive-log.d.ts +32 -0
  50. package/dist/hooks/git-destructive-log.js +46 -0
  51. package/dist/hooks/index.d.ts +2 -0
  52. package/dist/hooks/index.js +2 -0
  53. package/dist/hooks/scope.js +3 -1
  54. package/dist/hooks/shell-write-targets.d.ts +10 -0
  55. package/dist/hooks/shell-write-targets.js +274 -0
  56. package/dist/hooks/tools.d.ts +20 -2
  57. package/dist/hooks/tools.js +30 -1
  58. package/dist/init-deposit/agent-hooks.d.ts +2 -1
  59. package/dist/init-deposit/agent-hooks.js +8 -1
  60. package/dist/init-deposit/gitignore.d.ts +7 -0
  61. package/dist/init-deposit/gitignore.js +24 -0
  62. package/dist/init-deposit/hook-runtime-travel.d.ts +77 -0
  63. package/dist/init-deposit/hook-runtime-travel.js +269 -0
  64. package/dist/init-deposit/init-deposit.js +3 -0
  65. package/dist/init-deposit/refresh.js +7 -0
  66. package/dist/init-deposit/runtime-writers.d.ts +14 -0
  67. package/dist/init-deposit/runtime-writers.js +33 -0
  68. package/dist/intake/clause-derivation.js +9 -3
  69. package/dist/intake/issue-ingest.d.ts +6 -1
  70. package/dist/intake/issue-ingest.js +83 -4
  71. package/dist/intake/platform-capabilities.d.ts +9 -2
  72. package/dist/intake/platform-capabilities.js +38 -9
  73. package/dist/intake/reconcile-issues.js +13 -13
  74. package/dist/lifecycle/brief-envelope.d.ts +25 -0
  75. package/dist/lifecycle/brief-envelope.js +42 -0
  76. package/dist/lifecycle/index.d.ts +1 -0
  77. package/dist/lifecycle/index.js +1 -0
  78. package/dist/literal-acceptance/evaluate.js +14 -5
  79. package/dist/literal-acceptance/index.d.ts +1 -1
  80. package/dist/literal-acceptance/index.js +1 -1
  81. package/dist/literal-acceptance/run.d.ts +2 -0
  82. package/dist/literal-acceptance/run.js +19 -1
  83. package/dist/orphan-active/candidate-scope.d.ts +53 -0
  84. package/dist/orphan-active/candidate-scope.js +157 -0
  85. package/dist/orphan-active/evaluate.d.ts +52 -0
  86. package/dist/orphan-active/evaluate.js +250 -128
  87. package/dist/orphan-active/index.d.ts +2 -0
  88. package/dist/orphan-active/index.js +2 -0
  89. package/dist/orphan-active/issue-state.d.ts +121 -0
  90. package/dist/orphan-active/issue-state.js +278 -0
  91. package/dist/platform/cursor-managed-runtime.d.ts +95 -0
  92. package/dist/platform/cursor-managed-runtime.js +241 -0
  93. package/dist/platform/index.d.ts +1 -0
  94. package/dist/platform/index.js +1 -0
  95. package/dist/platform/platform-capabilities.d.ts +23 -1
  96. package/dist/platform/platform-capabilities.js +55 -15
  97. package/dist/policy/ceremony-dial.js +5 -9
  98. package/dist/policy/host-hooks.js +4 -9
  99. package/dist/policy/merge-approval-head.js +7 -6
  100. package/dist/policy/org-force-on-migration.js +5 -10
  101. package/dist/policy/plan-extensions.d.ts +14 -2
  102. package/dist/policy/plan-extensions.js +24 -3
  103. package/dist/policy/product-signal.js +5 -10
  104. package/dist/policy/require-human-merge.js +5 -9
  105. package/dist/policy/resolve.js +77 -16
  106. package/dist/policy/value-feedback.js +9 -18
  107. package/dist/pr-closeout-attestable/evaluate.d.ts +80 -0
  108. package/dist/pr-closeout-attestable/evaluate.js +306 -0
  109. package/dist/pr-closeout-attestable/index.d.ts +2 -0
  110. package/dist/pr-closeout-attestable/index.js +2 -0
  111. package/dist/pr-closing-keywords/gh.js +32 -9
  112. package/dist/pr-closing-keywords/main.d.ts +1 -0
  113. package/dist/pr-closing-keywords/main.js +68 -3
  114. package/dist/pr-closing-keywords/types.d.ts +2 -0
  115. package/dist/pr-merge-readiness/gh.js +32 -9
  116. package/dist/pr-protected-issues/gh.d.ts +6 -2
  117. package/dist/pr-protected-issues/gh.js +42 -11
  118. package/dist/pr-wait-mergeable/cascade.d.ts +9 -1
  119. package/dist/pr-wait-mergeable/cascade.js +21 -1
  120. package/dist/pr-wait-mergeable/types.d.ts +2 -0
  121. package/dist/pr-wait-mergeable/wrappers.d.ts +6 -0
  122. package/dist/pr-wait-mergeable/wrappers.js +14 -3
  123. package/dist/preflight/evaluate.d.ts +15 -0
  124. package/dist/preflight/evaluate.js +29 -3
  125. package/dist/product-first-done-gate/acceptance-resolver.d.ts +14 -2
  126. package/dist/product-first-done-gate/acceptance-resolver.js +13 -2
  127. package/dist/product-first-done-gate/evaluate.js +23 -9
  128. package/dist/product-first-done-gate/types.js +2 -0
  129. package/dist/release/cli-drift-report.d.ts +68 -0
  130. package/dist/release/cli-drift-report.js +189 -0
  131. package/dist/release/consumer-hard-stops.d.ts +48 -0
  132. package/dist/release/consumer-hard-stops.js +140 -0
  133. package/dist/release/consumer-readiness-disclosure.d.ts +18 -0
  134. package/dist/release/consumer-readiness-disclosure.js +51 -0
  135. package/dist/release/index.d.ts +3 -0
  136. package/dist/release/index.js +3 -0
  137. package/dist/release/issue-state-fetch.d.ts +5 -3
  138. package/dist/release/issue-state-fetch.js +86 -21
  139. package/dist/release/native-steps.js +1 -0
  140. package/dist/release/pipeline.js +74 -0
  141. package/dist/release/run-consumer-readiness.d.ts +15 -0
  142. package/dist/release/run-consumer-readiness.js +24 -0
  143. package/dist/release/types.d.ts +20 -0
  144. package/dist/render/constants.d.ts +4 -0
  145. package/dist/render/constants.js +11 -8
  146. package/dist/render/export-spec.js +31 -5
  147. package/dist/render/index.d.ts +1 -1
  148. package/dist/render/index.js +1 -1
  149. package/dist/render/prd-render.d.ts +4 -1
  150. package/dist/render/prd-render.js +82 -23
  151. package/dist/render/project-render.js +14 -7
  152. package/dist/render/scope-outlook.d.ts +2 -0
  153. package/dist/render/scope-outlook.js +3 -0
  154. package/dist/render/spec-render.js +2 -2
  155. package/dist/resolution/package-manager.d.ts +33 -4
  156. package/dist/resolution/package-manager.js +210 -9
  157. package/dist/review-monitor/constants.d.ts +7 -0
  158. package/dist/review-monitor/constants.js +7 -0
  159. package/dist/review-monitor/github-lease.d.ts +98 -1
  160. package/dist/review-monitor/github-lease.js +186 -4
  161. package/dist/review-monitor/lease-comment.d.ts +36 -0
  162. package/dist/review-monitor/lease-comment.js +103 -2
  163. package/dist/run-summary/types.d.ts +2 -2
  164. package/dist/scm/build-command.d.ts +2 -2
  165. package/dist/scm/build-command.js +2 -2
  166. package/dist/scm/call-shape.d.ts +25 -0
  167. package/dist/scm/call-shape.js +59 -0
  168. package/dist/scm/call.d.ts +7 -4
  169. package/dist/scm/call.js +48 -9
  170. package/dist/scm/design-critique-chip.d.ts +1 -0
  171. package/dist/scm/design-critique-chip.js +22 -6
  172. package/dist/scm/gh-rest.d.ts +34 -13
  173. package/dist/scm/gh-rest.js +168 -15
  174. package/dist/scm/index.d.ts +2 -0
  175. package/dist/scm/index.js +2 -0
  176. package/dist/scm/readiness.d.ts +2 -0
  177. package/dist/scm/readiness.js +28 -4
  178. package/dist/scm/spawn-status.d.ts +33 -0
  179. package/dist/scm/spawn-status.js +53 -0
  180. package/dist/scope/acceptance-evidence.d.ts +1 -1
  181. package/dist/scope/project-definition-sync.js +14 -7
  182. package/dist/scope/transition.js +4 -14
  183. package/dist/session/ac-pass-banking.d.ts +2 -2
  184. package/dist/session/ac-pass-banking.js +2 -2
  185. package/dist/session/git.d.ts +24 -0
  186. package/dist/session/git.js +138 -2
  187. package/dist/session/host-session-owner.d.ts +53 -0
  188. package/dist/session/host-session-owner.js +89 -0
  189. package/dist/session/index.d.ts +1 -0
  190. package/dist/session/index.js +1 -0
  191. package/dist/session/occupancy.d.ts +259 -13
  192. package/dist/session/occupancy.js +877 -33
  193. package/dist/session/ritual-sentinel.d.ts +5 -0
  194. package/dist/session/ritual-sentinel.js +5 -0
  195. package/dist/session/session-ready.d.ts +5 -1
  196. package/dist/session/session-ready.js +98 -8
  197. package/dist/session/session-start.d.ts +5 -1
  198. package/dist/session/session-start.js +32 -17
  199. package/dist/session/toolchain-preflight.d.ts +13 -3
  200. package/dist/session/toolchain-preflight.js +93 -18
  201. package/dist/session/verify-ac-session-cache.d.ts +2 -2
  202. package/dist/session/verify-ac-session-cache.js +2 -2
  203. package/dist/session/verify-session-ritual.d.ts +11 -0
  204. package/dist/session/verify-session-ritual.js +60 -15
  205. package/dist/slice/constants.d.ts +1 -1
  206. package/dist/spec-authority/constants.d.ts +10 -2
  207. package/dist/spec-authority/constants.js +53 -8
  208. package/dist/spec-authority/resolver.d.ts +3 -0
  209. package/dist/spec-authority/resolver.js +55 -7
  210. package/dist/subprocess/max-buffer.d.ts +14 -0
  211. package/dist/subprocess/max-buffer.js +15 -0
  212. package/dist/swarm/complete-cohort.d.ts +2 -0
  213. package/dist/swarm/complete-cohort.js +21 -13
  214. package/dist/swarm/index.d.ts +1 -0
  215. package/dist/swarm/index.js +1 -0
  216. package/dist/swarm/launch-cli.js +53 -33
  217. package/dist/swarm/launch.d.ts +8 -0
  218. package/dist/swarm/launch.js +63 -43
  219. package/dist/swarm/pre-dispatch-cli.js +2 -1
  220. package/dist/swarm/pre-dispatch.js +10 -1
  221. package/dist/swarm/subagent-status-dir.d.ts +27 -0
  222. package/dist/swarm/subagent-status-dir.js +42 -0
  223. package/dist/swarm/worktrees.d.ts +17 -3
  224. package/dist/swarm/worktrees.js +48 -4
  225. package/dist/triage/evaluate/worktrees.js +153 -6
  226. package/dist/triage/scope/mutations-core.d.ts +2 -6
  227. package/dist/triage/scope/mutations-core.js +23 -55
  228. package/dist/triage/scope-drift/add-ignore.js +5 -39
  229. package/dist/triage/subscribe/index.d.ts +2 -6
  230. package/dist/triage/subscribe/index.js +15 -65
  231. package/dist/triage/welcome/writers.js +15 -74
  232. package/dist/umbrella-current-shape/index.d.ts +51 -3
  233. package/dist/umbrella-current-shape/index.js +106 -18
  234. package/dist/validate-content/deposit-required.d.ts +39 -0
  235. package/dist/validate-content/deposit-required.js +147 -0
  236. package/dist/validate-content/index.d.ts +1 -0
  237. package/dist/validate-content/index.js +1 -0
  238. package/dist/validate-content/validate-links.d.ts +2 -3
  239. package/dist/validate-content/validate-links.js +29 -2
  240. package/dist/vbrief-activate/activate.d.ts +7 -2
  241. package/dist/vbrief-activate/activate.js +26 -13
  242. package/dist/vbrief-build/index.d.ts +2 -1
  243. package/dist/vbrief-build/index.js +2 -1
  244. package/dist/vbrief-build/parity-scenarios.js +5 -5
  245. package/dist/vbrief-build/project-definition-io.d.ts +63 -3
  246. package/dist/vbrief-build/project-definition-io.js +357 -31
  247. package/dist/vbrief-build/project-definition-mutation.d.ts +32 -0
  248. package/dist/vbrief-build/project-definition-mutation.js +43 -0
  249. package/dist/vbrief-validate/conformance.d.ts +1 -0
  250. package/dist/vbrief-validate/conformance.js +85 -8
  251. package/dist/vbrief-validate/main.js +2 -0
  252. package/dist/vbrief-validate/precutover.js +5 -10
  253. package/dist/verify-ac/clauses.d.ts +62 -2
  254. package/dist/verify-ac/clauses.js +183 -111
  255. package/dist/verify-ac/evaluate.d.ts +9 -0
  256. package/dist/verify-ac/evaluate.js +32 -9
  257. package/dist/verify-ac/index.d.ts +1 -1
  258. package/dist/verify-ac/index.js +1 -1
  259. package/dist/verify-env/node-runtime.d.ts +8 -4
  260. package/dist/verify-env/node-runtime.js +9 -6
  261. package/dist/verify-env/toolchain-check.d.ts +35 -3
  262. package/dist/verify-env/toolchain-check.js +155 -36
  263. package/dist/verify-source/deposit-closure.d.ts +23 -0
  264. package/dist/verify-source/deposit-closure.js +162 -0
  265. package/dist/verify-source/index.d.ts +2 -0
  266. package/dist/verify-source/index.js +2 -0
  267. package/dist/verify-source/project-definition-mutation-boundary.d.ts +104 -0
  268. package/dist/verify-source/project-definition-mutation-boundary.js +326 -0
  269. package/dist/verify-source/semantic-single-source.d.ts +36 -0
  270. package/dist/verify-source/semantic-single-source.js +349 -0
  271. 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, resolveSpecArtifactPath, } from "../layout/resolve.js";
4
- import { contentHasGeneratedSpecSource, GENERATED_SPEC_PURPOSE, } from "../spec-authority/constants.js";
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) || !contentHasGeneratedSpecSource(content)) {
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
- export declare function walkAcceptanceClauses(clauses: readonly AcceptanceClause[], projectRoot: string): ClauseWalkReport;
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
- /** Numbered independently testable clauses from the task statement (#3323). */
137
- export function deriveAcceptanceClauses(taskStatement) {
138
- const text = taskStatement.trim();
139
- if (text.length === 0) {
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 acHeading = findAcHeading(text);
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
- const paths = extractPathTokens(text);
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
- if (isScratchArtifactPath(artifactPath)) {
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: "failed",
338
- detail: "artifact path is a buffer/scratch copy, not the shipped path",
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
- return {
354
- id: clause.id,
355
- text: clause.text,
356
- artifact_path: artifactPath,
357
- outcome: "verified",
358
- detail: `artifact correctly absent at ${artifactPath}`,
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
- id: clause.id,
442
- text: clause.text,
443
- artifact_path: artifactPath,
444
- outcome: "unverifiable",
445
- detail: `cannot evaluate behavioral claim against shipped artifact ${artifactPath}`,
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 && (verified.length > 0 || walked.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
- // One walk-level event: the method is the command set, not each command.
89
- // Per-command emit was blind to a shrinking list that kept the first command (#3397).
90
- const commands = options.runs.map((run) => run.command);
91
- const firstCwd = options.runs[0]?.cwd ?? "";
92
- // Hash the cwd key (joined only when cwds differ) so cwd paths never enter
93
- // the fingerprint; commandCountFromFingerprint can still count commands.
94
- const cwdKey = options.runs.every((run) => run.cwd === firstCwd)
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
- : options.runs.map((run) => run.cwd).join("\0");
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
@@ -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/pnpm presence contract for TS-backed consumer gates (#1828 / #1530). */
2
- export declare const NODE_RUNTIME_TOOL_NAMES: readonly ["node", "pnpm"];
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
- /** Append remediation lines when node or pnpm is among the missing tools. */
5
- export declare function nodeRuntimeRemediationLines(failed: readonly string[]): readonly string[];
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