@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
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* the missing derive step.
|
|
7
7
|
*/
|
|
8
8
|
import { ENV_RUN_SUMMARY_PATH, RunSummaryEmitter, } from "../run-summary/index.js";
|
|
9
|
-
import { deriveAcceptanceClauses, readAcceptanceClauses, serializeAcceptanceClauses, } from "../verify-ac/clauses.js";
|
|
9
|
+
import { collectPlanItemAcceptanceSurface, deriveAcceptanceClauses, readAcceptanceClauses, serializeAcceptanceClauses, } from "../verify-ac/clauses.js";
|
|
10
10
|
/** One-line remediation when a stamp has no statement-traceable clause (#3398). */
|
|
11
11
|
export const CLAUSE_STAMP_IMPLEMENTATION_ONLY_REMEDIATION = "derive clauses from the statement's testable constraints";
|
|
12
12
|
export const MISSING_AMBIGUITY_ATTESTATION_CAUSE = "missing_ambiguity_attestation";
|
|
@@ -72,7 +72,11 @@ export function collectTaskStatementFromPlan(plan) {
|
|
|
72
72
|
continue;
|
|
73
73
|
}
|
|
74
74
|
const narrative = asRecord(rec.narrative);
|
|
75
|
-
const
|
|
75
|
+
const declared = narrative?.Acceptance;
|
|
76
|
+
// #3826: criteria commonly live in item.title with an empty narrative object.
|
|
77
|
+
// Reading only narrative.Acceptance left them out of the statement entirely,
|
|
78
|
+
// so a clause derived from a title could not trace back to it.
|
|
79
|
+
const text = isNonEmptyString(declared) ? declared : rec.title;
|
|
76
80
|
if (isNonEmptyString(text)) {
|
|
77
81
|
parts.push(text.trim());
|
|
78
82
|
}
|
|
@@ -296,7 +300,9 @@ export function applyClauseDerivationToPlan(plan, options = {}) {
|
|
|
296
300
|
notice: "",
|
|
297
301
|
};
|
|
298
302
|
}
|
|
299
|
-
const clauses = deriveAcceptanceClauses(collectTaskStatementFromPlan(plan)
|
|
303
|
+
const clauses = deriveAcceptanceClauses(collectTaskStatementFromPlan(plan), {
|
|
304
|
+
itemSurface: collectPlanItemAcceptanceSurface(plan),
|
|
305
|
+
});
|
|
300
306
|
if (clauses.length === 0) {
|
|
301
307
|
return { applied: false, clauses: [], notice: "" };
|
|
302
308
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ScanFlag } from "../cache/scanner.js";
|
|
2
|
-
import { type IssueComment as ShapeIssueComment } from "../umbrella-current-shape/index.js";
|
|
2
|
+
import { type CurrentShapeNullReason, type IssueComment as ShapeIssueComment } from "../umbrella-current-shape/index.js";
|
|
3
3
|
import { LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY } from "../xbrief-migrate/constants.js";
|
|
4
4
|
import { type ScmCallFn } from "./reconcile-issues.js";
|
|
5
5
|
/** Reference type pointing at the canonical current-shape comment permalink (#1870). */
|
|
@@ -42,6 +42,11 @@ export declare function mapIngestCommentsToShapeComments(comments: readonly Issu
|
|
|
42
42
|
export declare function selectIngestCurrentShape(comments: readonly IssueComment[]): (ShapeIssueComment & {
|
|
43
43
|
pass: number;
|
|
44
44
|
}) | null;
|
|
45
|
+
/**
|
|
46
|
+
* Classify why `selectIngestCurrentShape` returned null so ingest can report a
|
|
47
|
+
* reason instead of silently omitting the CurrentShape narrative (#3934).
|
|
48
|
+
*/
|
|
49
|
+
export declare function describeIngestCurrentShapeNull(comments: readonly IssueComment[]): CurrentShapeNullReason;
|
|
45
50
|
/** Count maintainer current-shape comments (lint surface for !=1). */
|
|
46
51
|
export declare function countIngestCurrentShapeComments(comments: readonly IssueComment[]): number;
|
|
47
52
|
export declare function bodyControlCharacterLabels(body: string): string[];
|
|
@@ -2,6 +2,7 @@ import { lstatSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSyn
|
|
|
2
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { cacheGet } from "../cache/operations.js";
|
|
4
4
|
import { scan } from "../cache/scanner.js";
|
|
5
|
+
import { assertCompletedArcAllowsIngest, DesignCritiqueIngestBlockedError, } from "../design-critique/completed-arc-record.js";
|
|
5
6
|
import { assertWriteTargetSafe, ProjectionContainmentError } from "../fs/projection-containment.js";
|
|
6
7
|
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
7
8
|
import { captureAndAttachLiteralAcceptance } from "../literal-acceptance/index.js";
|
|
@@ -10,7 +11,7 @@ import { stampAcceptanceFromLiteralCapture } from "../product-first-done-gate/in
|
|
|
10
11
|
import { call } from "../scm/call.js";
|
|
11
12
|
import { resolveProjectRoot } from "../scope/project-context.js";
|
|
12
13
|
import { resolveProjectRepo } from "../slice/project-context.js";
|
|
13
|
-
import { countMaintainerCurrentShapeComments, mapIssueCommentEntry, RAW_ISSUE_COMMENTS_KEY, selectCurrentShapeComment, } from "../umbrella-current-shape/index.js";
|
|
14
|
+
import { countMaintainerCurrentShapeComments, describeCurrentShapeNull, mapIssueCommentEntry, RAW_ISSUE_COMMENTS_KEY, selectCurrentShapeComment, } from "../umbrella-current-shape/index.js";
|
|
14
15
|
import { slugify, TODAY } from "../vbrief-build/build.js";
|
|
15
16
|
import { EMITTED_VBRIEF_VERSION } from "../vbrief-build/constants.js";
|
|
16
17
|
import { stampDerivedClausesOnAcceptance } from "../verify-ac/clauses.js";
|
|
@@ -65,6 +66,13 @@ export function mapIngestCommentsToShapeComments(comments) {
|
|
|
65
66
|
export function selectIngestCurrentShape(comments) {
|
|
66
67
|
return selectCurrentShapeComment(mapIngestCommentsToShapeComments(comments));
|
|
67
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Classify why `selectIngestCurrentShape` returned null so ingest can report a
|
|
71
|
+
* reason instead of silently omitting the CurrentShape narrative (#3934).
|
|
72
|
+
*/
|
|
73
|
+
export function describeIngestCurrentShapeNull(comments) {
|
|
74
|
+
return describeCurrentShapeNull(mapIngestCommentsToShapeComments(comments));
|
|
75
|
+
}
|
|
68
76
|
/** Count maintainer current-shape comments (lint surface for !=1). */
|
|
69
77
|
export function countIngestCurrentShapeComments(comments) {
|
|
70
78
|
return countMaintainerCurrentShapeComments(mapIngestCommentsToShapeComments(comments));
|
|
@@ -408,6 +416,17 @@ export function buildIssueVbrief(issue, status, repoUrl, options = {}) {
|
|
|
408
416
|
// Scan shape body under the same fail-closed contract as Overview (#2306).
|
|
409
417
|
narratives.CurrentShape = scanUntrustedIngestText(number, currentShape.body);
|
|
410
418
|
}
|
|
419
|
+
else {
|
|
420
|
+
// #3934: a thread whose only shape comments failed the #2307 authorship
|
|
421
|
+
// filter is otherwise indistinguishable from a thread that never had one,
|
|
422
|
+
// so a cache-reading agent falls back to the stale body. The note is
|
|
423
|
+
// framework-authored and carries comment ids plus normalized author
|
|
424
|
+
// associations only -- no comment text -- so it needs no quarantine scan.
|
|
425
|
+
const shapeNullReason = describeIngestCurrentShapeNull(commentThread);
|
|
426
|
+
if (shapeNullReason.kind === "non-maintainer-shape") {
|
|
427
|
+
narratives.CurrentShapeUnavailable = shapeNullReason.message;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
411
430
|
if (labelNames.length > 0) {
|
|
412
431
|
narratives.Labels = labelNames.join(", ");
|
|
413
432
|
}
|
|
@@ -639,7 +658,8 @@ export function fetchSingleIssue(repo, number, options = {}) {
|
|
|
639
658
|
return null;
|
|
640
659
|
}
|
|
641
660
|
if (result.returncode !== 0) {
|
|
642
|
-
|
|
661
|
+
const invoked = result.args?.[0] ?? "gh";
|
|
662
|
+
process.stderr.write(`Error: ${invoked} failed fetching #${number}: ${result.stderr.trim()}\n`);
|
|
643
663
|
return null;
|
|
644
664
|
}
|
|
645
665
|
try {
|
|
@@ -703,6 +723,41 @@ function resolveIngestProjectRoot(vbriefDir, cwd) {
|
|
|
703
723
|
}
|
|
704
724
|
return null;
|
|
705
725
|
}
|
|
726
|
+
function issueLabelNames(issue) {
|
|
727
|
+
const labels = issue.labels;
|
|
728
|
+
if (!Array.isArray(labels))
|
|
729
|
+
return [];
|
|
730
|
+
const names = [];
|
|
731
|
+
for (const lbl of labels) {
|
|
732
|
+
if (typeof lbl === "string") {
|
|
733
|
+
names.push(lbl);
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
if (lbl !== null && typeof lbl === "object" && !Array.isArray(lbl)) {
|
|
737
|
+
const name = lbl.name;
|
|
738
|
+
if (typeof name === "string")
|
|
739
|
+
names.push(name);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return names;
|
|
743
|
+
}
|
|
744
|
+
function threadCommentsFromIssue(issue) {
|
|
745
|
+
const raw = issue[ISSUE_COMMENT_THREAD_KEY];
|
|
746
|
+
if (!Array.isArray(raw))
|
|
747
|
+
return [];
|
|
748
|
+
const out = [];
|
|
749
|
+
for (const entry of raw) {
|
|
750
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry))
|
|
751
|
+
continue;
|
|
752
|
+
const rec = entry;
|
|
753
|
+
const id = Number(rec.id);
|
|
754
|
+
if (!Number.isSafeInteger(id) || id <= 0)
|
|
755
|
+
continue;
|
|
756
|
+
const body = typeof rec.body === "string" ? rec.body : "";
|
|
757
|
+
out.push({ id, body });
|
|
758
|
+
}
|
|
759
|
+
return out;
|
|
760
|
+
}
|
|
706
761
|
export function ingestOne(issue, options) {
|
|
707
762
|
const number = Number(issue.number);
|
|
708
763
|
const refs = options.existingRefs ?? scanProvenanceRefs(options.vbriefDir);
|
|
@@ -719,6 +774,11 @@ export function ingestOne(issue, options) {
|
|
|
719
774
|
cwd: options.cwd,
|
|
720
775
|
cacheRoot: options.cacheRoot,
|
|
721
776
|
});
|
|
777
|
+
assertCompletedArcAllowsIngest({
|
|
778
|
+
issueNumber: number,
|
|
779
|
+
labels: issueLabelNames(enriched),
|
|
780
|
+
comments: threadCommentsFromIssue(enriched),
|
|
781
|
+
});
|
|
722
782
|
const emissionLayout = resolveIngestEmissionLayout(options.vbriefDir);
|
|
723
783
|
const [vbrief, folder] = buildIssueVbrief(enriched, options.status, options.repoUrl, {
|
|
724
784
|
infoRootKey: emissionLayout.infoRootKey,
|
|
@@ -774,6 +834,7 @@ export function ingestBulk(issues, options) {
|
|
|
774
834
|
duplicate: [],
|
|
775
835
|
dryrun: [],
|
|
776
836
|
failed: [],
|
|
837
|
+
blocked: [],
|
|
777
838
|
notices: [],
|
|
778
839
|
};
|
|
779
840
|
for (const issue of filtered) {
|
|
@@ -790,6 +851,11 @@ export function ingestBulk(issues, options) {
|
|
|
790
851
|
process.stderr.write(`${exc.message}\n`);
|
|
791
852
|
continue;
|
|
792
853
|
}
|
|
854
|
+
if (exc instanceof DesignCritiqueIngestBlockedError) {
|
|
855
|
+
summary.blocked.push(`#${exc.issueNumber}`);
|
|
856
|
+
process.stderr.write(`${exc.message}\n`);
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
793
859
|
throw exc;
|
|
794
860
|
}
|
|
795
861
|
const [result, path, msg] = ingested;
|
|
@@ -861,7 +927,8 @@ export function issueIngestMain(args) {
|
|
|
861
927
|
const duplicate = summary.duplicate;
|
|
862
928
|
const dryrun = summary.dryrun;
|
|
863
929
|
const failed = summary.failed ?? [];
|
|
864
|
-
|
|
930
|
+
const blocked = summary.blocked ?? [];
|
|
931
|
+
process.stdout.write(`issue:ingest bulk summary: ${created.length} created, ${duplicate.length} duplicate, ${dryrun.length} dry-run, ${failed.length} refused, ${blocked.length} blocked (total considered: ${summary.total})\n`);
|
|
865
932
|
for (const entry of created) {
|
|
866
933
|
process.stdout.write(` CREATED ${entry}\n`);
|
|
867
934
|
}
|
|
@@ -877,8 +944,16 @@ export function issueIngestMain(args) {
|
|
|
877
944
|
for (const entry of failed) {
|
|
878
945
|
process.stdout.write(` REFUSED ${entry} (quarantine scanner hard-fail; nothing written)\n`);
|
|
879
946
|
}
|
|
947
|
+
for (const entry of blocked) {
|
|
948
|
+
process.stdout.write(` BLOCKED ${entry} (design-critique completed-arc record; nothing written)\n`);
|
|
949
|
+
}
|
|
880
950
|
// #2306: fail closed on any quarantine hard-fail in the batch.
|
|
881
|
-
|
|
951
|
+
// Design-critique protocol holds are exit 1, not the scanner fatal path.
|
|
952
|
+
if (failed.length > 0)
|
|
953
|
+
return 2;
|
|
954
|
+
if (blocked.length > 0)
|
|
955
|
+
return 1;
|
|
956
|
+
return 0;
|
|
882
957
|
}
|
|
883
958
|
const issue = fetchIssue(repo, args.number, { cwd: projectRoot });
|
|
884
959
|
if (issue === null) {
|
|
@@ -901,6 +976,10 @@ export function issueIngestMain(args) {
|
|
|
901
976
|
process.stderr.write(`${exc.message}\n`);
|
|
902
977
|
return 2;
|
|
903
978
|
}
|
|
979
|
+
if (exc instanceof DesignCritiqueIngestBlockedError) {
|
|
980
|
+
process.stderr.write(`${exc.message}\n`);
|
|
981
|
+
return 1;
|
|
982
|
+
}
|
|
904
983
|
throw exc;
|
|
905
984
|
}
|
|
906
985
|
process.stdout.write(`${msg}\n`);
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/** Minimal runtime capability probe for github_auth_modes (#1557a / #1784). */
|
|
2
|
+
import { type ManagedRuntimeProbe } from "../platform/cursor-managed-runtime.js";
|
|
2
3
|
export declare const RUNTIME_MODE_LOCAL_UNSANDBOXED = "local-unsandboxed";
|
|
3
4
|
export declare const RUNTIME_MODE_CURSOR_NATIVE_SANDBOX = "cursor-native-sandbox";
|
|
4
5
|
export declare const RUNTIME_MODE_CLOUD_HEADLESS = "cloud-headless";
|
|
5
6
|
export declare const KNOWN_RUNTIME_MODES: Set<string>;
|
|
6
7
|
export interface RuntimeCapabilityReport {
|
|
7
8
|
readonly runtimeMode: string;
|
|
9
|
+
/** Stable id naming why `runtimeMode` was chosen; surfaced by scm:status (#3859). */
|
|
10
|
+
readonly runtimeModeReason?: string;
|
|
8
11
|
}
|
|
9
|
-
export
|
|
10
|
-
|
|
12
|
+
export interface ProbeRuntimeCapabilityOptions {
|
|
13
|
+
/** Injectable managed-runtime probe (#3859). Defaults to the metadata read. */
|
|
14
|
+
readonly managedRuntimeProbe?: ManagedRuntimeProbe;
|
|
15
|
+
}
|
|
16
|
+
export declare function probeRuntimeCapabilities(environ?: NodeJS.ProcessEnv, options?: ProbeRuntimeCapabilityOptions): RuntimeCapabilityReport;
|
|
17
|
+
export declare function getPlatformCapabilities(options?: ProbeRuntimeCapabilityOptions): RuntimeCapabilityReport;
|
|
11
18
|
//# sourceMappingURL=platform-capabilities.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Minimal runtime capability probe for github_auth_modes (#1557a / #1784). */
|
|
2
|
+
import { hasExplicitHostGhSelection, probeManagedRuntime, RUNTIME_REASON_CI_MARKER, RUNTIME_REASON_CURSOR_MARKER_AMBIGUOUS, RUNTIME_REASON_CURSOR_SANDBOX_MARKER, RUNTIME_REASON_EXPLICIT_HOST_GH, RUNTIME_REASON_MANAGED_RUNTIME_PROBE, RUNTIME_REASON_NO_RUNTIME_MARKER, } from "../platform/cursor-managed-runtime.js";
|
|
2
3
|
export const RUNTIME_MODE_LOCAL_UNSANDBOXED = "local-unsandboxed";
|
|
3
4
|
export const RUNTIME_MODE_CURSOR_NATIVE_SANDBOX = "cursor-native-sandbox";
|
|
4
5
|
export const RUNTIME_MODE_CLOUD_HEADLESS = "cloud-headless";
|
|
@@ -11,24 +12,52 @@ const TRUTHY = new Set(["1", "true", "yes", "on"]);
|
|
|
11
12
|
function isTruthy(value) {
|
|
12
13
|
return value !== undefined && TRUTHY.has(value.trim().toLowerCase());
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Classify the execution runtime.
|
|
17
|
+
*
|
|
18
|
+
* Ordering is load-bearing (#3859):
|
|
19
|
+
* 1. CI markers, so a CI runner is never reclassified by a Cursor signal.
|
|
20
|
+
* 2. A positive Cursor managed-runtime read, above every other Cursor signal.
|
|
21
|
+
* 3. Cursor native sandbox.
|
|
22
|
+
* 4. A Cursor marker with no managed read leaves the runtime AMBIGUOUS. Only
|
|
23
|
+
* an explicit operator/dispatcher selection resolves it to local; absent
|
|
24
|
+
* that, the verdict is unchanged from before #3859.
|
|
25
|
+
*/
|
|
26
|
+
function classifyRuntimeMode(environ = process.env, options = {}) {
|
|
15
27
|
for (const key of ["GROK_BUILD", "GITHUB_ACTIONS", "CI", "BUILDKITE", "DEFT_AGENT_RUNTIME"]) {
|
|
16
28
|
if (isTruthy(environ[key])) {
|
|
17
|
-
return RUNTIME_MODE_CLOUD_HEADLESS;
|
|
29
|
+
return { mode: RUNTIME_MODE_CLOUD_HEADLESS, reason: RUNTIME_REASON_CI_MARKER };
|
|
18
30
|
}
|
|
19
31
|
}
|
|
32
|
+
const managedProbe = options.managedRuntimeProbe ?? probeManagedRuntime;
|
|
33
|
+
if (managedProbe(environ).verdict === "managed") {
|
|
34
|
+
return {
|
|
35
|
+
mode: RUNTIME_MODE_CLOUD_HEADLESS,
|
|
36
|
+
reason: RUNTIME_REASON_MANAGED_RUNTIME_PROBE,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
20
39
|
if (isTruthy(environ.CURSOR_SANDBOX) || isTruthy(environ.CURSOR_SANDBOX_LANDLOCK_STATUS)) {
|
|
21
|
-
return
|
|
40
|
+
return {
|
|
41
|
+
mode: RUNTIME_MODE_CURSOR_NATIVE_SANDBOX,
|
|
42
|
+
reason: RUNTIME_REASON_CURSOR_SANDBOX_MARKER,
|
|
43
|
+
};
|
|
22
44
|
}
|
|
23
45
|
if (isTruthy(environ.CURSOR_AGENT) || isTruthy(environ.CURSOR_COMPOSER)) {
|
|
24
|
-
|
|
46
|
+
if (hasExplicitHostGhSelection(environ)) {
|
|
47
|
+
return { mode: RUNTIME_MODE_LOCAL_UNSANDBOXED, reason: RUNTIME_REASON_EXPLICIT_HOST_GH };
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
mode: RUNTIME_MODE_CLOUD_HEADLESS,
|
|
51
|
+
reason: RUNTIME_REASON_CURSOR_MARKER_AMBIGUOUS,
|
|
52
|
+
};
|
|
25
53
|
}
|
|
26
|
-
return RUNTIME_MODE_LOCAL_UNSANDBOXED;
|
|
54
|
+
return { mode: RUNTIME_MODE_LOCAL_UNSANDBOXED, reason: RUNTIME_REASON_NO_RUNTIME_MARKER };
|
|
27
55
|
}
|
|
28
|
-
export function probeRuntimeCapabilities(environ = process.env) {
|
|
29
|
-
|
|
56
|
+
export function probeRuntimeCapabilities(environ = process.env, options = {}) {
|
|
57
|
+
const { mode, reason } = classifyRuntimeMode(environ, options);
|
|
58
|
+
return { runtimeMode: mode, runtimeModeReason: reason };
|
|
30
59
|
}
|
|
31
|
-
export function getPlatformCapabilities() {
|
|
32
|
-
return probeRuntimeCapabilities();
|
|
60
|
+
export function getPlatformCapabilities(options = {}) {
|
|
61
|
+
return probeRuntimeCapabilities(process.env, options);
|
|
33
62
|
}
|
|
34
63
|
//# sourceMappingURL=platform-capabilities.js.map
|
|
@@ -3,12 +3,12 @@ import { mkdirSync, readdirSync, readFileSync, renameSync, statSync, writeFileSy
|
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { assertProjectionContained, assertWriteTargetSafe, ProjectionContainmentError, } from "../fs/projection-containment.js";
|
|
5
5
|
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
6
|
+
import { missingEnvelopeMessage, stampExistingEnvelopes } from "../lifecycle/brief-envelope.js";
|
|
6
7
|
import { call } from "../scm/call.js";
|
|
7
8
|
import { updateDecomposedChildBackReferences } from "../scope/decomposed-refs.js";
|
|
8
9
|
import { resolveProjectRoot } from "../scope/project-context.js";
|
|
9
10
|
import { resolveProjectRepo } from "../slice/project-context.js";
|
|
10
11
|
import { FOLDER_ALLOWED_STATUSES } from "../vbrief-validate/constants.js";
|
|
11
|
-
import { LEGACY_INFO_ROOT_KEY, MIGRATED_INFO_ROOT_KEY } from "../xbrief-migrate/constants.js";
|
|
12
12
|
export const LIFECYCLE_FOLDERS = [
|
|
13
13
|
"proposed",
|
|
14
14
|
"pending",
|
|
@@ -713,14 +713,13 @@ export function applyLifecycleFixes(vbriefDir, report, projectRoot = null) {
|
|
|
713
713
|
plan.status = terminalStatus;
|
|
714
714
|
const stamp = utcNowIso();
|
|
715
715
|
// Stamp `updated` into whichever info envelope the file already uses (#2346).
|
|
716
|
-
//
|
|
717
|
-
//
|
|
718
|
-
//
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
info.updated = stamp;
|
|
716
|
+
// A file carrying neither envelope is already invalid; creating one here hid
|
|
717
|
+
// that cause behind a manufactured version-less `vBRIEFInfo` (#3933), so the
|
|
718
|
+
// sweep now refuses it by name and leaves the artifact in place.
|
|
719
|
+
if (stampExistingEnvelopes(data, stamp).length === 0) {
|
|
720
|
+
failures.push(missingEnvelopeMessage(relPath));
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
724
723
|
plan.updated = stamp;
|
|
725
724
|
propagateItemStatus(plan.items, terminalStatus, stamp);
|
|
726
725
|
try {
|
|
@@ -780,12 +779,13 @@ export function repairCompletedStatusDrift(vbriefDir, drift, projectRoot = null)
|
|
|
780
779
|
continue;
|
|
781
780
|
}
|
|
782
781
|
const stamp = utcNowIso();
|
|
782
|
+
// Same envelope policy as the closed-issue sweep above (#3933).
|
|
783
|
+
if (stampExistingEnvelopes(data, stamp).length === 0) {
|
|
784
|
+
failures.push(missingEnvelopeMessage(entry.rel_path));
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
783
787
|
plan.status = "completed";
|
|
784
788
|
plan.updated = stamp;
|
|
785
|
-
const infoKey = MIGRATED_INFO_ROOT_KEY in data ? MIGRATED_INFO_ROOT_KEY : LEGACY_INFO_ROOT_KEY;
|
|
786
|
-
const info = (data[infoKey] ?? {});
|
|
787
|
-
data[infoKey] = info;
|
|
788
|
-
info.updated = stamp;
|
|
789
789
|
propagateItemStatus(plan.items, "completed", stamp);
|
|
790
790
|
try {
|
|
791
791
|
writeFileSync(src, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared document-envelope policy for lifecycle mutators (#3933).
|
|
3
|
+
*
|
|
4
|
+
* A brief carries one document envelope: `xBRIEFInfo` on canonical v0.8
|
|
5
|
+
* artifacts, `vBRIEFInfo` on legacy v0.6 ones. A mutator stamps whichever
|
|
6
|
+
* envelope the artifact already has and creates none. Creating one on a v0.8
|
|
7
|
+
* brief appends a version-less `vBRIEFInfo`, and `validateVbriefSchema`
|
|
8
|
+
* resolves `vBRIEFInfo` first, so the manufactured block wins and the brief the
|
|
9
|
+
* mutator just wrote fails validation (#2346 / #2862 / #3933).
|
|
10
|
+
*/
|
|
11
|
+
import { LEGACY_INFO_ROOT_KEY, MIGRATED_INFO_ROOT_KEY } from "../xbrief-migrate/constants.js";
|
|
12
|
+
export type BriefEnvelopeKey = typeof MIGRATED_INFO_ROOT_KEY | typeof LEGACY_INFO_ROOT_KEY;
|
|
13
|
+
/** Envelope keys in canonical order: v0.8 first, legacy v0.6 second. */
|
|
14
|
+
export declare const BRIEF_ENVELOPE_KEYS: readonly BriefEnvelopeKey[];
|
|
15
|
+
/** Envelope keys the artifact already carries as JSON objects. */
|
|
16
|
+
export declare function presentEnvelopeKeys(data: Record<string, unknown>): BriefEnvelopeKey[];
|
|
17
|
+
/**
|
|
18
|
+
* Stamp `updated` on every envelope the artifact already carries; create none.
|
|
19
|
+
* Returns the stamped keys so a caller can refuse an envelope-less artifact by
|
|
20
|
+
* name instead of manufacturing one.
|
|
21
|
+
*/
|
|
22
|
+
export declare function stampExistingEnvelopes(data: Record<string, unknown>, nowIso: string): BriefEnvelopeKey[];
|
|
23
|
+
/** Refusal naming both accepted envelopes, for a caller-supplied subject (#3933). */
|
|
24
|
+
export declare function missingEnvelopeMessage(subject: string): string;
|
|
25
|
+
//# sourceMappingURL=brief-envelope.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared document-envelope policy for lifecycle mutators (#3933).
|
|
3
|
+
*
|
|
4
|
+
* A brief carries one document envelope: `xBRIEFInfo` on canonical v0.8
|
|
5
|
+
* artifacts, `vBRIEFInfo` on legacy v0.6 ones. A mutator stamps whichever
|
|
6
|
+
* envelope the artifact already has and creates none. Creating one on a v0.8
|
|
7
|
+
* brief appends a version-less `vBRIEFInfo`, and `validateVbriefSchema`
|
|
8
|
+
* resolves `vBRIEFInfo` first, so the manufactured block wins and the brief the
|
|
9
|
+
* mutator just wrote fails validation (#2346 / #2862 / #3933).
|
|
10
|
+
*/
|
|
11
|
+
import { LEGACY_INFO_ROOT_KEY, MIGRATED_INFO_ROOT_KEY } from "../xbrief-migrate/constants.js";
|
|
12
|
+
/** Envelope keys in canonical order: v0.8 first, legacy v0.6 second. */
|
|
13
|
+
export const BRIEF_ENVELOPE_KEYS = [
|
|
14
|
+
MIGRATED_INFO_ROOT_KEY,
|
|
15
|
+
LEGACY_INFO_ROOT_KEY,
|
|
16
|
+
];
|
|
17
|
+
/** Envelope keys the artifact already carries as JSON objects. */
|
|
18
|
+
export function presentEnvelopeKeys(data) {
|
|
19
|
+
return BRIEF_ENVELOPE_KEYS.filter((key) => {
|
|
20
|
+
const env = data[key];
|
|
21
|
+
return typeof env === "object" && env !== null && !Array.isArray(env);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Stamp `updated` on every envelope the artifact already carries; create none.
|
|
26
|
+
* Returns the stamped keys so a caller can refuse an envelope-less artifact by
|
|
27
|
+
* name instead of manufacturing one.
|
|
28
|
+
*/
|
|
29
|
+
export function stampExistingEnvelopes(data, nowIso) {
|
|
30
|
+
const stamped = presentEnvelopeKeys(data);
|
|
31
|
+
for (const key of stamped) {
|
|
32
|
+
data[key].updated = nowIso;
|
|
33
|
+
}
|
|
34
|
+
return stamped;
|
|
35
|
+
}
|
|
36
|
+
/** Refusal naming both accepted envelopes, for a caller-supplied subject (#3933). */
|
|
37
|
+
export function missingEnvelopeMessage(subject) {
|
|
38
|
+
return (`${subject} carries neither \`${MIGRATED_INFO_ROOT_KEY}\` (v0.8) nor ` +
|
|
39
|
+
`\`${LEGACY_INFO_ROOT_KEY}\` (v0.6) -- malformed. Lifecycle mutators refuse ` +
|
|
40
|
+
"rather than create one (#3933).");
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=brief-envelope.js.map
|
package/dist/lifecycle/index.js
CHANGED
|
@@ -189,16 +189,25 @@ export function evaluateLiteralAcceptanceFromPlan(plan, options = {}) {
|
|
|
189
189
|
// Rejected stated commands are fail-closed for completion (#3267 Greptile conf residual).
|
|
190
190
|
// A safety-rejected shell-shaped acceptance line is not "optional diagnostic" — operators
|
|
191
191
|
// must promote a safe alternative or remove the stated command from the task statement.
|
|
192
|
+
const mergedRejected = [];
|
|
193
|
+
const seenRejected = new Set();
|
|
194
|
+
for (const row of [...(result.rejected ?? []), ...resolved.rejected]) {
|
|
195
|
+
const key = `${row.command}\0${row.reason}`;
|
|
196
|
+
if (seenRejected.has(key))
|
|
197
|
+
continue;
|
|
198
|
+
seenRejected.add(key);
|
|
199
|
+
mergedRejected.push(row);
|
|
200
|
+
}
|
|
192
201
|
let ok = result.ok;
|
|
193
202
|
let code = result.code;
|
|
194
|
-
let message = appendRejectedNote(result.message,
|
|
195
|
-
if (
|
|
203
|
+
let message = appendRejectedNote(result.message, mergedRejected);
|
|
204
|
+
if (mergedRejected.length > 0) {
|
|
196
205
|
ok = false;
|
|
197
206
|
if (code === 0)
|
|
198
207
|
code = 1;
|
|
199
|
-
const ledger = formatRejectedLedger(
|
|
208
|
+
const ledger = formatRejectedLedger(mergedRejected);
|
|
200
209
|
message =
|
|
201
|
-
`Literal acceptance-command gate FAILED (#3267): ${
|
|
210
|
+
`Literal acceptance-command gate FAILED (#3267): ${mergedRejected.length} ` +
|
|
202
211
|
`safety-rejected stated command(s) block completion until resolved ` +
|
|
203
212
|
`(promote a safe alternative or remove from the task statement).\n` +
|
|
204
213
|
ledger +
|
|
@@ -212,7 +221,7 @@ export function evaluateLiteralAcceptanceFromPlan(plan, options = {}) {
|
|
|
212
221
|
...result,
|
|
213
222
|
ok,
|
|
214
223
|
code,
|
|
215
|
-
rejected:
|
|
224
|
+
rejected: mergedRejected,
|
|
216
225
|
advisoryRejected: resolved.advisoryRejected,
|
|
217
226
|
transcriptPromptSkipped: resolved.transcriptPromptSkipped,
|
|
218
227
|
message,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { attachLiteralAcceptanceCommands, type CaptureLiteralAcceptanceResult, captureAndAttachLiteralAcceptance, captureLiteralAcceptanceCommands, captureLiteralAcceptanceCommandsDetailed, formatRejectedLedger, hasStructuredAcceptanceCommands, INLINE_PROSE_MENTION_REASON, isInlineProseMention, isProseDerivedRejection, readNotAcceptanceCommands, readStoredLiteralAcceptanceCommands, readStoredLiteralAcceptanceDetailed, } from "./capture.js";
|
|
8
8
|
export { appendLiteralAcceptanceAdvisory, type EvaluateLiteralAcceptanceOptions, evaluateLiteralAcceptanceFromPath, evaluateLiteralAcceptanceFromPlan, formatLiteralAcceptanceAdvisory, isLiteralAcceptanceRequiredAtCeremonyDepth, LITERAL_ACCEPTANCE_ADVISORY_MARKER, type ResolvedLiteralAcceptance, resolveLiteralAcceptanceCommands, resolveLiteralAcceptanceDetailed, stripLiteralAcceptanceAdvisory, } from "./evaluate.js";
|
|
9
|
-
export { defaultLiteralAcceptanceRunner, runLiteralAcceptanceCommand, runLiteralAcceptanceCommands, } from "./run.js";
|
|
9
|
+
export { defaultLiteralAcceptanceRunner, isSafetyRefusalRun, runLiteralAcceptanceCommand, runLiteralAcceptanceCommands, } from "./run.js";
|
|
10
10
|
export { type CommandSafetyResult, evaluateCommandSafety, evaluateNoopDenylist, evaluateStampAcceptanceSafety, isExecutableLiteralSource, isNoopRefusalReason, isVerbatimStatementSpan, NOOP_ACCEPTANCE_REMEDIATION, REJECTED_NOOP_OUTCOME, type RejectedNoopOutcome, type StampAcceptanceCommand, type StampAcceptanceSafetyInput, type StampAcceptanceSafetyResult, type StampSourceRung, } from "./safety.js";
|
|
11
11
|
export { EXECUTABLE_LITERAL_SOURCES, LITERAL_ACCEPTANCE_METADATA_KEY, LITERAL_ACCEPTANCE_METADATA_KEY_CAMEL, LITERAL_ACCEPTANCE_NOT_COMMANDS_METADATA_KEY, LITERAL_ACCEPTANCE_REJECTED_METADATA_KEY, type LiteralAcceptanceCommand, type LiteralAcceptanceGateResult, type LiteralAcceptanceRunner, type LiteralAcceptanceRunResult, type LiteralAcceptanceSource, type RejectedLiteralCommand, } from "./types.js";
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { attachLiteralAcceptanceCommands, captureAndAttachLiteralAcceptance, captureLiteralAcceptanceCommands, captureLiteralAcceptanceCommandsDetailed, formatRejectedLedger, hasStructuredAcceptanceCommands, INLINE_PROSE_MENTION_REASON, isInlineProseMention, isProseDerivedRejection, readNotAcceptanceCommands, readStoredLiteralAcceptanceCommands, readStoredLiteralAcceptanceDetailed, } from "./capture.js";
|
|
8
8
|
export { appendLiteralAcceptanceAdvisory, evaluateLiteralAcceptanceFromPath, evaluateLiteralAcceptanceFromPlan, formatLiteralAcceptanceAdvisory, isLiteralAcceptanceRequiredAtCeremonyDepth, LITERAL_ACCEPTANCE_ADVISORY_MARKER, resolveLiteralAcceptanceCommands, resolveLiteralAcceptanceDetailed, stripLiteralAcceptanceAdvisory, } from "./evaluate.js";
|
|
9
|
-
export { defaultLiteralAcceptanceRunner, runLiteralAcceptanceCommand, runLiteralAcceptanceCommands, } from "./run.js";
|
|
9
|
+
export { defaultLiteralAcceptanceRunner, isSafetyRefusalRun, runLiteralAcceptanceCommand, runLiteralAcceptanceCommands, } from "./run.js";
|
|
10
10
|
export { evaluateCommandSafety, evaluateNoopDenylist, evaluateStampAcceptanceSafety, isExecutableLiteralSource, isNoopRefusalReason, isVerbatimStatementSpan, NOOP_ACCEPTANCE_REMEDIATION, REJECTED_NOOP_OUTCOME, } from "./safety.js";
|
|
11
11
|
export { EXECUTABLE_LITERAL_SOURCES, LITERAL_ACCEPTANCE_METADATA_KEY, LITERAL_ACCEPTANCE_METADATA_KEY_CAMEL, LITERAL_ACCEPTANCE_NOT_COMMANDS_METADATA_KEY, LITERAL_ACCEPTANCE_REJECTED_METADATA_KEY, } from "./types.js";
|
|
12
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Self-chosen verification is supplementary — this gate only runs stored literals.
|
|
7
7
|
*/
|
|
8
8
|
import type { LiteralAcceptanceCommand, LiteralAcceptanceGateResult, LiteralAcceptanceRunner, LiteralAcceptanceRunResult } from "./types.js";
|
|
9
|
+
/** True when the row is a pre-execution safety refusal, not a product measurement (#3615). */
|
|
10
|
+
export declare function isSafetyRefusalRun(run: Pick<LiteralAcceptanceRunResult, "exitCode" | "detail">): boolean;
|
|
9
11
|
/** Default shell runner: exact command string via platform shell. */
|
|
10
12
|
export declare function defaultLiteralAcceptanceRunner(input: {
|
|
11
13
|
readonly command: string;
|
|
@@ -9,6 +9,13 @@ import { spawnSync } from "node:child_process";
|
|
|
9
9
|
import { isAbsolute, resolve } from "node:path";
|
|
10
10
|
import { isInlineProseMention } from "./capture.js";
|
|
11
11
|
import { evaluateCommandSafety, isExecutableLiteralSource } from "./safety.js";
|
|
12
|
+
/** True when the row is a pre-execution safety refusal, not a product measurement (#3615). */
|
|
13
|
+
export function isSafetyRefusalRun(run) {
|
|
14
|
+
return run.exitCode === 2 && /^refused:\s*/i.test(run.detail);
|
|
15
|
+
}
|
|
16
|
+
function safetyRefusalReason(run) {
|
|
17
|
+
return run.detail.replace(/^refused:\s*/i, "").trim();
|
|
18
|
+
}
|
|
12
19
|
/** Default shell runner: exact command string via platform shell. */
|
|
13
20
|
export function defaultLiteralAcceptanceRunner(input) {
|
|
14
21
|
// Windows: cmd.exe /c; POSIX: shell true uses sh -c. Exact string preserved.
|
|
@@ -173,6 +180,7 @@ export function runLiteralAcceptanceCommands(commands, options) {
|
|
|
173
180
|
};
|
|
174
181
|
}
|
|
175
182
|
const runs = [];
|
|
183
|
+
const rejected = [];
|
|
176
184
|
for (const cmd of executable) {
|
|
177
185
|
if (typeof cmd.command !== "string" || cmd.command.trim().length === 0) {
|
|
178
186
|
return {
|
|
@@ -181,9 +189,18 @@ export function runLiteralAcceptanceCommands(commands, options) {
|
|
|
181
189
|
message: "Literal acceptance-command gate config error: empty command entry (#3267)",
|
|
182
190
|
commands,
|
|
183
191
|
runs,
|
|
192
|
+
rejected: rejected.length > 0 ? rejected : undefined,
|
|
184
193
|
};
|
|
185
194
|
}
|
|
186
|
-
|
|
195
|
+
const run = runLiteralAcceptanceCommand(cmd, options);
|
|
196
|
+
runs.push(run);
|
|
197
|
+
if (isSafetyRefusalRun(run)) {
|
|
198
|
+
rejected.push({
|
|
199
|
+
command: run.command,
|
|
200
|
+
reason: safetyRefusalReason(run),
|
|
201
|
+
sourceSpan: cmd.sourceSpan ?? null,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
187
204
|
}
|
|
188
205
|
const failed = runs.filter((r) => !r.ok);
|
|
189
206
|
if (failed.length === 0) {
|
|
@@ -213,6 +230,7 @@ export function runLiteralAcceptanceCommands(commands, options) {
|
|
|
213
230
|
lines.join("\n"),
|
|
214
231
|
commands,
|
|
215
232
|
runs,
|
|
233
|
+
rejected: rejected.length > 0 ? rejected : undefined,
|
|
216
234
|
};
|
|
217
235
|
}
|
|
218
236
|
function truncate(s, max) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Candidate diff ownership for the merge-chokepoint orphan run (#3893).
|
|
3
|
+
*
|
|
4
|
+
* The unscoped sweep enumerates every running brief under `active/`. Composed
|
|
5
|
+
* on `check:merge` that gives one stranded brief merge authority over every
|
|
6
|
+
* open PR, and N stranded briefs make N single-brief lifecycle PRs mutually
|
|
7
|
+
* unmergeable — each leaves the other orphan. The pre-merge run cannot see the
|
|
8
|
+
* residue its own candidate is about to create either: that candidate's linked
|
|
9
|
+
* PR still reads `merged_at: null` while the gate runs.
|
|
10
|
+
*
|
|
11
|
+
* Scoping the merge run to the candidate's own diff removes the coupling
|
|
12
|
+
* without touching the detector. Repo-wide truth stays enforced at the
|
|
13
|
+
* delivery tip (HEAD on the delivery line falls back to the full sweep) and
|
|
14
|
+
* after merge (`--issue N`, #3429).
|
|
15
|
+
*/
|
|
16
|
+
import { type GitRunner } from "../session/git.js";
|
|
17
|
+
export type CandidateScope = {
|
|
18
|
+
readonly kind: "diff";
|
|
19
|
+
/** Ref the candidate was diffed against (e.g. `origin/master`). */
|
|
20
|
+
readonly baseRef: string;
|
|
21
|
+
/** Absolute, platform-normalized brief paths this candidate owns. */
|
|
22
|
+
readonly paths: ReadonlySet<string>;
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: "sweep";
|
|
25
|
+
/** Why this run stayed repo-wide; always printed with the verdict. */
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
};
|
|
28
|
+
export interface CandidateScopeOptions {
|
|
29
|
+
/** Explicit base ref; defaults to `origin/<deliveryBranch>` then the branch. */
|
|
30
|
+
readonly baseRef?: string | null;
|
|
31
|
+
readonly runGit?: GitRunner;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One comparable form for a git path and a readdir path.
|
|
35
|
+
*
|
|
36
|
+
* Only the directory is canonicalized: the file itself may be a deletion in
|
|
37
|
+
* the candidate diff and no longer exist on disk.
|
|
38
|
+
*/
|
|
39
|
+
export declare function normalizeScopePath(path: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Base ref for the candidate diff: explicit override, else `origin/<branch>`,
|
|
42
|
+
* else the local delivery branch. Null when none resolves.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveCandidateBaseRef(projectRoot: string, override: string | null | undefined, runGit: GitRunner): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Brief paths under `activeDir` that the candidate's own diff touches.
|
|
47
|
+
*
|
|
48
|
+
* Falls back to the repo-wide sweep — never to a narrower scan — when git,
|
|
49
|
+
* the base ref, or the diff is unavailable, so the flag cannot silently
|
|
50
|
+
* shrink what a merge gate looks at.
|
|
51
|
+
*/
|
|
52
|
+
export declare function resolveCandidateScope(projectRoot: string, activeDir: string, options?: CandidateScopeOptions): CandidateScope;
|
|
53
|
+
//# sourceMappingURL=candidate-scope.d.ts.map
|