dorfl 0.1.0 → 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 +83 -77
- 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 +22 -22
- 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 +33 -39
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +18 -31
- 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/prd-to-spec.d.ts +15 -1
- package/dist/prd-to-spec.d.ts.map +1 -1
- package/dist/prd-to-spec.js +36 -14
- package/dist/prd-to-spec.js.map +1 -1
- package/dist/prompt.d.ts +24 -24
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +29 -31
- package/dist/prompt.js.map +1 -1
- package/dist/protocol/CLAIM-PROTOCOL.md +4 -4
- package/dist/protocol/REVIEW-PROTOCOL.md +1 -1
- package/dist/protocol/TASKING-PROTOCOL.md +12 -12
- package/dist/protocol/WORK-CONTRACT.md +39 -39
- package/dist/protocol/spec-template.md +1 -1
- package/dist/protocol/task-template.md +3 -3
- 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 +5 -5
- 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 +89 -88
- 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 +94 -84
- 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 +49 -49
- package/src/drop-source.ts +2 -2
- package/src/env-config.ts +8 -8
- package/src/format.ts +3 -3
- package/src/frontmatter.ts +42 -60
- 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/prd-to-spec.ts +51 -15
- package/src/prompt.ts +33 -35
- 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 +6 -6
- 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 +124 -123
- 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
package/src/repo-config.ts
CHANGED
|
@@ -61,16 +61,16 @@ export const REPO_CONFIG_FILENAME = brand.repoConfigFilename;
|
|
|
61
61
|
*/
|
|
62
62
|
export const REPO_ALLOWED_KEYS = [
|
|
63
63
|
'integration',
|
|
64
|
-
// `taskingIntegration` (the per-TRANSITION override for the
|
|
64
|
+
// `taskingIntegration` (the per-TRANSITION override for the spec→tasks TASKING
|
|
65
65
|
// transition ONLY) is a genuine repo property exactly like `integration`: whether
|
|
66
|
-
// THIS repo tasks a
|
|
66
|
+
// THIS repo tasks a spec straight onto `main` (task FILES land, no PR) while it
|
|
67
67
|
// still BUILDS each task as a reviewable PR is agreed by all collaborators +
|
|
68
68
|
// travels with the repo. Resolved per-repo through the SAME chain as
|
|
69
69
|
// `integration`, then falls back to `integration` when unset. DISTINCT from
|
|
70
70
|
// intake's per-EMITTED-TYPE `{task, prd}` resolver (front door, author-trust):
|
|
71
71
|
// this is a per-lifecycle-transition knob, inside the boundary, config-resolved.
|
|
72
72
|
'taskingIntegration',
|
|
73
|
-
// `tasksLandIn` (the per-repo TASK-PLACEMENT default — staging vs pool,
|
|
73
|
+
// `tasksLandIn` (the per-repo TASK-PLACEMENT default — staging vs pool, spec
|
|
74
74
|
// `staging-pool-position-gate-and-trust-model` US #5) is a genuine repo property
|
|
75
75
|
// exactly like `taskingIntegration`/`integration`: whether THIS repo's tasker
|
|
76
76
|
// output lands STAGED (`pre-backlog/`, review-without-PR human-promote path) or
|
|
@@ -91,7 +91,7 @@ export const REPO_ALLOWED_KEYS = [
|
|
|
91
91
|
// through the SAME chain as `tasksLandIn` (flag `--specs-land-in` > env
|
|
92
92
|
// `DORFL_SPECS_LAND_IN` > per-repo > global > built-in). Fed into the shared
|
|
93
93
|
// placement resolver as the configured-default rung for the spec lifecycle
|
|
94
|
-
// (`src/placement.ts`). The sole spec-placement key after the prd → spec HARD
|
|
94
|
+
// (`src/placement.ts`). The sole spec-placement key after the `prd` → `spec` HARD
|
|
95
95
|
// CUTOVER (the legacy `prdsLandIn` key is GONE — clean break, no accepted alias).
|
|
96
96
|
'specsLandIn',
|
|
97
97
|
// `noPR` (the PR-INTENT axis — push the branch but deliberately skip the PR) is
|
|
@@ -116,7 +116,7 @@ export const REPO_ALLOWED_KEYS = [
|
|
|
116
116
|
'autoBuild',
|
|
117
117
|
// `autoTask` (may an agent auto-task undeclared prds in this repo?) is a
|
|
118
118
|
// genuine repo property — the tasking-autonomy mirror of `autoBuild`
|
|
119
|
-
// (`work/
|
|
119
|
+
// (`work/specs/auto-task.md`), resolved per-repo through the same chain.
|
|
120
120
|
'autoTask',
|
|
121
121
|
// `observationTriage` (the 3-state `off|ask|auto` gate over the observation
|
|
122
122
|
// INBOX) is a genuine repo property — the observation-side question-surfacing
|
|
@@ -125,7 +125,7 @@ export const REPO_ALLOWED_KEYS = [
|
|
|
125
125
|
// boolean (no alias; no external users owed a migration window, 2026-06-12).
|
|
126
126
|
'observationTriage',
|
|
127
127
|
// `mergeQuestions` (the 3-state `off|ask|auto` gate over the MERGE-QUESTION
|
|
128
|
-
// SURFACER —
|
|
128
|
+
// SURFACER — spec `land-time-reverify-and-parallel-merge-ceiling` Story 17 /
|
|
129
129
|
// task `merge-questions-gate-axis`) is a genuine repo property exactly like
|
|
130
130
|
// `observationTriage`: whether THIS repo's unmerged `work/*` branches surface
|
|
131
131
|
// as merge-questions (and whether they auto-land) is agreed by all
|
|
@@ -136,13 +136,13 @@ export const REPO_ALLOWED_KEYS = [
|
|
|
136
136
|
// (flag > env > per-repo > global > default `ask`).
|
|
137
137
|
'mergeQuestions',
|
|
138
138
|
// `surfaceBlockers` (the BOOLEAN gate over DECLARED blocked work — whether a
|
|
139
|
-
// task/
|
|
139
|
+
// task/spec carrying `needsAnswers:true` is rendered into a question sidecar) is a
|
|
140
140
|
// genuine repo property — the blocked-work side of the question-surfacing gate
|
|
141
141
|
// family (ADR `ci-config-policy-and-gate-family`), the orthogonal peer of
|
|
142
142
|
// `observationTriage`, resolved per-repo through the same chain as `autoBuild`.
|
|
143
143
|
'surfaceBlockers',
|
|
144
144
|
// `surfaceStaging` (the BOOLEAN gate-family member that widens SURFACE into
|
|
145
|
-
// STAGING —
|
|
145
|
+
// STAGING — spec `staging-surface-and-apply-promote-safety` F2) is a genuine
|
|
146
146
|
// repo property exactly like its siblings (`surfaceBlockers`/`autoBuild`):
|
|
147
147
|
// whether THIS repo inspects staging for questions is agreed by all
|
|
148
148
|
// collaborators + travels with the repo. Default `true`; resolved per-repo
|
|
@@ -161,8 +161,8 @@ export const REPO_ALLOWED_KEYS = [
|
|
|
161
161
|
// (machine paths/commands), so they are rejected below.
|
|
162
162
|
'model',
|
|
163
163
|
'harness',
|
|
164
|
-
// Gate 2 (PR/code review) policy is a genuine repo property (GATES
|
|
165
|
-
// `work/
|
|
164
|
+
// Gate 2 (PR/code review) policy is a genuine repo property (GATES spec
|
|
165
|
+
// `work/specs/tasked/review.md`), resolved per-repo like `integration`/`autoBuild`:
|
|
166
166
|
// whether this repo runs Gate 2 (`review`), which model the review agent runs
|
|
167
167
|
// on (`reviewModel`), and the revise↔review loop bound (`reviewMaxRounds`).
|
|
168
168
|
// `reviewModel` is routing intent (not auth), so — like `model` — it is
|
|
@@ -185,7 +185,7 @@ export const REPO_ALLOWED_KEYS = [
|
|
|
185
185
|
// artifact (and pays the per-gate install cost) is agreed by all collaborators
|
|
186
186
|
// + travels with the repo. Resolved per-repo through the SAME chain.
|
|
187
187
|
'freshWorktreeGate',
|
|
188
|
-
// `mergeRetries` (the cross-job merge serialiser's CAS-retry cap —
|
|
188
|
+
// `mergeRetries` (the cross-job merge serialiser's CAS-retry cap — spec
|
|
189
189
|
// `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a))
|
|
190
190
|
// is a genuine repo property exactly like `freshWorktreeGate`: "how many
|
|
191
191
|
// re-rebase-and-retry attempts before a contender bounces to needs-attention"
|
|
@@ -195,7 +195,7 @@ export const REPO_ALLOWED_KEYS = [
|
|
|
195
195
|
// CAS still costs only a re-rebase + re-gate retry, never a `--force`.
|
|
196
196
|
'mergeRetries',
|
|
197
197
|
// `strictMergeApproval` (the OPT-IN strictness layered on the OQ6
|
|
198
|
-
// stale-approval default —
|
|
198
|
+
// stale-approval default — spec `land-time-reverify-and-parallel-merge-ceiling`
|
|
199
199
|
// sidecar OQ6 / task `strict-merge-approval-gate`) is a genuine repo property
|
|
200
200
|
// exactly like `mergeQuestions`/`mergeRetries`: whether THIS repo re-surfaces
|
|
201
201
|
// the merge-question on a merge-base change (the host-agnostic analogue of
|
package/src/review-gate.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {NullHarness, substituteModel, type Harness} from './harness.js';
|
|
2
2
|
import {launchWithOptionalWatch} from './agent-launch.js';
|
|
3
3
|
import {boundaryLine} from './watch-session.js';
|
|
4
|
+
import {workItemRel} from './work-layout.js';
|
|
4
5
|
import {
|
|
5
6
|
parseReviewVerdict,
|
|
6
7
|
ReviewParseError,
|
|
@@ -18,7 +19,7 @@ export {
|
|
|
18
19
|
} from './review-verdict.js';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
|
-
* **Gate 2 — the PR/code review gate** (GATES
|
|
22
|
+
* **Gate 2 — the PR/code review gate** (GATES spec `work/specs/tasked/review.md`), the
|
|
22
23
|
* JUDGEMENT layer that rides ON TOP of the deterministic `verify` floor (ADR §8).
|
|
23
24
|
*
|
|
24
25
|
* After the green `verify` and BEFORE the done-move, `complete`/`do` invoke the
|
|
@@ -110,7 +111,7 @@ export function buildReviewPrompt(slug: string): string {
|
|
|
110
111
|
return [
|
|
111
112
|
`You are a FRESH-CONTEXT reviewer (Gate 2 — PR/code review). Review the`,
|
|
112
113
|
`code changes on this work branch AGAINST the task that specified them`,
|
|
113
|
-
`(work/in-progress/${slug}.md or work/done/${slug}.md) and its source
|
|
114
|
+
`(work/in-progress/${slug}.md or work/done/${slug}.md) and its source spec.`,
|
|
114
115
|
``,
|
|
115
116
|
reviewDisciplinePrompt(),
|
|
116
117
|
``,
|
|
@@ -150,7 +151,7 @@ export function buildReviewPrompt(slug: string): string {
|
|
|
150
151
|
`comment on the PR — write it FOR a human landing there, NOT as scratch`,
|
|
151
152
|
`thinking. LEAD with the verdict ("Approved" or "Blocked") and then give the`,
|
|
152
153
|
`lenses' reasoning and the destination check ("merged as written, do we reach`,
|
|
153
|
-
`the task/
|
|
154
|
+
`the task/spec goal?"). Write it deliberately; do NOT narrate your process`,
|
|
154
155
|
`("Let me check…"). Keep it TIGHT: aim for a few short sentences and DO NOT`,
|
|
155
156
|
`exceed ~1500 characters — a long, multi-paragraph field is exactly what`,
|
|
156
157
|
`corrupts the JSON on large diffs; say less, not more. It is plain text inside`,
|
|
@@ -247,10 +248,10 @@ export function harnessReviewGate(
|
|
|
247
248
|
* Render the TASK-SET acceptance-gate PROMPT — the task-path mirror of
|
|
248
249
|
* {@link buildReviewPrompt} (task `slice-acceptance-gate`). Instead of
|
|
249
250
|
* reviewing a code diff against ONE task, this instructs a FRESH-CONTEXT
|
|
250
|
-
* agent to review the WHOLE candidate SET of tasks produced for
|
|
251
|
+
* agent to review the WHOLE candidate SET of tasks produced for spec `slug`,
|
|
251
252
|
* using the **review discipline**'s SET-OF-TASKS lens (coherence / dependency
|
|
252
253
|
* graph / gaps + overlap / "if every task is built exactly as written, do we
|
|
253
|
-
* reach the system the
|
|
254
|
+
* reach the system the spec describes, and is each task
|
|
254
255
|
* correct-if-implemented?"). It emits the SAME unified `ReviewVerdict` shape
|
|
255
256
|
* so {@link parseReviewVerdict} reads it identically.
|
|
256
257
|
*
|
|
@@ -265,24 +266,24 @@ export function harnessReviewGate(
|
|
|
265
266
|
export function buildTaskAcceptancePrompt(slug: string): string {
|
|
266
267
|
return [
|
|
267
268
|
`You are a FRESH-CONTEXT reviewer (the task-SET ACCEPTANCE GATE). Review`,
|
|
268
|
-
`the candidate tasks this tasking run produced for the
|
|
269
|
+
`the candidate tasks this tasking run produced for the spec "${slug}" — the`,
|
|
269
270
|
`new/changed candidate task files on this work branch — AGAINST their source`,
|
|
270
|
-
`
|
|
271
|
+
`spec (${workItemRel('specs-ready', `${slug}.md`)} — the held spec stays in specs/ready/ while it is being`,
|
|
271
272
|
`tasked).`,
|
|
272
273
|
``,
|
|
273
274
|
reviewDisciplinePrompt(),
|
|
274
275
|
``,
|
|
275
276
|
`Review the WHOLE SET as a SET, not each task in isolation. The set-level`,
|
|
276
277
|
`framings the review discipline names:`,
|
|
277
|
-
` - COHERENCE — do the tasks speak the
|
|
278
|
-
` consistently; no task re-means or forks a concept another task/the
|
|
278
|
+
` - COHERENCE — do the tasks speak the spec's (and the system's) language`,
|
|
279
|
+
` consistently; no task re-means or forks a concept another task/the spec`,
|
|
279
280
|
` already owns?`,
|
|
280
281
|
` - DEPENDENCY GRAPH — is the \`blockedBy\`/ordering graph sound (acyclic, the`,
|
|
281
282
|
` keystone first, each task's stated blockers really land its premise)?`,
|
|
282
|
-
` - GAPS + OVERLAP — does the set COVER the
|
|
283
|
+
` - GAPS + OVERLAP — does the set COVER the spec with no missing piece, and`,
|
|
283
284
|
` without two tasks doing the same work or fighting over the same seam?`,
|
|
284
285
|
` - CORRECT-IF-IMPLEMENTED — if EVERY task is built EXACTLY as written, do we`,
|
|
285
|
-
` reach the system the
|
|
286
|
+
` reach the system the spec describes, and is each task individually`,
|
|
286
287
|
` correct-if-implemented (no task that compiles but builds the wrong thing)?`,
|
|
287
288
|
``,
|
|
288
289
|
`This is a TERMINAL one-shot accept/reject gate: do NOT edit any task, do NOT`,
|
package/src/review-verdict.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (`work/protocol/REVIEW-PROTOCOL.md`, source-of-truth
|
|
5
5
|
* `skills/setup/protocol/REVIEW-PROTOCOL.md`).
|
|
6
6
|
*
|
|
7
|
-
* This is the keystone of the `runner-invoked-disciplines-into-protocol`
|
|
7
|
+
* This is the keystone of the `runner-invoked-disciplines-into-protocol` spec
|
|
8
8
|
* (task 1, D4): every runner-invoked review prompt builder
|
|
9
9
|
* ({@link buildReviewPrompt}, {@link buildTaskAcceptancePrompt} in
|
|
10
10
|
* `review-gate.ts`; {@link buildLoneTaskReviewPrompt} in `intake.ts`;
|
|
@@ -84,7 +84,7 @@ export interface ReviewVerdict {
|
|
|
84
84
|
questions?: string[];
|
|
85
85
|
/** For the tasker improver loop: specific tasks to emit `needsAnswers: true`. */
|
|
86
86
|
uncertainTasks?: UncertainTask[];
|
|
87
|
-
/** For the tasker improver loop: route the WHOLE
|
|
87
|
+
/** For the tasker improver loop: route the WHOLE spec to needs-attention. */
|
|
88
88
|
decompositionUnclear?: {questions: string[]};
|
|
89
89
|
}
|
|
90
90
|
|
package/src/run.ts
CHANGED
|
@@ -765,7 +765,7 @@ async function runOneItem(
|
|
|
765
765
|
}
|
|
766
766
|
|
|
767
767
|
// 3. Build the prompt — the SAME dual-use assembly `dorfl prompt`
|
|
768
|
-
// emits: the canonical wrapper (+ source
|
|
768
|
+
// emits: the canonical wrapper (+ source spec) + the task's ## Prompt.
|
|
769
769
|
let prompt: string;
|
|
770
770
|
try {
|
|
771
771
|
// CONTINUE-aware resolution: only on a continue (the job continued a kept
|
|
@@ -801,14 +801,14 @@ async function runOneItem(
|
|
|
801
801
|
})
|
|
802
802
|
: undefined;
|
|
803
803
|
// Thread the resolved per-repo nudge through the per-item override layer
|
|
804
|
-
// (a task or
|
|
804
|
+
// (a task or spec may pin `promptGuidance.testFirst` in its frontmatter,
|
|
805
805
|
// superseding the repo policy for THIS item) before the wrapper is built.
|
|
806
806
|
const itemGuidance = resolvePromptGuidanceForItem({
|
|
807
807
|
cwd: tree.dir,
|
|
808
808
|
repoResolved: resolvePromptGuidance(config),
|
|
809
809
|
taskContent: readFileSync(task.path, 'utf8'),
|
|
810
810
|
});
|
|
811
|
-
prompt = buildAgentPrompt(task.slug, task.
|
|
811
|
+
prompt = buildAgentPrompt(task.slug, task.spec, task.taskPrompt, {
|
|
812
812
|
cwd: tree.dir,
|
|
813
813
|
continueContext,
|
|
814
814
|
promptGuidance: itemGuidance,
|
|
@@ -879,7 +879,7 @@ async function runOneItem(
|
|
|
879
879
|
// 5–7 (CONVERGED). The whole gate → review → done-move → commit → rebase →
|
|
880
880
|
// integrate band — plus the needs-attention routing on any failure — now runs
|
|
881
881
|
// through the SHARED `performIntegration` core (`integration-core.ts`, the
|
|
882
|
-
// run/do convergence
|
|
882
|
+
// run/do convergence spec). `run` no longer forks its own gate / done-move /
|
|
883
883
|
// completion commit / `Integrator`+`integrateWithRebase`: that closed all
|
|
884
884
|
// three drift instances at once (the fleet now gets the review gate, the PR
|
|
885
885
|
// title/body, AND the per-repo language-agnostic `verify` gate instead of the
|
|
@@ -954,7 +954,7 @@ async function runOneItem(
|
|
|
954
954
|
// (`do`/`--isolated`/`--remote`/`complete`) already pass it unconditionally.
|
|
955
955
|
freshWorktreeGate: config.freshWorktreeGate,
|
|
956
956
|
// The cross-job merge-serialiser CAS-retry cap (config `mergeRetries`) —
|
|
957
|
-
// the git-alone FLOOR of the cross-job land queue (
|
|
957
|
+
// the git-alone FLOOR of the cross-job land queue (spec `land-time-reverify-
|
|
958
958
|
// and-parallel-merge-ceiling` Story 5 / Applied Answer q1 (a)). Threaded
|
|
959
959
|
// from the per-repo resolved config so a wide-matrix CI's raised cap actually
|
|
960
960
|
// reaches the merge loop — across separate `run` fleet jobs the CAS loop IS
|
|
@@ -1262,7 +1262,7 @@ export function defaultRunWorkspace(): string {
|
|
|
1262
1262
|
* One supervised TICK over the registry, as a swappable unit. Today the tick IS
|
|
1263
1263
|
* `runOnce` (claim+build+integrate a concurrent batch of eligible TASKS). The
|
|
1264
1264
|
* loop ({@link runLoop}) is deliberately written against this signature — NOT
|
|
1265
|
-
* against `runOnce` directly — so the advance-loop
|
|
1265
|
+
* against `runOnce` directly — so the advance-loop spec can later swap the tick
|
|
1266
1266
|
* (build / task / triage / surface / apply) WITHOUT re-architecting the loop
|
|
1267
1267
|
* (the forward-pointer: the loop owns concurrency/scheduling, the tick owns one
|
|
1268
1268
|
* item's work). The loop never reaches inside a tick.
|
package/src/scan.ts
CHANGED
|
@@ -53,7 +53,7 @@ export function lifecycleGatesFrom(config: {
|
|
|
53
53
|
surfaceBlockers: boolean;
|
|
54
54
|
/**
|
|
55
55
|
* Spec `staging-surface-and-apply-promote-safety` F2 — the gate that widens
|
|
56
|
-
* the SURFACE candidate set into STAGING (`tasks/backlog/` + `
|
|
56
|
+
* the SURFACE candidate set into STAGING (`tasks/backlog/` + `specs/proposed/`).
|
|
57
57
|
* Threaded here so the `scan --json` `lifecycle.surface[]` reflects the
|
|
58
58
|
* expanded pool and the CI matrix enumerates staging surface legs. BUILD/claim
|
|
59
59
|
* stays pool-only — only this lifecycle path widens.
|
|
@@ -78,7 +78,7 @@ export interface ScannedTriageItem {
|
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
80
|
* A surface/apply lifecycle item, with its namespace. SURFACE only ever carries
|
|
81
|
-
* `needsAnswers` task/
|
|
81
|
+
* `needsAnswers` task/spec items (an observation with no sidecar goes to `triage`,
|
|
82
82
|
* not `surface`). APPLY, however, ALSO carries an ANSWERED OBSERVATION: since the
|
|
83
83
|
* classifier (`buildLifecyclePools`) routes an observation whose sidecar is
|
|
84
84
|
* all-answered to `apply` (CONSUME, always-on), the projection MUST keep it here
|
|
@@ -108,7 +108,7 @@ export interface ScannedBlockedItem {
|
|
|
108
108
|
export interface ScannedLifecycle {
|
|
109
109
|
/** Untriaged observations → `obs:<slug>` legs (gated by `observationTriage`). */
|
|
110
110
|
triage: ScannedTriageItem[];
|
|
111
|
-
/** `needsAnswers` task/
|
|
111
|
+
/** `needsAnswers` task/spec items with no answered sidecar → surface legs (gated by `surfaceBlockers`). */
|
|
112
112
|
surface: ScannedBlockedItem[];
|
|
113
113
|
/**
|
|
114
114
|
* Items WITH an all-answered sidecar → apply legs (CONSUME, always-on). Carries
|
|
@@ -132,7 +132,7 @@ export interface ScannedItem extends ReadyItem {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
|
-
* A
|
|
135
|
+
* A SPEC entry in `scan --json`'s taskable-spec pool — the SAME shape an eligible
|
|
136
136
|
* task carries in `items[]` (a `slug` + an `eligibility.eligible` boolean), so
|
|
137
137
|
* the propose-matrix `jq` filter mirrors the task one: `select(.eligibility.eligible)
|
|
138
138
|
* | "spec:" + .slug`. "Eligible" here means TASKABLE — the per-repo `autoTask`
|
|
@@ -159,7 +159,7 @@ export interface RepoReport {
|
|
|
159
159
|
items: ScannedItem[];
|
|
160
160
|
/**
|
|
161
161
|
* The TASKABLE-SPEC pool for this repo (the `specs[]` companion of `items[]`):
|
|
162
|
-
* every spec in `work/
|
|
162
|
+
* every spec in `work/specs/ready/` not already in `work/specs/tasked/`, each tagged with
|
|
163
163
|
* `eligibility.eligible` from {@link taskableSpecs} (the SAME `autoslice-gate`
|
|
164
164
|
* predicate the mirror-side pool scan uses — NOT a forked predicate). This is
|
|
165
165
|
* what makes the propose-mode CI matrix enumerate `spec:<slug>` legs for ready
|
|
@@ -183,7 +183,7 @@ export interface RepoReport {
|
|
|
183
183
|
*/
|
|
184
184
|
lifecycle: ScannedLifecycle;
|
|
185
185
|
/**
|
|
186
|
-
* The one-slug-one-folder LINT result (
|
|
186
|
+
* The one-slug-one-folder LINT result (spec `ledger-integrity` story 3): any
|
|
187
187
|
* slug present in MORE THAN ONE `work/` status folder in THIS repo's ledger.
|
|
188
188
|
* Empty ⇒ a clean ledger. Non-empty ⇒ a corrupt ledger the formatter WARNS
|
|
189
189
|
* about loudly and a human must resolve (never auto-fixed). Derived by listing
|
|
@@ -191,7 +191,7 @@ export interface RepoReport {
|
|
|
191
191
|
*/
|
|
192
192
|
ledgerDuplicates: DuplicateSlug[];
|
|
193
193
|
/**
|
|
194
|
-
* The PER-ITEM LOCK in-flight view for this repo (
|
|
194
|
+
* The PER-ITEM LOCK in-flight view for this repo (spec
|
|
195
195
|
* `ledger-status-per-item-lock-refs` US #8; task
|
|
196
196
|
* `needs-attention-as-stuck-lock-state`): the held lock entries read from the
|
|
197
197
|
* repo's `refs/dorfl/lock/*` refs — `active` holds (in-progress) and
|
|
@@ -240,7 +240,7 @@ export function readReadyItems(repoPath: string): ReadyItem[] {
|
|
|
240
240
|
* through the EXACT same eligibility path as in-place (`do-autopick`), not a fork.
|
|
241
241
|
*/
|
|
242
242
|
/**
|
|
243
|
-
* Score a
|
|
243
|
+
* Score a spec pool down to its TASKABLE subset, then label every spec with
|
|
244
244
|
* `eligibility.eligible` (true ⇔ taskable). REUSES {@link taskableSpecs} —
|
|
245
245
|
* the SAME `autoslice-gate` predicate the mirror-side `scanMirrorPool` + the
|
|
246
246
|
* in-place `do-autopick` pool already run — so what is taskable does not
|
|
@@ -281,7 +281,7 @@ export function scoreSpecs(
|
|
|
281
281
|
*
|
|
282
282
|
* The pool items' `namespace` is the wider {@link SelectedNamespace}. SURFACE by
|
|
283
283
|
* construction only carries `'task'`/`'prd'` (an observation with no sidecar is a
|
|
284
|
-
* `triage` candidate, never `surface`), so it narrows + drops any non-task/
|
|
284
|
+
* `triage` candidate, never `surface`), so it narrows + drops any non-task/spec
|
|
285
285
|
* defensively. APPLY additionally admits `'observation'` (an answered observation
|
|
286
286
|
* sidecar → apply), and it MUST be kept so the matrix `jq` emits its
|
|
287
287
|
* `observation:<slug>` apply leg — narrowing it away here is exactly what stranded
|
|
@@ -324,7 +324,7 @@ export function scoreItems(
|
|
|
324
324
|
counts: {totalItems: number; totalEligible: number},
|
|
325
325
|
heldSlugs: Set<string> = new Set(),
|
|
326
326
|
): ScannedItem[] {
|
|
327
|
-
// HELD-SLUG SUBTRACTION (
|
|
327
|
+
// HELD-SLUG SUBTRACTION (spec `ledger-status-per-item-lock-refs` US #15; task
|
|
328
328
|
// `claim-acquires-unified-lock-no-body-move`): exclude any pool slug whose
|
|
329
329
|
// per-item lock is currently held — the eligible pool is "in `tasks/ready/` on
|
|
330
330
|
// `main` AND no lock held".
|
|
@@ -435,7 +435,7 @@ export async function scan(
|
|
|
435
435
|
// the lock refs from the mirror's origin; non-fatal (empty set on any fault),
|
|
436
436
|
// so the read-only scan degrades gracefully exactly as its config reads do.
|
|
437
437
|
const heldSlugs = await heldTaskSlugs(mirror.path, 'origin', options.env);
|
|
438
|
-
// The PER-ITEM LOCK in-flight view (
|
|
438
|
+
// The PER-ITEM LOCK in-flight view (spec US #8; task
|
|
439
439
|
// `needs-attention-as-stuck-lock-state`): ADDITIONALLY read the full held
|
|
440
440
|
// lock entries (action × state + reason) from the mirror's lock refs, so the
|
|
441
441
|
// scan surfaces held (in-progress) + stuck (needs-attention) items. Read from
|
|
@@ -448,7 +448,7 @@ export async function scan(
|
|
|
448
448
|
'origin',
|
|
449
449
|
options.env,
|
|
450
450
|
);
|
|
451
|
-
// Spec pool — the TASKABLE-
|
|
451
|
+
// Spec pool — the TASKABLE-SPEC companion of the task pool above
|
|
452
452
|
// (`ci-propose-matrix-must-enumerate-sliceable-prds-not-only-slices`). Resolve
|
|
453
453
|
// `autoTask` PER REPO from the mirror's COMMITTED `.dorfl.json`
|
|
454
454
|
// (exactly as the mirror-side pool scan does — NOT forked); a read fault is
|
|
@@ -508,7 +508,7 @@ export async function scan(
|
|
|
508
508
|
env: options.env,
|
|
509
509
|
}),
|
|
510
510
|
);
|
|
511
|
-
// The one-slug-one-folder LINT (
|
|
511
|
+
// The one-slug-one-folder LINT (spec story 3): derive any slug residing in >1
|
|
512
512
|
// status folder from the mirror's committed `main` tree (the SAME `ls-tree`
|
|
513
513
|
// read the seam uses), so a corrupt ledger is surfaced LOUDLY by the formatter.
|
|
514
514
|
const ledgerDuplicates = lintRefLedger('main', mirror.path, options.env);
|
|
@@ -543,7 +543,7 @@ export function scanRepoPaths(
|
|
|
543
543
|
repoPaths: string[],
|
|
544
544
|
config: Config,
|
|
545
545
|
/**
|
|
546
|
-
* The HELD-SLUG set to SUBTRACT from each repo's pool (`tasks/ready/`) (
|
|
546
|
+
* The HELD-SLUG set to SUBTRACT from each repo's pool (`tasks/ready/`) (spec
|
|
547
547
|
* `ledger-status-per-item-lock-refs` US #15). This is a WORKING-TREE, OFFLINE
|
|
548
548
|
* scan (it has no arbiter handle to fetch the lock refs from — that is the
|
|
549
549
|
* registry `scan`'s job), so the held set is supplied by the in-place CALLER
|
|
@@ -569,7 +569,7 @@ export function scanRepoPaths(
|
|
|
569
569
|
global: config,
|
|
570
570
|
override,
|
|
571
571
|
}).config;
|
|
572
|
-
// Spec pool — the TASKABLE-
|
|
572
|
+
// Spec pool — the TASKABLE-SPEC companion of the task pool. Resolve
|
|
573
573
|
// `autoTask` PER REPO from the working-tree `.dorfl.json` (the same
|
|
574
574
|
// way `autoBuild` is resolved); `taskableSpecs` (the SAME `autoslice-gate`
|
|
575
575
|
// predicate the autopick paths run) decides what is taskable — no forked
|
package/src/select-order.ts
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* member of this union and naming it is a usage error.
|
|
29
29
|
*
|
|
30
30
|
* - `build` — build an eligible task;
|
|
31
|
-
* - `task` — task a taskable
|
|
31
|
+
* - `task` — task a taskable spec;
|
|
32
32
|
* - `surface` — render a `needsAnswers` blocker into an answerable sidecar;
|
|
33
33
|
* - `triage` — triage an untriaged observation.
|
|
34
34
|
*/
|
package/src/select-priority.ts
CHANGED
|
@@ -30,16 +30,16 @@ import {
|
|
|
30
30
|
* land). Build it standalone; do not assume `run` already calls it.
|
|
31
31
|
*
|
|
32
32
|
* **Up to FIVE pools.** The `scan`/`selectCandidates`/eligibility model is
|
|
33
|
-
* TASK-ONLY (there is no
|
|
33
|
+
* TASK-ONLY (there is no spec candidate). So this helper composes:
|
|
34
34
|
*
|
|
35
35
|
* - the **`build` pool** (eligible TASKS) — the EXISTING {@link selectCandidates}
|
|
36
36
|
* path (round-robin across repos, capped). This is the EXACT task-selection
|
|
37
37
|
* primitive `run` uses, so `run` and this helper SHARE it (they share
|
|
38
38
|
* `selectCandidates`, the task-pool core).
|
|
39
|
-
* - the **`task` pool** (
|
|
39
|
+
* - the **`task` pool** (spec-to-task) — a pool the caller builds from the spec reader
|
|
40
40
|
* (`ledgerRead.resolveSpecPool`) filtered by `autoslice-gate`'s pure predicate
|
|
41
41
|
* ({@link resolveTaskingEligibility}); see {@link taskableSpecs}. The helper
|
|
42
|
-
* does NOT reinvent
|
|
42
|
+
* does NOT reinvent spec eligibility.
|
|
43
43
|
*
|
|
44
44
|
* `do` is STRICTLY SEQUENTIAL (parallelism is `run`'s job, ADR §3) — this helper
|
|
45
45
|
* only ORDERS + COUNTS the items; the caller runs the existing `do` pipeline per
|
|
@@ -82,7 +82,7 @@ export interface SelectedItem {
|
|
|
82
82
|
*/
|
|
83
83
|
export type LifecycleSelectedItem = SelectedItem;
|
|
84
84
|
|
|
85
|
-
/** A
|
|
85
|
+
/** A spec candidate for the tasking pool, before the eligibility gate runs. */
|
|
86
86
|
export interface SpecCandidate {
|
|
87
87
|
repoPath: string;
|
|
88
88
|
slug: string;
|
|
@@ -91,21 +91,21 @@ export interface SpecCandidate {
|
|
|
91
91
|
taskedAfter: string[];
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
/** Inputs to {@link taskableSpecs}: the raw
|
|
94
|
+
/** Inputs to {@link taskableSpecs}: the raw spec pool + the gate context. */
|
|
95
95
|
export interface TaskableSpecsInput {
|
|
96
|
-
/** Every
|
|
96
|
+
/** Every spec enumerated from `work/specs/ready/` (the auto-task candidate source). */
|
|
97
97
|
candidates: SpecCandidate[];
|
|
98
|
-
/** Slugs whose
|
|
98
|
+
/** Slugs whose spec resides in `work/specs/tasked/` (resolves `taskedAfter`). */
|
|
99
99
|
taskedSlugs: Set<string>;
|
|
100
100
|
/** The repo's resolved `autoTask` policy (`autoslice-gate`'s per-repo key). */
|
|
101
101
|
autoTask: boolean;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* Filter a raw
|
|
105
|
+
* Filter a raw spec pool down to the TASKABLE prds, in declaration order, using
|
|
106
106
|
* `autoslice-gate`'s pure predicate ({@link resolveTaskingEligibility}) — NOT a
|
|
107
|
-
* reinvented eligibility model. A
|
|
108
|
-
* humanOnly !== true && autoTask` AND every `taskedAfter`
|
|
107
|
+
* reinvented eligibility model. A spec is taskable iff `needsAnswers !== true &&
|
|
108
|
+
* humanOnly !== true && autoTask` AND every `taskedAfter` spec is already tasked.
|
|
109
109
|
* Pure: no I/O (the caller reads the pool through `ledgerRead.resolveSpecPool`).
|
|
110
110
|
*/
|
|
111
111
|
export function taskableSpecs(input: TaskableSpecsInput): SpecCandidate[] {
|
|
@@ -171,7 +171,7 @@ export interface SelectPrioritisedInput {
|
|
|
171
171
|
*/
|
|
172
172
|
lifecycle?: SelectedLifecyclePools;
|
|
173
173
|
/**
|
|
174
|
-
* The HELD-SLUG set to SUBTRACT from the `build` pool (eligible TASKS) —
|
|
174
|
+
* The HELD-SLUG set to SUBTRACT from the `build` pool (eligible TASKS) — spec
|
|
175
175
|
* `ledger-status-per-item-lock-refs` US #15, task
|
|
176
176
|
* `claim-acquires-unified-lock-no-body-move`. A task whose per-item lock is
|
|
177
177
|
* currently held is dropped from selection, so the eligible pool is "in
|
|
@@ -198,7 +198,7 @@ export interface SelectedLifecyclePools {
|
|
|
198
198
|
* Build the ordered, counted list of items to do across the (up to) FIVE pools,
|
|
199
199
|
* applying the configurable {@link selectionOrder} with `apply` PINNED FIRST and
|
|
200
200
|
* the count bound. The task pool is selected via the EXISTING
|
|
201
|
-
* {@link selectCandidates} (the shared primitive `run` uses); the
|
|
201
|
+
* {@link selectCandidates} (the shared primitive `run` uses); the spec pool is the
|
|
202
202
|
* pre-filtered {@link taskableSpecs} output; the lifecycle pools (`apply` /
|
|
203
203
|
* `surface` / `triage`) are caller-built (none for `do`).
|
|
204
204
|
*
|
|
@@ -235,7 +235,7 @@ export function selectPrioritised(
|
|
|
235
235
|
|
|
236
236
|
// The per-pool item lists, keyed by the orderable pool name. NOTE the
|
|
237
237
|
// vocabulary bridge: `build` = the eligible-TASK pool (namespace `task`),
|
|
238
|
-
// `task` = the taskable-
|
|
238
|
+
// `task` = the taskable-spec pool (namespace `prd`) — the action names, not the
|
|
239
239
|
// item namespaces (task `advance-selection-order-config`).
|
|
240
240
|
const byPool: Record<SelectionPool, SelectedItem[]> = {
|
|
241
241
|
build: buildItems,
|
package/src/sidecar.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {parseSlugArg, type SlugNamespace} from './slug-namespace.js';
|
|
|
2
2
|
import {workItemRel} from './work-layout.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* The **question/answer SIDECAR contract** (
|
|
5
|
+
* The **question/answer SIDECAR contract** (spec `advance-loop`, task
|
|
6
6
|
* `advance-sidecar-contract`) — the one genuinely-new piece of the `advance`
|
|
7
7
|
* family. A strict, tooling-OWNED per-item file `work/questions/<type>-<slug>.md`
|
|
8
8
|
* carrying per-entry answered-state, so the tooling fully owns the Q&A artifact
|
|
@@ -208,7 +208,7 @@ function typeForNamespace(
|
|
|
208
208
|
if (explicit === 'task') {
|
|
209
209
|
return 'task';
|
|
210
210
|
}
|
|
211
|
-
// `parseSlugArg` only knows `task:`/`
|
|
211
|
+
// `parseSlugArg` only knows `task:`/`spec:`; the sidecar adds the
|
|
212
212
|
// `observation:` namespace (`obs:` is the CLI alias the verb resolves; the
|
|
213
213
|
// sidecar stores the canonical `observation`). A bare slug (no prefix)
|
|
214
214
|
// defaults to the task namespace, matching the resolver's "bare = task".
|
|
@@ -267,7 +267,7 @@ export function sidecarPathFor(identity: string): string {
|
|
|
267
267
|
* canonical {@link sidecarPathFor} path FIRST, then any legacy-data fallback that
|
|
268
268
|
* may still be on disk before the migration command converts it.
|
|
269
269
|
*
|
|
270
|
-
* MIGRATE step (
|
|
270
|
+
* MIGRATE step (spec `prd-to-spec-vocabulary-cutover-and-migration-command`): the
|
|
271
271
|
* producer side now emits `spec:<slug>`, so {@link sidecarPathFor} resolves
|
|
272
272
|
* `work/questions/spec-<slug>.md`. But the ON-DISK sidecar is still the legacy
|
|
273
273
|
* `work/questions/prd-<slug>.md` until `dorfl prd-to-spec` renames the DATA. So a
|
package/src/slug-namespace.ts
CHANGED
|
@@ -263,7 +263,7 @@ export function resolveSlug(input: ResolveSlugInput): ResolvedSlug {
|
|
|
263
263
|
const parsed = parseSlugArg(input.arg);
|
|
264
264
|
|
|
265
265
|
if (parsed.explicit === 'observation') {
|
|
266
|
-
// `do` spans the task/
|
|
266
|
+
// `do` spans the task/spec namespaces ONLY (build a task OR task a spec).
|
|
267
267
|
// The `observation` namespace is `advance`'s alone (triage). Reject it here
|
|
268
268
|
// rather than let a `do obs:<slug>` resolve into a namespace `do` cannot act
|
|
269
269
|
// on — point the human at the verb that owns it.
|
|
@@ -289,7 +289,7 @@ export function resolveSlug(input: ResolveSlugInput): ResolvedSlug {
|
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
/**
|
|
292
|
-
* Resolve a slug argument for the `advance` verb (
|
|
292
|
+
* Resolve a slug argument for the `advance` verb (spec `advance-loop`, task
|
|
293
293
|
* `advance-verb-resolver`). `advance` is the SIBLING top-level verb (NOT a `do`
|
|
294
294
|
* subcommand) that reuses this SAME shared `prefix:arg` resolver, EXTENDED with
|
|
295
295
|
* the `observation` namespace `do` does not span:
|
|
@@ -362,6 +362,6 @@ export function resolveTaskOnlyArg(arg: string): string {
|
|
|
362
362
|
);
|
|
363
363
|
}
|
|
364
364
|
// Bare or `task:` → the task slug. (A bare slug on a task-only command is
|
|
365
|
-
// unambiguously the task; the
|
|
365
|
+
// unambiguously the task; the spec namespace is unreachable here.)
|
|
366
366
|
return parsed.slug;
|
|
367
367
|
}
|
package/src/spec-complete.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from './work-layout.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* The read-only **"is this spec complete?"** core query (
|
|
13
|
+
* The read-only **"is this spec complete?"** core query (spec `issue-intake`, US #8 —
|
|
14
14
|
* the closure-linkage half). Given a spec slug + a `work/` tree, a spec is COMPLETE
|
|
15
15
|
* iff there is **≥1 task carrying `spec:<slug>`** AND **all such tasks reside in
|
|
16
16
|
* `work/done/`**. Pure `work/`-folder logic — no seam, no git, no `gh`, no mutation.
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
* means the spec is not yet complete.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
/** The task lifecycle folders a `
|
|
35
|
+
/** The task lifecycle folders a `spec:<slug>` task can reside in. */
|
|
36
36
|
const TASK_FOLDERS = TASK_LIFECYCLE_FOLDERS;
|
|
37
37
|
|
|
38
38
|
/** Where a task resides — the folder name under `work/`. */
|
package/src/start.ts
CHANGED
|
@@ -78,7 +78,7 @@ export interface StartOptions {
|
|
|
78
78
|
*/
|
|
79
79
|
override?: boolean;
|
|
80
80
|
/**
|
|
81
|
-
* `--allow-backlog` (
|
|
81
|
+
* `--allow-backlog` (spec
|
|
82
82
|
* `do-allow-backlog-drive-staged-tasks-without-promotion`): recognise a
|
|
83
83
|
* `tasks/backlog/`-resident body (staging) as a valid start/onboard residence,
|
|
84
84
|
* so the no-checkout `do --remote/--isolated … --allow-backlog` flow (which
|
|
@@ -236,7 +236,7 @@ async function runStart(
|
|
|
236
236
|
* resume the lock `stuck → active`, onboard).
|
|
237
237
|
* Everything else dispatches by folder unchanged.
|
|
238
238
|
*
|
|
239
|
-
* Under `--allow-backlog` (
|
|
239
|
+
* Under `--allow-backlog` (spec
|
|
240
240
|
* `do-allow-backlog-drive-staged-tasks-without-promotion`) a body resting in
|
|
241
241
|
* `tasks/backlog/` (staging) is treated EXACTLY like the pool for this re-key
|
|
242
242
|
* (held active ⇒ in-progress; held stuck ⇒ needs-attention; else the backlog
|
|
@@ -620,7 +620,7 @@ async function switchToWorkBranch(params: {
|
|
|
620
620
|
}): Promise<SwitchResult> {
|
|
621
621
|
const {slug, arbiter, cwd, env, note} = params;
|
|
622
622
|
// `start` is a TASK-only command: the branch is the task-namespaced
|
|
623
|
-
// `work/task-<slug>` (distinct from a same-slug
|
|
623
|
+
// `work/task-<slug>` (distinct from a same-slug spec-tasking branch).
|
|
624
624
|
const branch = workBranchRef('task', slug);
|
|
625
625
|
|
|
626
626
|
await gitHard(['fetch', '--quiet', arbiter], cwd, env);
|
|
@@ -909,7 +909,7 @@ async function inferSlugFromBranch(
|
|
|
909
909
|
|
|
910
910
|
/**
|
|
911
911
|
* Which work/ folder the slug currently lives in on `<arbiter>/main`. Under
|
|
912
|
-
* `--allow-backlog` (
|
|
912
|
+
* `--allow-backlog` (spec `do-allow-backlog-drive-staged-tasks-without-promotion`)
|
|
913
913
|
* it ALSO recognises `tasks/backlog/` (staging) at LOWEST priority — after the
|
|
914
914
|
* pool — so a same-slug pool copy still wins; otherwise staging is invisible.
|
|
915
915
|
*/
|
package/src/status.ts
CHANGED
|
@@ -81,7 +81,7 @@ export interface JobStatus {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* One repo's PER-ITEM LOCK refs, surfaced for the dashboard (
|
|
84
|
+
* One repo's PER-ITEM LOCK refs, surfaced for the dashboard (spec
|
|
85
85
|
* `ledger-status-per-item-lock-refs` US #8; task
|
|
86
86
|
* `needs-attention-as-stuck-lock-state`). The in-flight view read from the lock
|
|
87
87
|
* refs — held (`active` = in-progress) and stuck (`needs-attention`) entries +
|
|
@@ -111,7 +111,7 @@ export interface StatusReport {
|
|
|
111
111
|
/** Stuck (needs-attention), crashed (running-but-dead), or un-reaped (done) jobs. */
|
|
112
112
|
attention: JobStatus[];
|
|
113
113
|
/**
|
|
114
|
-
* The PER-ITEM LOCK in-flight view (
|
|
114
|
+
* The PER-ITEM LOCK in-flight view (spec `ledger-status-per-item-lock-refs` US
|
|
115
115
|
* #8; task `needs-attention-as-stuck-lock-state`): per registered hub mirror,
|
|
116
116
|
* the held lock entries read from the mirror's `refs/dorfl/lock/*` refs —
|
|
117
117
|
* `active` holds (in-progress) and `stuck` holds (needs-attention) + reasons.
|
|
@@ -124,7 +124,7 @@ export interface StatusReport {
|
|
|
124
124
|
*/
|
|
125
125
|
lockHeld?: RepoLockEntries[];
|
|
126
126
|
/**
|
|
127
|
-
* The one-slug-one-folder LINT (
|
|
127
|
+
* The one-slug-one-folder LINT (spec `ledger-integrity` story 3): per registered
|
|
128
128
|
* hub mirror, any slug present in MORE THAN ONE `work/` status folder (a corrupt
|
|
129
129
|
* ledger). Read from the mirror's bare `main` ref (the SAME `ls-tree` source the
|
|
130
130
|
* needs-attention surface uses). Only repos WITH a duplicate appear. `status`
|
|
@@ -235,7 +235,7 @@ export async function status(options: StatusOptions): Promise<StatusReport> {
|
|
|
235
235
|
// reflects the remote truth. Never fatal — a failed fetch WARNS and falls back
|
|
236
236
|
// to the mirror's last-known `main`.
|
|
237
237
|
fetchMirrorMainOrWarn({mirrorPath, warn: options.warn, env: options.env});
|
|
238
|
-
// The PER-ITEM LOCK in-flight view (
|
|
238
|
+
// The PER-ITEM LOCK in-flight view (spec US #8): read the mirror's lock refs to
|
|
239
239
|
// surface held (`active` = in-progress) and stuck (`needs-attention`) entries +
|
|
240
240
|
// reasons/questions. A bare hub mirror's arbiter is its `origin` (the SAME
|
|
241
241
|
// handle the `scan` held-slug subtraction reads). Best-effort: a fetch/read
|
|
@@ -249,7 +249,7 @@ export async function status(options: StatusOptions): Promise<StatusReport> {
|
|
|
249
249
|
if (entries.length > 0) {
|
|
250
250
|
lockHeld.push({repoPath: mirrorPath, entries});
|
|
251
251
|
}
|
|
252
|
-
// The one-slug-one-folder LINT (
|
|
252
|
+
// The one-slug-one-folder LINT (spec story 3): derive any slug residing in >1
|
|
253
253
|
// status folder from the SAME freshly-fetched `main` ref, surfaced LOUDLY.
|
|
254
254
|
const dups = lintRefLedger('main', mirrorPath, options.env);
|
|
255
255
|
if (dups.length > 0) {
|
|
@@ -359,7 +359,7 @@ export function formatStatus(report: StatusReport): string {
|
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
// The PER-ITEM LOCK in-flight view (
|
|
362
|
+
// The PER-ITEM LOCK in-flight view (spec US #8; task
|
|
363
363
|
// `cutover-needs-attention-becomes-lock-stuck-recovery-surface`): the held lock
|
|
364
364
|
// refs read from each mirror — `active` holds (in-progress) and `stuck` holds
|
|
365
365
|
// (needs-attention) + their reasons/questions. This is the SOLE stuck-state
|
|
@@ -377,7 +377,7 @@ export function formatStatus(report: StatusReport): string {
|
|
|
377
377
|
}
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
-
// The one-slug-one-folder LINT (
|
|
380
|
+
// The one-slug-one-folder LINT (spec `ledger-integrity` story 3): WARN LOUDLY
|
|
381
381
|
// about every slug residing in >1 status folder of a registered mirror's ledger
|
|
382
382
|
// (a corrupt ledger — never a silent pass). A human must resolve each.
|
|
383
383
|
if (dupCount > 0) {
|