dorfl 0.1.1 → 0.1.2
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/advance-ci-template.d.ts +3 -3
- package/dist/advance-ci-template.js +1 -1
- package/dist/advance-ci-template.js.map +1 -1
- package/dist/advance-classify.d.ts +5 -5
- package/dist/advance-classify.d.ts.map +1 -1
- package/dist/advance-classify.js +4 -4
- package/dist/advance-drivers.d.ts +7 -7
- package/dist/advance-drivers.d.ts.map +1 -1
- package/dist/advance-drivers.js +5 -5
- package/dist/advance-drivers.js.map +1 -1
- package/dist/advance-isolated.d.ts +3 -3
- package/dist/advance-isolated.d.ts.map +1 -1
- package/dist/advance-isolated.js +1 -1
- package/dist/advance-lifecycle-template.d.ts +2 -2
- package/dist/advance-lifecycle-template.js +9 -9
- package/dist/advance-lifecycle-template.js.map +1 -1
- package/dist/advance-loop-driver.d.ts +3 -3
- package/dist/advance-loop-driver.d.ts.map +1 -1
- package/dist/advance-loop-driver.js +1 -1
- package/dist/advance-treeless-publish.d.ts +1 -1
- package/dist/advance.d.ts +11 -11
- package/dist/advance.d.ts.map +1 -1
- package/dist/advance.js +21 -21
- package/dist/advance.js.map +1 -1
- package/dist/advancing-lock.d.ts +1 -1
- package/dist/advancing-lock.js +5 -5
- package/dist/apply-decide.d.ts +2 -2
- package/dist/apply-decide.js +2 -2
- package/dist/apply-merge-action.d.ts +4 -4
- package/dist/apply-merge-action.js +2 -2
- package/dist/apply-persist.d.ts +5 -5
- package/dist/apply-persist.d.ts.map +1 -1
- package/dist/apply-persist.js +7 -7
- package/dist/apply-persist.js.map +1 -1
- package/dist/buildable-body.d.ts +14 -14
- package/dist/buildable-body.js +9 -9
- package/dist/claim-cas.d.ts +3 -3
- package/dist/claim-cas.js +1 -1
- package/dist/claim-cas.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +76 -76
- package/dist/cli.js.map +1 -1
- package/dist/close-job-template.d.ts +3 -3
- package/dist/close-job-template.js +8 -8
- package/dist/close-job.d.ts +8 -8
- package/dist/close-job.js +25 -25
- package/dist/close-job.js.map +1 -1
- package/dist/complete.d.ts +3 -3
- package/dist/complete.js +8 -8
- package/dist/complete.js.map +1 -1
- package/dist/concurrency.d.ts +1 -1
- package/dist/concurrency.js +1 -1
- package/dist/config.d.ts +32 -32
- package/dist/config.js +5 -5
- package/dist/config.js.map +1 -1
- package/dist/continue-branch.d.ts +1 -1
- package/dist/continue-branch.js +1 -1
- package/dist/cwd-section.js +1 -1
- package/dist/cwd-section.js.map +1 -1
- package/dist/decision-engine.d.ts +2 -2
- package/dist/do-autopick.d.ts +6 -6
- package/dist/do-autopick.d.ts.map +1 -1
- package/dist/do-autopick.js +5 -5
- package/dist/do-autopick.js.map +1 -1
- package/dist/do-config.d.ts +3 -3
- package/dist/do-config.js +3 -3
- package/dist/do-config.js.map +1 -1
- package/dist/do-remote-auto.d.ts +2 -2
- package/dist/do-remote-auto.js +1 -1
- package/dist/do.d.ts +25 -25
- package/dist/do.d.ts.map +1 -1
- package/dist/do.js +20 -20
- package/dist/do.js.map +1 -1
- package/dist/drop-source.d.ts +2 -2
- package/dist/env-config.js +8 -8
- package/dist/env-config.js.map +1 -1
- package/dist/format.js +3 -3
- package/dist/format.js.map +1 -1
- package/dist/frontmatter.d.ts +14 -13
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +12 -24
- package/dist/frontmatter.js.map +1 -1
- package/dist/install-ci-branch-protection.d.ts +1 -1
- package/dist/install-ci-branch-protection.js +1 -1
- package/dist/install-ci-capabilities/advance-lifecycle.d.ts +1 -1
- package/dist/install-ci-capabilities/advance-lifecycle.js +1 -1
- package/dist/install-ci-capabilities/close-job.d.ts +1 -1
- package/dist/install-ci-capabilities/close-job.js +1 -1
- package/dist/install-ci-capabilities/example-noop.d.ts +1 -1
- package/dist/install-ci-capabilities/example-noop.js +1 -1
- package/dist/install-ci-capabilities/intake.d.ts +2 -2
- package/dist/install-ci-capabilities/intake.js +2 -2
- package/dist/install-ci-capabilities/verify.d.ts +1 -1
- package/dist/install-ci-capabilities/verify.js +1 -1
- package/dist/install-ci-core.d.ts +3 -3
- package/dist/install-ci-core.js +2 -2
- package/dist/install-ci-core.js.map +1 -1
- package/dist/install-ci-github.d.ts +1 -1
- package/dist/install-ci-github.js +1 -1
- package/dist/install-ci.d.ts +1 -1
- package/dist/install-ci.js +4 -4
- package/dist/install-ci.js.map +1 -1
- package/dist/intake-event.d.ts +6 -6
- package/dist/intake-event.js +6 -6
- package/dist/intake-marker.d.ts +3 -3
- package/dist/intake-marker.d.ts.map +1 -1
- package/dist/intake-triage.d.ts +1 -1
- package/dist/intake-triage.js +2 -2
- package/dist/intake-trigger-template.d.ts +8 -8
- package/dist/intake-trigger-template.d.ts.map +1 -1
- package/dist/intake-trigger-template.js +16 -16
- package/dist/intake-trigger-template.js.map +1 -1
- package/dist/intake.d.ts +50 -50
- package/dist/intake.d.ts.map +1 -1
- package/dist/intake.js +70 -70
- package/dist/intake.js.map +1 -1
- package/dist/integration-core.d.ts +17 -17
- package/dist/integration-core.js +17 -17
- package/dist/integration-core.js.map +1 -1
- package/dist/isolation.d.ts +3 -3
- package/dist/issue-provider.d.ts +4 -4
- package/dist/issue-provider.js +1 -1
- package/dist/item-lock.d.ts +21 -21
- package/dist/item-lock.d.ts.map +1 -1
- package/dist/item-lock.js +16 -16
- package/dist/item-path.d.ts +2 -2
- package/dist/item-path.js +2 -2
- package/dist/ledger-lint.d.ts +9 -9
- package/dist/ledger-lint.js +9 -9
- package/dist/ledger-read.d.ts +57 -57
- package/dist/ledger-read.d.ts.map +1 -1
- package/dist/ledger-read.js +24 -24
- package/dist/ledger-read.js.map +1 -1
- package/dist/ledger-write.d.ts +2 -2
- package/dist/ledger-write.js +1 -1
- package/dist/lifecycle-gather.d.ts +1 -1
- package/dist/lifecycle-gather.js +16 -16
- package/dist/lifecycle-gather.js.map +1 -1
- package/dist/lifecycle-pools.d.ts +4 -4
- package/dist/lifecycle-pools.js +1 -1
- package/dist/merge-question-surfacer.d.ts +3 -3
- package/dist/merge-question-surfacer.js +2 -2
- package/dist/merge-question-surfacer.js.map +1 -1
- package/dist/mint-adr.js +4 -4
- package/dist/mirror-pool-scan.d.ts +2 -2
- package/dist/mirror-pool-scan.js +3 -3
- package/dist/mirror-pool-scan.js.map +1 -1
- package/dist/needs-attention.d.ts +13 -13
- package/dist/needs-attention.d.ts.map +1 -1
- package/dist/needs-attention.js +11 -11
- package/dist/needs-attention.js.map +1 -1
- package/dist/orphan-sidecar.d.ts +2 -2
- package/dist/placement.d.ts +6 -6
- package/dist/placement.js +2 -2
- package/dist/prompt.d.ts +16 -19
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +17 -19
- package/dist/prompt.js.map +1 -1
- package/dist/readiness.d.ts +1 -1
- package/dist/recover-isolated.js +1 -1
- package/dist/repo-config.js +12 -12
- package/dist/repo-config.js.map +1 -1
- package/dist/review-gate.d.ts +3 -3
- package/dist/review-gate.d.ts.map +1 -1
- package/dist/review-gate.js +11 -10
- package/dist/review-gate.js.map +1 -1
- package/dist/review-verdict.d.ts +2 -2
- package/dist/review-verdict.d.ts.map +1 -1
- package/dist/review-verdict.js +1 -1
- package/dist/run.d.ts +1 -1
- package/dist/run.js +4 -4
- package/dist/run.js.map +1 -1
- package/dist/scan.d.ts +10 -10
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +8 -8
- package/dist/scan.js.map +1 -1
- package/dist/select-order.d.ts +1 -1
- package/dist/select-priority.d.ts +12 -12
- package/dist/select-priority.d.ts.map +1 -1
- package/dist/select-priority.js +5 -5
- package/dist/select-priority.js.map +1 -1
- package/dist/sidecar.d.ts +2 -2
- package/dist/sidecar.js +2 -2
- package/dist/sidecar.js.map +1 -1
- package/dist/slug-namespace.d.ts +1 -1
- package/dist/slug-namespace.js +3 -3
- package/dist/slug-namespace.js.map +1 -1
- package/dist/spec-complete.js +2 -2
- package/dist/spec-complete.js.map +1 -1
- package/dist/start.d.ts +1 -1
- package/dist/start.js +3 -3
- package/dist/start.js.map +1 -1
- package/dist/status.d.ts +3 -3
- package/dist/status.js +4 -4
- package/dist/status.js.map +1 -1
- package/dist/surface-gate.d.ts +2 -2
- package/dist/surface-gate.d.ts.map +1 -1
- package/dist/surface-persist.d.ts +2 -2
- package/dist/surface-persist.d.ts.map +1 -1
- package/dist/tasker-review-loop.d.ts +8 -8
- package/dist/tasker-review-loop.d.ts.map +1 -1
- package/dist/tasker-review-loop.js +8 -8
- package/dist/tasker-review-loop.js.map +1 -1
- package/dist/tasking-eligibility.d.ts +21 -21
- package/dist/tasking-eligibility.d.ts.map +1 -1
- package/dist/tasking-eligibility.js +10 -10
- package/dist/tasking-lock.d.ts +8 -8
- package/dist/tasking-lock.d.ts.map +1 -1
- package/dist/tasking-lock.js +20 -21
- package/dist/tasking-lock.js.map +1 -1
- package/dist/tasking.d.ts +33 -33
- package/dist/tasking.d.ts.map +1 -1
- package/dist/tasking.js +88 -86
- package/dist/tasking.js.map +1 -1
- package/dist/triage-gate.d.ts +1 -1
- package/dist/triage-persist.d.ts +5 -5
- package/dist/triage-persist.js +15 -15
- package/dist/triage-persist.js.map +1 -1
- package/dist/verify-workflow-template.d.ts +1 -1
- package/dist/verify-workflow-template.js +2 -2
- package/dist/work-layout.d.ts +9 -7
- package/dist/work-layout.d.ts.map +1 -1
- package/dist/work-layout.js +9 -7
- package/dist/work-layout.js.map +1 -1
- package/dist/workspace.d.ts +1 -1
- package/package.json +1 -1
- package/src/advance-ci-template.ts +4 -4
- package/src/advance-classify.ts +5 -5
- package/src/advance-drivers.ts +10 -10
- package/src/advance-isolated.ts +3 -3
- package/src/advance-lifecycle-template.ts +9 -9
- package/src/advance-loop-driver.ts +3 -3
- package/src/advance-treeless-publish.ts +1 -1
- package/src/advance.ts +30 -30
- package/src/advancing-lock.ts +6 -6
- package/src/apply-decide.ts +2 -2
- package/src/apply-merge-action.ts +5 -5
- package/src/apply-persist.ts +8 -8
- package/src/buildable-body.ts +14 -14
- package/src/claim-cas.ts +4 -4
- package/src/cli.ts +83 -83
- package/src/close-job-template.ts +8 -8
- package/src/close-job.ts +26 -26
- package/src/complete.ts +11 -11
- package/src/concurrency.ts +1 -1
- package/src/config.ts +37 -37
- package/src/continue-branch.ts +1 -1
- package/src/cwd-section.ts +1 -1
- package/src/decision-engine.ts +3 -3
- package/src/do-autopick.ts +9 -9
- package/src/do-config.ts +6 -6
- package/src/do-remote-auto.ts +2 -2
- package/src/do.ts +47 -47
- package/src/drop-source.ts +2 -2
- package/src/env-config.ts +8 -8
- package/src/format.ts +3 -3
- package/src/frontmatter.ts +23 -33
- package/src/install-ci-branch-protection.ts +1 -1
- package/src/install-ci-capabilities/advance-lifecycle.ts +1 -1
- package/src/install-ci-capabilities/close-job.ts +1 -1
- package/src/install-ci-capabilities/example-noop.ts +1 -1
- package/src/install-ci-capabilities/intake.ts +2 -2
- package/src/install-ci-capabilities/verify.ts +1 -1
- package/src/install-ci-core.ts +4 -4
- package/src/install-ci-github.ts +1 -1
- package/src/install-ci.ts +4 -4
- package/src/intake-event.ts +6 -6
- package/src/intake-marker.ts +3 -3
- package/src/intake-triage.ts +2 -2
- package/src/intake-trigger-template.ts +17 -17
- package/src/intake.ts +97 -97
- package/src/integration-core.ts +35 -35
- package/src/isolation.ts +3 -3
- package/src/issue-provider.ts +4 -4
- package/src/item-lock.ts +21 -21
- package/src/item-path.ts +2 -2
- package/src/ledger-lint.ts +9 -9
- package/src/ledger-read.ts +81 -81
- package/src/ledger-write.ts +3 -3
- package/src/lifecycle-gather.ts +16 -16
- package/src/lifecycle-pools.ts +4 -4
- package/src/merge-question-surfacer.ts +4 -4
- package/src/mint-adr.ts +4 -4
- package/src/mirror-pool-scan.ts +5 -5
- package/src/needs-attention.ts +22 -22
- package/src/orphan-sidecar.ts +2 -2
- package/src/placement.ts +6 -6
- package/src/prompt.ts +20 -25
- package/src/readiness.ts +1 -1
- package/src/recover-isolated.ts +1 -1
- package/src/repo-config.ts +12 -12
- package/src/review-gate.ts +12 -11
- package/src/review-verdict.ts +2 -2
- package/src/run.ts +5 -5
- package/src/scan.ts +15 -15
- package/src/select-order.ts +1 -1
- package/src/select-priority.ts +13 -13
- package/src/sidecar.ts +3 -3
- package/src/slug-namespace.ts +3 -3
- package/src/spec-complete.ts +2 -2
- package/src/start.ts +4 -4
- package/src/status.ts +7 -7
- package/src/surface-gate.ts +2 -2
- package/src/surface-persist.ts +2 -2
- package/src/tasker-review-loop.ts +15 -15
- package/src/tasking-eligibility.ts +21 -21
- package/src/tasking-lock.ts +27 -28
- package/src/tasking.ts +123 -121
- package/src/triage-gate.ts +1 -1
- package/src/triage-persist.ts +16 -16
- package/src/verify-workflow-template.ts +2 -2
- package/src/work-layout.ts +9 -7
- package/src/workspace.ts +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `install-ci` CLOSE-JOB capability (
|
|
2
|
+
* The `install-ci` CLOSE-JOB capability (spec `runner-in-ci`, task
|
|
3
3
|
* `install-ci-close-job-workflow`; capability E: close issues when their work
|
|
4
4
|
* lands). This module GENERATES the one fixed workflow file for the close-job and
|
|
5
5
|
* STRUCTURALLY VALIDATES it, mirroring the snapshot-assertion style of
|
|
6
6
|
* `advance-lifecycle-template.ts` / `advance-ci-template.ts` (the package depends on
|
|
7
7
|
* NO YAML lib, so the checks are presence/shape assertions over the raw text).
|
|
8
8
|
*
|
|
9
|
-
* The discipline (from the
|
|
9
|
+
* The discipline (from the spec capability-E row + the Out-of-Scope fence):
|
|
10
10
|
*
|
|
11
11
|
* - TRIGGER: a MERGE to `main`. There is no native "PR merged" event, so the
|
|
12
12
|
* workflow uses `push: {branches: [main]}` (NOT `pull_request: closed`): it
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* cannot close. (See the `## Decisions` block in the task.)
|
|
17
17
|
* - The job INVOKES the close machinery via `dorfl close-merged-issues`,
|
|
18
18
|
* which CONSUMES the UNCHANGED engine pieces: the resolution
|
|
19
|
-
* (`resolveClosingIssue`), the "
|
|
19
|
+
* (`resolveClosingIssue`), the "spec complete?" query (`prd-complete-query`,
|
|
20
20
|
* done), and `IssueProvider.closeIssue`. CI owns ONLY the job + trigger; it
|
|
21
21
|
* re-implements NONE of those (the Out-of-Scope fence).
|
|
22
22
|
* - CI runs IN-PLACE (the CI container IS the isolation): no
|
|
@@ -54,7 +54,7 @@ export const CLOSE_JOB_WORKFLOW_PATH = 'workflows/close-job.yml';
|
|
|
54
54
|
*/
|
|
55
55
|
export function generateCloseJobWorkflow(_config: ResolvedCIConfig): string {
|
|
56
56
|
return `\
|
|
57
|
-
# dorfl — the ISSUE CLOSE-JOB in CI (capability E,
|
|
57
|
+
# dorfl — the ISSUE CLOSE-JOB in CI (capability E, spec runner-in-ci).
|
|
58
58
|
# EMITTED by \`dorfl install-ci\`; the human commits it. DO NOT hand-edit a
|
|
59
59
|
# copy — re-run install-ci to upgrade the shell.
|
|
60
60
|
#
|
|
@@ -69,9 +69,9 @@ export function generateCloseJobWorkflow(_config: ResolvedCIConfig): string {
|
|
|
69
69
|
# the landed work closes and closes them. CI owns ONLY this job + the trigger; the
|
|
70
70
|
# command CONSUMES the engine's UNCHANGED pieces and re-implements none of them:
|
|
71
71
|
# * the RESOLUTION (resolveClosingIssue): a lone task closes its own \`issue:\`;
|
|
72
|
-
# a fanned task reaches the number via \`task.
|
|
73
|
-
# * the "
|
|
74
|
-
# ONLY when ALL its \`
|
|
72
|
+
# a fanned task reaches the number via \`task.spec: → spec issue:\`.
|
|
73
|
+
# * the "spec complete?" QUERY (prd-complete-query, done): a spec's issue closes
|
|
74
|
+
# ONLY when ALL its \`spec:<slug>\` tasks are in work/done/.
|
|
75
75
|
# * the CLOSE (IssueProvider.closeIssue): the atomic comment+close seam — NO
|
|
76
76
|
# direct \`gh\` in the engine core; any comment rides this close, never the PR
|
|
77
77
|
# comment seam.
|
|
@@ -117,7 +117,7 @@ jobs:
|
|
|
117
117
|
- name: close issues whose work has landed on main
|
|
118
118
|
# In-place in this checkout (no --isolated/--remote): the CI container IS
|
|
119
119
|
# the isolation. Resolves the closing issue(s) from the work/ tree, runs
|
|
120
|
-
# the "
|
|
120
|
+
# the "spec complete?" query for the spec case, and closes via the provider
|
|
121
121
|
# seam — all UNCHANGED engine pieces, consumed not re-built.
|
|
122
122
|
env:
|
|
123
123
|
GH_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
package/src/close-job.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The CI CLOSE-JOB driver (
|
|
2
|
+
* The CI CLOSE-JOB driver (spec `runner-in-ci`, capability E; task
|
|
3
3
|
* `install-ci-close-job-workflow`). When work lands on `main`, this resolves which
|
|
4
4
|
* source issue(s) the landed work closes and closes them — but it OWNS none of the
|
|
5
5
|
* machinery it relies on. It is the thin JOB that WIRES three UNCHANGED engine
|
|
6
6
|
* pieces together (the Out-of-Scope fence: do NOT re-build them):
|
|
7
7
|
*
|
|
8
8
|
* - the RESOLUTION — {@link resolveClosingIssue} (`frontmatter.ts`): an artifact
|
|
9
|
-
* uses `issue:` XOR `
|
|
10
|
-
* fanned task reaches the number via `task.
|
|
11
|
-
* issue:`, and `
|
|
9
|
+
* uses `issue:` XOR `spec:`; a lone task closes its own `issue:` directly, a
|
|
10
|
+
* fanned task reaches the number via `task.spec: → work/specs/<spec>.md spec
|
|
11
|
+
* issue:`, and `spec:` WINS on a (hand-edited) conflict;
|
|
12
12
|
* - the QUERY — {@link isSpecComplete} (`spec-complete.ts`, task
|
|
13
13
|
* `prd-complete-query`, done): a spec is COMPLETE iff ≥1 `spec:<slug>` task AND
|
|
14
14
|
* all such tasks are in `work/done/`;
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
*
|
|
20
20
|
* The closure conditions, per artifact kind:
|
|
21
21
|
*
|
|
22
|
-
* - a **lone task** (`issue:`, no `
|
|
22
|
+
* - a **lone task** (`issue:`, no `spec:`) that resides in `work/done/` — its PR
|
|
23
23
|
* merged, so its own issue closes (reason `completed`);
|
|
24
|
-
* - a **
|
|
24
|
+
* - a **spec** (`issue:`) — closes ONLY when {@link isSpecComplete} says ALL its
|
|
25
25
|
* `spec:<slug>` tasks are in `work/done/` (reason `completed`).
|
|
26
26
|
*
|
|
27
|
-
* A
|
|
27
|
+
* A spec whose query is NOT yet complete is left OPEN (the final fanned task's
|
|
28
28
|
* merge tick closes it). A lone task still outside `work/done/` is skipped. The
|
|
29
29
|
* close DEGRADES (never throws) on a missing/unauthenticated provider, exactly
|
|
30
30
|
* like intake's bounce close — the run reports the real cause and stays exit-0.
|
|
@@ -62,7 +62,7 @@ const SPEC_LIFECYCLE_FOLDERS = SPEC_FOLDERS;
|
|
|
62
62
|
/** Why the close-job acted (or did not act) on a candidate issue. */
|
|
63
63
|
export type CloseDecision =
|
|
64
64
|
| 'closed' // the issue was closed via the provider seam
|
|
65
|
-
| 'not-complete' // a
|
|
65
|
+
| 'not-complete' // a spec whose query says it is not yet complete → left open
|
|
66
66
|
| 'not-landed' // a lone task not yet in work/done/ → left open
|
|
67
67
|
| 'close-failed'; // closure condition held but the provider close degraded
|
|
68
68
|
|
|
@@ -111,9 +111,9 @@ function listMarkdown(repoPath: string, folder: WorkFolderKey): string[] {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
|
-
* Read a
|
|
115
|
-
* `undefined` when no
|
|
116
|
-
* issue, or a typo'd `
|
|
114
|
+
* Read a spec's `issue:` number by slug, scanning the spec folders. Returns
|
|
115
|
+
* `undefined` when no spec with that slug carries an `issue:` (a spec with no source
|
|
116
|
+
* issue, or a typo'd `spec:` hop — degrades to "no issue to close", never crashes).
|
|
117
117
|
*/
|
|
118
118
|
function specIssueNumber(
|
|
119
119
|
repoPath: string,
|
|
@@ -137,14 +137,14 @@ function specIssueNumber(
|
|
|
137
137
|
* Resolve the DEDUPLICATED set of closure candidates from the `work/` tree, each
|
|
138
138
|
* via the UNCHANGED {@link resolveClosingIssue}:
|
|
139
139
|
*
|
|
140
|
-
* - every
|
|
141
|
-
*
|
|
142
|
-
* - every LONE task (`issue:` and NO `
|
|
140
|
+
* - every spec carrying `issue:` (in `work/specs/ready/` or `work/specs/tasked/`) is a
|
|
141
|
+
* spec-kind candidate keyed on its own `spec:` query;
|
|
142
|
+
* - every LONE task (`issue:` and NO `spec:`) is an `issue`-kind candidate.
|
|
143
143
|
*
|
|
144
|
-
* A fanned task carries `
|
|
145
|
-
* through its
|
|
146
|
-
* the
|
|
147
|
-
* tasks point at it.
|
|
144
|
+
* A fanned task carries `spec:` (NOT its own `issue:`), so it reaches the number
|
|
145
|
+
* through its spec's candidate, never as its own — the issue number lives ONLY on
|
|
146
|
+
* the spec. Deduplicated by issue number: a spec enumerated once even though many
|
|
147
|
+
* tasks point at it. Spec candidates are listed before lone-task candidates, each
|
|
148
148
|
* group slug-sorted, for a deterministic log.
|
|
149
149
|
*/
|
|
150
150
|
function resolveCandidates(repoPath: string): {
|
|
@@ -165,9 +165,9 @@ function resolveCandidates(repoPath: string): {
|
|
|
165
165
|
);
|
|
166
166
|
const slug = fm.slug ?? basename(file, '.md');
|
|
167
167
|
const closing = resolveClosingIssue(fm);
|
|
168
|
-
// A
|
|
169
|
-
// hand-edit conflict `
|
|
170
|
-
// `issue:`-bearing
|
|
168
|
+
// A spec's own closing link is its `issue:` (a spec has no `spec:`); on the
|
|
169
|
+
// hand-edit conflict `spec:` wins via resolveClosingIssue, so only a true
|
|
170
|
+
// `issue:`-bearing spec becomes a candidate here.
|
|
171
171
|
if (closing?.via === 'issue' && !seen.has(closing.issue)) {
|
|
172
172
|
seen.add(closing.issue);
|
|
173
173
|
specCandidates.push({issueNumber: closing.issue, via: 'spec', slug});
|
|
@@ -175,7 +175,7 @@ function resolveCandidates(repoPath: string): {
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
// Lone-task candidates: a task with `issue:` and NO `
|
|
178
|
+
// Lone-task candidates: a task with `issue:` and NO `spec:` closes its OWN
|
|
179
179
|
// issue directly when it lands in work/done/.
|
|
180
180
|
for (const folder of TASK_FOLDERS) {
|
|
181
181
|
for (const file of listMarkdown(repoPath, folder)) {
|
|
@@ -184,9 +184,9 @@ function resolveCandidates(repoPath: string): {
|
|
|
184
184
|
);
|
|
185
185
|
const slug = fm.slug ?? basename(file, '.md');
|
|
186
186
|
const closing = resolveClosingIssue(fm);
|
|
187
|
-
// `resolveClosingIssue` returns `via: 'issue'` ONLY when there is no `
|
|
188
|
-
// (
|
|
189
|
-
// its issue through the
|
|
187
|
+
// `resolveClosingIssue` returns `via: 'issue'` ONLY when there is no `spec:`
|
|
188
|
+
// (spec wins on conflict), so a fanned task never lands here — it reaches
|
|
189
|
+
// its issue through the spec candidate above.
|
|
190
190
|
if (closing?.via === 'issue' && !seen.has(closing.issue)) {
|
|
191
191
|
seen.add(closing.issue);
|
|
192
192
|
taskCandidates.push({issueNumber: closing.issue, via: 'issue', slug});
|
|
@@ -222,7 +222,7 @@ function closeComment(via: 'issue' | 'spec', slug: string): string {
|
|
|
222
222
|
|
|
223
223
|
/**
|
|
224
224
|
* Run the close-job over a repo's `work/` tree: resolve the closure candidates,
|
|
225
|
-
* apply the per-kind closure condition (a landed lone task; a
|
|
225
|
+
* apply the per-kind closure condition (a landed lone task; a spec whose
|
|
226
226
|
* {@link isSpecComplete} query holds), and close the qualifying issues through the
|
|
227
227
|
* {@link IssueProvider.closeIssue} seam (reason `completed`, an informational
|
|
228
228
|
* comment riding the SAME atomic close). REUSES the unchanged resolution + query +
|
package/src/complete.ts
CHANGED
|
@@ -160,7 +160,7 @@ export interface CompleteOptions {
|
|
|
160
160
|
*/
|
|
161
161
|
freshWorktreeGate?: boolean;
|
|
162
162
|
/**
|
|
163
|
-
* **The cross-job merge-serialiser CAS-retry cap** (config `mergeRetries`,
|
|
163
|
+
* **The cross-job merge-serialiser CAS-retry cap** (config `mergeRetries`, spec
|
|
164
164
|
* `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1
|
|
165
165
|
* (a)). Threaded verbatim into {@link performIntegration} as `mergeRetries` so
|
|
166
166
|
* the resolved per-repo value controls how many re-rebase-and-retry attempts
|
|
@@ -172,7 +172,7 @@ export interface CompleteOptions {
|
|
|
172
172
|
/** Skip the acceptance gate (human-only escape hatch; never used unattended). */
|
|
173
173
|
skipVerify?: boolean;
|
|
174
174
|
/**
|
|
175
|
-
* **`--allow-backlog`** (
|
|
175
|
+
* **`--allow-backlog`** (spec
|
|
176
176
|
* `do-allow-backlog-drive-staged-tasks-without-promotion`): TREAT a
|
|
177
177
|
* `tasks/backlog/`-resident body (staging) as a VALID build source, so a
|
|
178
178
|
* staged task driven in place done-moves `tasks/backlog/ → tasks/done/`
|
|
@@ -185,7 +185,7 @@ export interface CompleteOptions {
|
|
|
185
185
|
*/
|
|
186
186
|
allowBacklog?: boolean;
|
|
187
187
|
/**
|
|
188
|
-
* **Gate 2 — the PR/code review gate** (GATES
|
|
188
|
+
* **Gate 2 — the PR/code review gate** (GATES spec `work/specs/tasked/review.md`). When
|
|
189
189
|
* `true`, after the green `verify` and BEFORE the done-move, run the `review`
|
|
190
190
|
* SKILL as a FRESH-CONTEXT agent (its own harness launch) and route its verdict:
|
|
191
191
|
* `approve` → proceed to done-move/commit/integrate; `block` → route to
|
|
@@ -417,7 +417,7 @@ export async function performComplete(
|
|
|
417
417
|
return await runComplete(options, note);
|
|
418
418
|
} catch (err) {
|
|
419
419
|
// AUTONOMOUS-STRAND SURFACE (task
|
|
420
|
-
// `autonomous-integration-refusal-surfaces-not-strands-in-progress`,
|
|
420
|
+
// `autonomous-integration-refusal-surfaces-not-strands-in-progress`, spec
|
|
421
421
|
// `ledger-integrity` story 7). On the AUTONOMOUS path (`surfaceArbiter` set
|
|
422
422
|
// — the human-vs-autonomous gate the core's other failures use), a SOURCE-
|
|
423
423
|
// STRAND `CompleteRefusal` (the slug-is-stuck `nothing to complete`) and the
|
|
@@ -633,7 +633,7 @@ async function runComplete(
|
|
|
633
633
|
);
|
|
634
634
|
}
|
|
635
635
|
// The branch HEAD is on when it IS a work branch for this slug (so an explicit
|
|
636
|
-
// `
|
|
636
|
+
// `spec:`-style recovery still completes the branch it is standing on); else
|
|
637
637
|
// synthesise the task branch.
|
|
638
638
|
const branch =
|
|
639
639
|
headParsed && headParsed.slug === slug
|
|
@@ -676,7 +676,7 @@ async function runComplete(
|
|
|
676
676
|
const inProgress = workItemPath(cwd, 'in-progress', slug);
|
|
677
677
|
const done = workItemPath(cwd, 'done', slug);
|
|
678
678
|
const onBacklog = existsSync(backlog);
|
|
679
|
-
// `--allow-backlog` drive (
|
|
679
|
+
// `--allow-backlog` drive (spec
|
|
680
680
|
// `do-allow-backlog-drive-staged-tasks-without-promotion`): a staged task driven
|
|
681
681
|
// in place RESTS in `tasks/backlog/` (claim never moved it). Detect it as a build
|
|
682
682
|
// source so the done-move goes `tasks/backlog/ → tasks/done/` DIRECTLY (the
|
|
@@ -699,7 +699,7 @@ async function runComplete(
|
|
|
699
699
|
!onPreBacklog &&
|
|
700
700
|
!onInProgress &&
|
|
701
701
|
recordAtRenamedDonePosition(cwd, slug));
|
|
702
|
-
// STRANDED-DONE AUTO-RECOVER (
|
|
702
|
+
// STRANDED-DONE AUTO-RECOVER (spec `ledger-integrity` story 6, the autonomous
|
|
703
703
|
// half of `finish-already-committed-branch`). When neither in-progress/ nor
|
|
704
704
|
// needs-attention/ holds the slug on the BRANCH tree BUT done/ does, the work
|
|
705
705
|
// branch was already built + done-moved + committed by a prior run that never
|
|
@@ -892,7 +892,7 @@ async function runComplete(
|
|
|
892
892
|
freshWorktreeGate: options.freshWorktreeGate,
|
|
893
893
|
// The cross-job merge-serialiser CAS-retry cap (config `mergeRetries`) — the
|
|
894
894
|
// git-alone FLOOR of the cross-job land-queue, resolved through the gate-family
|
|
895
|
-
// precedence chain (
|
|
895
|
+
// precedence chain (spec `land-time-reverify-and-parallel-merge-ceiling` Story
|
|
896
896
|
// 5). Threaded so a wide-matrix CI's raised cap actually reaches the merge loop.
|
|
897
897
|
mergeRetries: options.mergeRetries,
|
|
898
898
|
skipVerify: options.skipVerify,
|
|
@@ -983,7 +983,7 @@ async function runComplete(
|
|
|
983
983
|
// because the work is already integrated and the branch may or may not
|
|
984
984
|
// still exist locally.
|
|
985
985
|
//
|
|
986
|
-
// CROSS-SUBSTRATE RELEASE (
|
|
986
|
+
// CROSS-SUBSTRATE RELEASE (spec `ledger-status-per-item-lock-refs` US #9/#10;
|
|
987
987
|
// task `complete-lock-then-durable-main-move-crash-safe`): the durable
|
|
988
988
|
// `main` record is already terminal (the kept tip is provably on
|
|
989
989
|
// `<arbiter>/main`), so the per-item lock claim took is now stale: release it
|
|
@@ -1021,7 +1021,7 @@ async function runComplete(
|
|
|
1021
1021
|
const commitMessage = core.commitMessage;
|
|
1022
1022
|
const mode = result.mode;
|
|
1023
1023
|
|
|
1024
|
-
// CROSS-SUBSTRATE RELEASE, gated on the work being DURABLY ON `main` (
|
|
1024
|
+
// CROSS-SUBSTRATE RELEASE, gated on the work being DURABLY ON `main` (spec
|
|
1025
1025
|
// `ledger-status-per-item-lock-refs` US #9/#10; ADR
|
|
1026
1026
|
// `ledger-status-on-per-item-lock-refs`; the trail's Amendment 6; task
|
|
1027
1027
|
// `complete-lock-then-durable-main-move-crash-safe`). ORDER MATTERS: the
|
|
@@ -1158,7 +1158,7 @@ async function runComplete(
|
|
|
1158
1158
|
/**
|
|
1159
1159
|
* Release the per-item lock `claim` ALSO acquired (`action: implement`, keyed
|
|
1160
1160
|
* `task:<slug>`) AFTER the durable `main` move has landed — the SECOND, lock-
|
|
1161
|
-
* release half of complete's cross-substrate ordering (
|
|
1161
|
+
* release half of complete's cross-substrate ordering (spec
|
|
1162
1162
|
* `ledger-status-per-item-lock-refs` US #9/#10; task
|
|
1163
1163
|
* `complete-lock-then-durable-main-move-crash-safe`).
|
|
1164
1164
|
*
|
package/src/concurrency.ts
CHANGED
|
@@ -49,7 +49,7 @@ export interface RunConcurrentOptions<I, T> {
|
|
|
49
49
|
/**
|
|
50
50
|
* A per-key async serialiser: `withKeyedLock(key, fn)` runs `fn` to completion
|
|
51
51
|
* before the next caller for the SAME key starts; different keys never block each
|
|
52
|
-
* other. Used to serialise the
|
|
52
|
+
* other. Used to serialise the spec, shared-working-tree CLAIM step PER REPO
|
|
53
53
|
* inside the otherwise-concurrent tick.
|
|
54
54
|
*
|
|
55
55
|
* Two concurrent claims in ONE repo would prepare their claim micro-commit in the
|
package/src/config.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
export type IntegrationMode = 'propose' | 'merge';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* **Per-repo TASK-PLACEMENT default** (
|
|
20
|
+
* **Per-repo TASK-PLACEMENT default** (spec
|
|
21
21
|
* `staging-pool-position-gate-and-trust-model`, task
|
|
22
22
|
* `runner-deterministic-slice-placement-policy-and-precedence`, governing ADR
|
|
23
23
|
* `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Which
|
|
@@ -38,24 +38,24 @@ export type IntegrationMode = 'propose' | 'merge';
|
|
|
38
38
|
export type TasksLandIn = 'pre-backlog' | 'ready';
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* **Per-repo
|
|
41
|
+
* **Per-repo SPEC-PLACEMENT default** (spec
|
|
42
42
|
* `staging-pool-position-gate-and-trust-model`, task
|
|
43
43
|
* `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing ADR
|
|
44
44
|
* `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Which
|
|
45
|
-
* folder the runner lands `intake`-authored
|
|
45
|
+
* folder the runner lands `intake`-authored spec files in BY DEFAULT —
|
|
46
46
|
* `'pre-proposed'` (staging — durable + readable but NOT in the auto-tasking
|
|
47
|
-
* POOL; a runner/human promotion is needed to make the
|
|
48
|
-
* on-disk folder for this value is `work/
|
|
47
|
+
* POOL; a runner/human promotion is needed to make the spec auto-taskable; the
|
|
48
|
+
* on-disk folder for this value is `work/specs/proposed/`) or `'ready'` (the
|
|
49
49
|
* auto-tasking POOL — the trusted fast-path landing, on-disk
|
|
50
|
-
* `work/
|
|
50
|
+
* `work/specs/ready/`). The same runner-deterministic placement RESOLVER
|
|
51
51
|
* (`src/placement.ts`) layers on top:
|
|
52
52
|
* `explicit operator flag > untrusted-origin ⇒ pre-proposed > specsLandIn
|
|
53
53
|
* default > built-in (pre-proposed)`. An untrusted-origin intake spec is FORCED
|
|
54
54
|
* to staging even in a `'ready'` repo (the positional analogue of the existing
|
|
55
|
-
* `untrusted-origin-forces-build-propose` rule). The
|
|
55
|
+
* `untrusted-origin-forces-build-propose` rule). The SPEC twin of
|
|
56
56
|
* {@link TasksLandIn}; the SAME shape, the SAME precedence chain. The value
|
|
57
|
-
* spellings mirror the live
|
|
58
|
-
* `
|
|
57
|
+
* spellings mirror the live spec folders (`specs/proposed/` staging,
|
|
58
|
+
* `specs/ready/` pool), exactly as {@link TasksLandIn} mirrors the task folders.
|
|
59
59
|
*/
|
|
60
60
|
export type SpecsLandIn = 'pre-proposed' | 'ready';
|
|
61
61
|
|
|
@@ -79,7 +79,7 @@ export type ObservationTriage = 'off' | 'ask' | 'auto';
|
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
81
|
* **The `mergeQuestions` gate axis** — the 3-state member of the question-
|
|
82
|
-
* surfacing gate family that governs the MERGE-QUESTION surfacer (
|
|
82
|
+
* surfacing gate family that governs the MERGE-QUESTION surfacer (spec
|
|
83
83
|
* `land-time-reverify-and-parallel-merge-ceiling` Story 17 / task
|
|
84
84
|
* `merge-questions-gate-axis`). MIRRORS `observationTriage`'s shape
|
|
85
85
|
* (`off | ask | auto`) but is a SEPARATE axis — "should this built work merge?"
|
|
@@ -99,7 +99,7 @@ export type ObservationTriage = 'off' | 'ask' | 'auto';
|
|
|
99
99
|
* invoke the agentic decider — a merge-land is never an agent decision.
|
|
100
100
|
* Resolved through the SAME precedence chain as the other gates (flag > env >
|
|
101
101
|
* per-repo > global > default `ask`). The exact name + default + shape were
|
|
102
|
-
* answered in this task's Applied answers 2026-06-26 (q1/q2/q3) +
|
|
102
|
+
* answered in this task's Applied answers 2026-06-26 (q1/q2/q3) + SPEC sidecar
|
|
103
103
|
* Q3.
|
|
104
104
|
*/
|
|
105
105
|
export type MergeQuestions = 'off' | 'ask' | 'auto';
|
|
@@ -201,10 +201,10 @@ export interface Config {
|
|
|
201
201
|
/**
|
|
202
202
|
* Per-repo policy: may an agent auto-task *undeclared* (not `humanOnly`,
|
|
203
203
|
* no open questions) prds in this repo? `false` (default, strict, human-first)
|
|
204
|
-
* ⇒ a human must drive every
|
|
205
|
-
* any
|
|
204
|
+
* ⇒ a human must drive every spec's tasking; `true` ⇒ an agent may auto-task
|
|
205
|
+
* any spec that is not `humanOnly: true` and has no `needsAnswers`. Resolved like
|
|
206
206
|
* `autoBuild`: flag > `DORFL_AUTO_TASK` env > per-repo > global >
|
|
207
|
-
* default. The two-axis tasking gate (`work/
|
|
207
|
+
* default. The two-axis tasking gate (`work/specs/auto-task.md`), one level up
|
|
208
208
|
* from the build gate's `autoBuild`.
|
|
209
209
|
*/
|
|
210
210
|
autoTask: boolean;
|
|
@@ -227,7 +227,7 @@ export interface Config {
|
|
|
227
227
|
observationTriage: ObservationTriage;
|
|
228
228
|
/**
|
|
229
229
|
* Per-repo policy governing the MERGE-QUESTION SURFACER — the 3-state member
|
|
230
|
-
* of the question-surfacing gate family (
|
|
230
|
+
* of the question-surfacing gate family (spec
|
|
231
231
|
* `land-time-reverify-and-parallel-merge-ceiling` Story 17 / task
|
|
232
232
|
* `merge-questions-gate-axis`). MIRRORS `observationTriage`'s SHAPE
|
|
233
233
|
* (`off | ask | auto`) but is a SEPARATE axis with a DIFFERENT default —
|
|
@@ -251,7 +251,7 @@ export interface Config {
|
|
|
251
251
|
* Per-repo policy governing DECLARED blocked work — the BOOLEAN member of the
|
|
252
252
|
* question-surfacing gate family (its orthogonal PEER is `observationTriage`,
|
|
253
253
|
* which governs the raw observation INBOX; ADR `ci-config-policy-and-gate-family`
|
|
254
|
-
* §2). It gates whether a task/
|
|
254
|
+
* §2). It gates whether a task/spec carrying `needsAnswers: true` is rendered
|
|
255
255
|
* into an answerable question sidecar (`on`) or left silently blocked in the
|
|
256
256
|
* backlog (`off`). `false` (default, calm) ⇒ the `needsAnswers`-blocked pool is
|
|
257
257
|
* dropped from the auto-pick SELECTION, so a bare `advance` does NOT proactively
|
|
@@ -271,11 +271,11 @@ export interface Config {
|
|
|
271
271
|
/**
|
|
272
272
|
* Per-repo policy governing whether SURFACING (the question-minting polarity)
|
|
273
273
|
* inspects STAGING in addition to the agent pool — the BOOLEAN gate-family
|
|
274
|
-
* member added by
|
|
274
|
+
* member added by spec `staging-surface-and-apply-promote-safety` (F2). The
|
|
275
275
|
* BUILD polarity is UNCHANGED in either mode: staging items stay non-claimable,
|
|
276
276
|
* the trust model is untouched. `true` (default) ⇒ the SURFACE candidate set
|
|
277
|
-
* draws from STAGING (`tasks/backlog/`, `
|
|
278
|
-
* a `needsAnswers` task/
|
|
277
|
+
* draws from STAGING (`tasks/backlog/`, `specs/proposed/`) PLUS the pool, so
|
|
278
|
+
* a `needsAnswers` task/spec in staging surfaces its questions BEFORE a human
|
|
279
279
|
* promotes it (you promote an already-clarified item, not blind and then get
|
|
280
280
|
* asked after); `false` ⇒ the legacy POOL-ONLY behaviour (staging is not
|
|
281
281
|
* inspected for questions). Resolved like `surfaceBlockers`/`autoBuild`:
|
|
@@ -340,14 +340,14 @@ export interface Config {
|
|
|
340
340
|
/** Integration mode for completed items: `propose` (default) or `merge`. */
|
|
341
341
|
integration: IntegrationMode;
|
|
342
342
|
/**
|
|
343
|
-
* **Per-TRANSITION override for the
|
|
344
|
-
* set, the tasking transition (a `do
|
|
345
|
-
* the `work/
|
|
343
|
+
* **Per-TRANSITION override for the spec→tasks (TASKING) transition only.** When
|
|
344
|
+
* set, the tasking transition (a `do spec:<slug>` run: emit `work/tasks/backlog/*.md` +
|
|
345
|
+
* the `work/specs/ready/ → work/specs/tasked/` lifecycle move) integrates with THIS
|
|
346
346
|
* mode instead of the flat {@link integration}; the task-BUILD transition is
|
|
347
347
|
* unaffected (it always reads {@link integration}). UNSET (the default) ⇒ tasking
|
|
348
348
|
* falls back to {@link integration} — byte-for-byte today's behaviour for any repo
|
|
349
349
|
* that does not set it. The maintainer's target is `integration: 'propose'` +
|
|
350
|
-
* `taskingIntegration: 'merge'`: task a
|
|
350
|
+
* `taskingIntegration: 'merge'`: task a spec straight onto `main` (the task FILES
|
|
351
351
|
* land, no PR) but build each task as a reviewable PR. Resolved per-repo like
|
|
352
352
|
* {@link integration}: flag (`--merge`/`--propose`) > env
|
|
353
353
|
* (`DORFL_TASKING_INTEGRATION`) > per-repo > global > (fall back to)
|
|
@@ -357,7 +357,7 @@ export interface Config {
|
|
|
357
357
|
*/
|
|
358
358
|
taskingIntegration?: IntegrationMode;
|
|
359
359
|
/**
|
|
360
|
-
* **Per-repo DEFAULT landing for the TASKER's emitted tasks** (
|
|
360
|
+
* **Per-repo DEFAULT landing for the TASKER's emitted tasks** (spec
|
|
361
361
|
* `staging-pool-position-gate-and-trust-model` US #5, task
|
|
362
362
|
* `runner-deterministic-slice-placement-policy-and-precedence`). Resolved
|
|
363
363
|
* per-repo EXACTLY like {@link taskingIntegration} (flag `--tasks-land-in`
|
|
@@ -366,7 +366,7 @@ export interface Config {
|
|
|
366
366
|
* CONFIGURED-DEFAULT rung into the shared placement resolver
|
|
367
367
|
* (`src/placement.ts`); the resolver overlays an EXPLICIT operator flag
|
|
368
368
|
* (top) and the UNTRUSTED-ORIGIN force (staging) on top, in that order. The
|
|
369
|
-
* tasker NEVER sets placement itself.
|
|
369
|
+
* tasker NEVER sets placement itself. Spec US #6 / the governing ADR: the
|
|
370
370
|
* runner OWNS placement from unforgeable inputs; the agent cannot
|
|
371
371
|
* influence it.
|
|
372
372
|
*/
|
|
@@ -385,7 +385,7 @@ export interface Config {
|
|
|
385
385
|
* influence it. KEY-LEVEL SYMMETRY with `tasksLandIn` — one resolver, two
|
|
386
386
|
* lifecycles, one precedence change touches ONE place.
|
|
387
387
|
*
|
|
388
|
-
* The sole spec-placement key after the prd → spec HARD CUTOVER (spec
|
|
388
|
+
* The sole spec-placement key after the `prd` → `spec` HARD CUTOVER (spec
|
|
389
389
|
* `prd-to-spec-vocabulary-cutover-and-migration-command`): the legacy
|
|
390
390
|
* `prdsLandIn` config key + `--prds-land-in` flag are GONE (clean break).
|
|
391
391
|
*/
|
|
@@ -483,7 +483,7 @@ export interface Config {
|
|
|
483
483
|
*/
|
|
484
484
|
verify?: VerifyConfig;
|
|
485
485
|
/**
|
|
486
|
-
* **Gate 2 — the PR/code review gate** (GATES
|
|
486
|
+
* **Gate 2 — the PR/code review gate** (GATES spec `work/specs/tasked/review.md`): run the
|
|
487
487
|
* `review` SKILL as a fresh-context judgement gate ON TOP of the deterministic
|
|
488
488
|
* `verify` floor, AFTER `verify` passes and BEFORE the done-move, on the
|
|
489
489
|
* `do`/`complete` path. Default **OFF** (it puts a model on the merge path —
|
|
@@ -519,7 +519,7 @@ export interface Config {
|
|
|
519
519
|
reviewMaxRounds: number;
|
|
520
520
|
/**
|
|
521
521
|
* **The tasker IMPROVER loop on/off toggle** (`--tasker-loop` /
|
|
522
|
-
* `--no-tasker-loop`). On the `do
|
|
522
|
+
* `--no-tasker-loop`). On the `do spec:<slug>` tasking path the improver loop is
|
|
523
523
|
* the task path's quality engine (auto-tasking has no `verify` floor), so it is
|
|
524
524
|
* ON by default; setting this false gates wiring the loop seam (the candidate
|
|
525
525
|
* tasks land as-is). Resolved per-repo like `integration`: flag
|
|
@@ -529,8 +529,8 @@ export interface Config {
|
|
|
529
529
|
taskerLoop: boolean;
|
|
530
530
|
/**
|
|
531
531
|
* **The tasker IMPROVER loop's convergence cap** (`slicer-review-edit-loop`,
|
|
532
|
-
* GATES
|
|
533
|
-
* A). On the `do
|
|
532
|
+
* GATES spec `work/specs/tasked/review.md` RESOLVED DESIGN — Shape 2 / insertion point
|
|
533
|
+
* A). On the `do spec:<slug>` tasking path, AFTER the agent produces candidate
|
|
534
534
|
* tasks the loop runs the `review` SKILL, APPLIES its edits, and re-reviews
|
|
535
535
|
* until a pass finds no NEW blocking issue (the natural terminator).
|
|
536
536
|
* `taskerLoopMax` is the HARD CAP on the in-context review passes (N) so the
|
|
@@ -583,7 +583,7 @@ export interface Config {
|
|
|
583
583
|
freshWorktreeGate: boolean;
|
|
584
584
|
/**
|
|
585
585
|
* **The cross-job merge serialiser's CAS-retry cap** — the git-alone FLOOR of the
|
|
586
|
-
* land-time cross-job queue (
|
|
586
|
+
* land-time cross-job queue (spec `land-time-reverify-and-parallel-merge-ceiling`,
|
|
587
587
|
* Story 5 + Applied Answer q1 (a)). The merge-mode `${branch}:main` push retries
|
|
588
588
|
* a non-fast-forward rejection by re-rebasing onto the moved `<arbiter>/main` and
|
|
589
589
|
* pushing again, up to this cap; only after exhaustion does a loser bounce to
|
|
@@ -605,7 +605,7 @@ export interface Config {
|
|
|
605
605
|
mergeRetries: number;
|
|
606
606
|
/**
|
|
607
607
|
* **Per-repo OPT-IN strictness layered on the OQ6 stale-approval default**
|
|
608
|
-
* (
|
|
608
|
+
* (spec `land-time-reverify-and-parallel-merge-ceiling`, sidecar OQ6 / task
|
|
609
609
|
* `strict-merge-approval-gate`). Controls how the apply rung treats a prior
|
|
610
610
|
* merge-answer when the merge-base CHANGED between the human's answer and
|
|
611
611
|
* the apply step. The default (`false`) honours the prior answer and lands
|
|
@@ -711,7 +711,7 @@ export const DEFAULT_CONFIG: Config = {
|
|
|
711
711
|
// auto-dispose the no-question cases). ADR `ci-config-policy-and-gate-family` §3.
|
|
712
712
|
observationTriage: 'off',
|
|
713
713
|
// The merge-question SURFACER defaults to `ask` — the conservative default
|
|
714
|
-
// (
|
|
714
|
+
// (spec `land-time-reverify-and-parallel-merge-ceiling` Applied answer q2 /
|
|
715
715
|
// task `merge-questions-gate-axis` Applied answer q2). NEVER `off` by default:
|
|
716
716
|
// a silently-dropped merge-question means finished, pushed work never lands —
|
|
717
717
|
// strictly more consequential than a dropped observation-promote prompt, so
|
|
@@ -728,9 +728,9 @@ export const DEFAULT_CONFIG: Config = {
|
|
|
728
728
|
// (a stuck build) is separate + always-on. ADR `ci-config-policy-and-gate-family` §3.
|
|
729
729
|
surfaceBlockers: false,
|
|
730
730
|
// SURFACING widens to STAGING by default (`true`) — a `needsAnswers` task in
|
|
731
|
-
// `tasks/backlog/` or a `needsAnswers`
|
|
731
|
+
// `tasks/backlog/` or a `needsAnswers` spec in `specs/proposed/` surfaces
|
|
732
732
|
// its questions BEFORE promotion, so a human promotes an already-clarified
|
|
733
|
-
// item.
|
|
733
|
+
// item. Spec `staging-surface-and-apply-promote-safety` (F2). BUILD/claim
|
|
734
734
|
// stays pool-only + trust-gated regardless: this widens ONLY the surface
|
|
735
735
|
// polarity, not the build polarity. Set `false` to restore the legacy
|
|
736
736
|
// pool-only surface behaviour.
|
|
@@ -791,7 +791,7 @@ export const DEFAULT_CONFIG: Config = {
|
|
|
791
791
|
// (positive name, default-on).
|
|
792
792
|
freshWorktreeGate: true,
|
|
793
793
|
// The cross-job merge serialiser's CAS-retry cap — the git-alone FLOOR of the
|
|
794
|
-
// land-time cross-job queue (
|
|
794
|
+
// land-time cross-job queue (spec `land-time-reverify-and-parallel-merge-ceiling`,
|
|
795
795
|
// Story 5 + Applied Answer q1 (a)). Matches `integration-core.ts`'s built-in
|
|
796
796
|
// `DEFAULT_MERGE_RETRIES` fallback (1000 — the C2 large liveness ceiling, NOT a
|
|
797
797
|
// small Race-1 budget) so resolving it through this layer is byte-for-byte
|
|
@@ -800,7 +800,7 @@ export const DEFAULT_CONFIG: Config = {
|
|
|
800
800
|
mergeRetries: 1000,
|
|
801
801
|
// The strict-merge-approval gate defaults OFF (sidecar OQ6 / task
|
|
802
802
|
// `strict-merge-approval-gate`): the cheap "green re-verify is enough" path
|
|
803
|
-
// is the default; the OQ6
|
|
803
|
+
// is the default; the OQ6 SPEC answer pins this. A repo opts in to the
|
|
804
804
|
// host-agnostic "dismiss stale approvals on base change" discipline with
|
|
805
805
|
// `strictMergeApproval: true` (or `--strict-merge-approval` /
|
|
806
806
|
// `DORFL_STRICT_MERGE_APPROVAL=true`). The re-surface vs. land branch is
|
package/src/continue-branch.ts
CHANGED
|
@@ -156,7 +156,7 @@ export interface ContinueRebaseResult {
|
|
|
156
156
|
* (ADR §10: rebase, NOT merge — linear history; the prior attempt's commits were
|
|
157
157
|
* based on an OLD main that moved while the item sat in backlog).
|
|
158
158
|
*
|
|
159
|
-
* This is a PLAIN rebase. After the per-item-lock cut-over (
|
|
159
|
+
* This is a PLAIN rebase. After the per-item-lock cut-over (spec
|
|
160
160
|
* `ledger-status-per-item-lock-refs`, tasks 9a–9d) NO transient status lands on
|
|
161
161
|
* a work branch: claim does not move the body (it rests in `backlog/`),
|
|
162
162
|
* needs-attention is the lock `state: stuck` (not a `git mv`), and the
|
package/src/cwd-section.ts
CHANGED
|
@@ -268,7 +268,7 @@ export async function resolveCwdSection(
|
|
|
268
268
|
const localReport = scanRepoPaths([cwd], config, heldSlugs, options.override);
|
|
269
269
|
const repo = localReport.repos[0];
|
|
270
270
|
|
|
271
|
-
// 3b. The PER-ITEM LOCK in-flight SURFACE for the cwd (
|
|
271
|
+
// 3b. The PER-ITEM LOCK in-flight SURFACE for the cwd (spec
|
|
272
272
|
// `ledger-status-per-item-lock-refs` US #8). The subtraction above removes a
|
|
273
273
|
// held slug from the eligible `items[]` pool; on its OWN that leaves a
|
|
274
274
|
// held/stuck cwd item in a BLIND SPOT — gone from every bucket with nothing
|
package/src/decision-engine.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {extractJsonObjectSpan} from './verdict-json.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* **The SHARED decision engine** (
|
|
4
|
+
* **The SHARED decision engine** (spec
|
|
5
5
|
* `agentic-question-resolution-retire-disposition-vocabulary` US #9, decision 3 +
|
|
6
6
|
* 13/14; task `decision-engine-shared-decide-seam`): the GENERALISED
|
|
7
7
|
* `decide(input, allowedOutcomes) → verdict` core every question-resolution
|
|
@@ -20,7 +20,7 @@ import {extractJsonObjectSpan} from './verdict-json.js';
|
|
|
20
20
|
* "the INPUT adapter differs per front door and is NOT forced to be shared").
|
|
21
21
|
* - **the ALLOWED-OUTCOME SET** ({@link decide}'s `allowedOutcomes`): each caller
|
|
22
22
|
* passes the SUBSET of {@link DecisionOutcome} it permits — advance-apply allows
|
|
23
|
-
* `{task | prd | adr | delete | ask}`, intake keeps its own `{task |
|
|
23
|
+
* `{task | prd | adr | delete | ask}`, intake keeps its own `{task | spec | ask |
|
|
24
24
|
* bounce}` (intake is NOT refactored onto this engine here — decision 13). The
|
|
25
25
|
* engine never hard-codes which outcomes a caller permits; it only VALIDATES the
|
|
26
26
|
* returned verdict against the set and rejects (loudly) one outside it
|
|
@@ -51,7 +51,7 @@ import {extractJsonObjectSpan} from './verdict-json.js';
|
|
|
51
51
|
* No caller is forced to allow ALL of these: each passes its own SUBSET to
|
|
52
52
|
* {@link decide}. The engine is agnostic to which subset a caller permits.
|
|
53
53
|
*/
|
|
54
|
-
// MIGRATE step (
|
|
54
|
+
// MIGRATE step (spec `prd-to-spec-vocabulary-cutover-and-migration-command`): the
|
|
55
55
|
// parent-spec verdict outcome is `'spec'` (renamed from `'prd'`); the decider
|
|
56
56
|
// prompt emits it and the parser accepts it. This is a fresh per-call LLM verdict
|
|
57
57
|
// (nothing `'prd'`-valued is persisted), so the rename needs no on-disk alias.
|
package/src/do-autopick.ts
CHANGED
|
@@ -24,9 +24,9 @@ import type {ConfigOverrideMap} from './config-override.js';
|
|
|
24
24
|
* Auto-pick / `-n` draw from TWO POOLS ordered by the configurable
|
|
25
25
|
* `selectionOrder` (the shared, pure {@link selectPrioritised} helper): eligible
|
|
26
26
|
* TASKS (the `build` pool — the existing `scan`/`selectCandidates`/eligibility
|
|
27
|
-
* path) and TASKABLE prds (the `task` pool — built from the
|
|
27
|
+
* path) and TASKABLE prds (the `task` pool — built from the spec reader +
|
|
28
28
|
* `autoslice-gate`'s predicate), in the per-repo `selectionOrder` (default `drain`
|
|
29
|
-
* = tasks-first). A selected
|
|
29
|
+
* = tasks-first). A selected spec dispatches to the `do spec:<slug>` path (tasking
|
|
30
30
|
* itself is `autoslice-command`, not built here).
|
|
31
31
|
*
|
|
32
32
|
* Explicit multi-arg (`do <a> <b>`) bypasses the pools/priority entirely — the
|
|
@@ -41,7 +41,7 @@ type SharedDoOptions = Omit<DoOptions, 'arg'>;
|
|
|
41
41
|
|
|
42
42
|
export interface PerformDoMultiOptions extends SharedDoOptions {
|
|
43
43
|
/**
|
|
44
|
-
* The resolved repo config (provides `autoTask` for the
|
|
44
|
+
* The resolved repo config (provides `autoTask` for the spec gate,
|
|
45
45
|
* `selectionOrder` for the pool order, and the task-pool selection caps). The
|
|
46
46
|
* per-item runs still receive `autoTask`/`integration`/etc. via the spread
|
|
47
47
|
* `SharedDoOptions`.
|
|
@@ -62,7 +62,7 @@ export interface PerformDoMultiOptions extends SharedDoOptions {
|
|
|
62
62
|
count?: number;
|
|
63
63
|
/** Override the single-`do` runner (tests inject a stub). Defaults to {@link performDo}. */
|
|
64
64
|
run?: DoRunner;
|
|
65
|
-
/** Override the read seam (
|
|
65
|
+
/** Override the read seam (spec pool); defaults to the active {@link ledgerRead}. */
|
|
66
66
|
read?: LedgerReadStrategy;
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -85,7 +85,7 @@ export interface DoMultiResult {
|
|
|
85
85
|
* The task-pool caps for an in-place `do` selection. `do` is per-repo +
|
|
86
86
|
* sequential, so the REAL bound is the requested `count` (handled by the
|
|
87
87
|
* priority helper); the task-pool selection should not truncate BEFORE the
|
|
88
|
-
* count + the
|
|
88
|
+
* count + the spec pool are combined. We therefore cap the task pool at "all
|
|
89
89
|
* eligible" (a large bound) and let {@link selectPrioritised}'s `count` do the
|
|
90
90
|
* trimming across both pools.
|
|
91
91
|
*/
|
|
@@ -116,7 +116,7 @@ export async function performDoAuto(
|
|
|
116
116
|
options.override,
|
|
117
117
|
);
|
|
118
118
|
|
|
119
|
-
// Pool 2 — TASKABLE prds: the NEW pool from the shared
|
|
119
|
+
// Pool 2 — TASKABLE prds: the NEW pool from the shared spec read path
|
|
120
120
|
// (`resolveSpecPool`) filtered by `autoslice-gate`'s predicate (not reinvented).
|
|
121
121
|
const pool = read.resolveSpecPool({repoPath: cwd});
|
|
122
122
|
const specCandidates: SpecCandidate[] = pool.specs.map((spec) => ({
|
|
@@ -155,8 +155,8 @@ export async function performDoAuto(
|
|
|
155
155
|
/**
|
|
156
156
|
* Run the EXPLICIT multi-arg form (`do <a> <b> …`): the named items in the GIVEN
|
|
157
157
|
* order (no pool/priority — the operator chose them). Each arg is run through the
|
|
158
|
-
* existing `do` pipeline, which itself resolves bare/`task:`/`
|
|
159
|
-
*
|
|
158
|
+
* existing `do` pipeline, which itself resolves bare/`task:`/`spec:` (so a named
|
|
159
|
+
* spec dispatches to the tasking path and a collision errors), SEQUENTIALLY.
|
|
160
160
|
*/
|
|
161
161
|
export async function performDoArgs(
|
|
162
162
|
args: string[],
|
|
@@ -176,7 +176,7 @@ export async function performDoArgs(
|
|
|
176
176
|
/**
|
|
177
177
|
* Run a list of selected items through the existing `do` pipeline, SEQUENTIALLY,
|
|
178
178
|
* threading the shared options to each. For the pool path the `do` arg encodes
|
|
179
|
-
* the namespace (`
|
|
179
|
+
* the namespace (`spec:<slug>` for a selected spec, bare slug for a task); for the
|
|
180
180
|
* explicit-arg path the caller's raw arg is passed verbatim.
|
|
181
181
|
*/
|
|
182
182
|
async function runSelectedInSequence(
|