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/intake.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'node:fs';
|
|
2
2
|
import {dirname, join} from 'node:path';
|
|
3
3
|
import {runAsync, type RunResult} from './git.js';
|
|
4
|
-
import {workFolderRel, workItemRel} from './work-layout.js';
|
|
4
|
+
import {workFolderRel, workFolderPrefix, workItemRel} from './work-layout.js';
|
|
5
5
|
import {paramCase} from './brand.js';
|
|
6
6
|
import {
|
|
7
7
|
performIntegration,
|
|
@@ -48,7 +48,7 @@ import {triageIntake, type IntakeTriageDecision} from './intake-triage.js';
|
|
|
48
48
|
import {renderTaskBody, renderSpecBody} from './buildable-body.js';
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* **`intake <N>`** (
|
|
51
|
+
* **`intake <N>`** (spec `issue-intake`, task `intake-tracer-slice-outcome`): the
|
|
52
52
|
* KEYSTONE of the issue front-door. A new, GATE-FREE command — explicit invocation
|
|
53
53
|
* IS the authorization (precedent: `explicit-do-prd-not-gated-by-autoslice`), so
|
|
54
54
|
* `autoTask`/`autoBuild` config does NOT apply — that reads a GitHub issue + its
|
|
@@ -62,24 +62,24 @@ import {renderTaskBody, renderSpecBody} from './buildable-body.js';
|
|
|
62
62
|
* prompt's JUDGEMENT is NOT unit-tested (like the review prompt's is not); only the
|
|
63
63
|
* dispatch is.
|
|
64
64
|
*
|
|
65
|
-
* The dispatcher implements the FULL four-outcome decision table (
|
|
65
|
+
* The dispatcher implements the FULL four-outcome decision table (spec
|
|
66
66
|
* `issue-intake` — the source of truth):
|
|
67
67
|
* - **ASK** (not clear enough to act on): `postIssueComment` the next clarifying
|
|
68
68
|
* question; emit NOTHING; STOP.
|
|
69
69
|
* - **TASK** (clear AND fits ONE tracer-bullet task): write
|
|
70
|
-
* `work/backlog/<slug>.md` (`covers: []`, NO `
|
|
70
|
+
* `work/backlog/<slug>.md` (`covers: []`, NO `spec:`) carrying `issue: N` (the
|
|
71
71
|
* lone-task closure link, NOT `Fixes #N`), integrate via {@link
|
|
72
72
|
* performIntegration} (default `propose`).
|
|
73
|
-
* - **
|
|
74
|
-
* which is NEVER bounced): write the
|
|
75
|
-
* axes the verdict carried), integrate, STOP (tasking is the separate `do
|
|
73
|
+
* - **SPEC** (clear AND coherent but >1 task — INCLUDING a coupled-but-SMALL pair,
|
|
74
|
+
* which is NEVER bounced): write the spec file (`work/specs/ready/<slug>.md`) with `issue: N` (+ the gate
|
|
75
|
+
* axes the verdict carried), integrate, STOP (tasking is the separate `do spec:`
|
|
76
76
|
* step).
|
|
77
77
|
* - **BOUNCE** (genuinely UNRELATED concerns — no shared vision): the bounce is
|
|
78
78
|
* TERMINAL (the asks are unrelated and must be re-filed), so intake CLOSES the
|
|
79
79
|
* issue ATOMICALLY — the "file separate issues" text as the closing comment +
|
|
80
80
|
* `reason: not planned` (the honest GitHub-native signal) in ONE `closeIssue`
|
|
81
81
|
* call; emit NOTHING. Intake closes on BOUNCE (as not planned); NEVER on
|
|
82
|
-
* task/
|
|
82
|
+
* task/spec (CI's close-job closes those via the `issue:` field) / ask.
|
|
83
83
|
*
|
|
84
84
|
* The per-outcome integration KNOBS, the processing LOCK, and event-classification
|
|
85
85
|
* are LATER tasks and are NOT built here (default `propose` is fine here).
|
|
@@ -92,7 +92,7 @@ import {renderTaskBody, renderSpecBody} from './buildable-body.js';
|
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* The four outcomes the decision prompt classifies an issue into (the decision
|
|
95
|
-
* table). EXPAND step (
|
|
95
|
+
* table). EXPAND step (spec
|
|
96
96
|
* `prd-to-spec-vocabulary-cutover-and-migration-command`): the `spec` outcome
|
|
97
97
|
* names the "clear + coherent but >1 task" classification (a parent SPEC). HARD
|
|
98
98
|
* CUTOVER (contract step): the legacy `prd` outcome token is GONE — the prompt
|
|
@@ -122,7 +122,7 @@ export interface IntakeVerdict {
|
|
|
122
122
|
/**
|
|
123
123
|
* The drafted task BODY (`task` outcome) — the markdown AFTER the frontmatter
|
|
124
124
|
* (the `## What to build` / `## Acceptance criteria` / `## Prompt` sections). The
|
|
125
|
-
* dispatcher writes the frontmatter (slug/title/`covers: []`, NO `
|
|
125
|
+
* dispatcher writes the frontmatter (slug/title/`covers: []`, NO `spec:`) carrying
|
|
126
126
|
* the lone-task `issue: N` closure link itself; the agent never writes
|
|
127
127
|
* git-visible files.
|
|
128
128
|
*/
|
|
@@ -151,7 +151,7 @@ export interface IntakeVerdict {
|
|
|
151
151
|
specBody?: string;
|
|
152
152
|
/**
|
|
153
153
|
* The spec's gate axes (`spec` outcome) AS THE PROMPT JUDGED THEM — surfaced onto
|
|
154
|
-
* the emitted spec frontmatter (
|
|
154
|
+
* the emitted spec frontmatter (spec `issue-intake` US #8: "the emitted artifact
|
|
155
155
|
* carries … its own gate axes"). Both omitted (undeclared) by default; the prompt
|
|
156
156
|
* sets `specHumanOnly: true` when a human should drive the TASKING and/or
|
|
157
157
|
* `specNeedsAnswers: true` when open questions remain.
|
|
@@ -186,16 +186,16 @@ export interface IntakeResult {
|
|
|
186
186
|
outcome: IntakeRunOutcome;
|
|
187
187
|
/** The issue number acted on. */
|
|
188
188
|
issueNumber: number;
|
|
189
|
-
/** The slug of the emitted artifact (task OR
|
|
189
|
+
/** The slug of the emitted artifact (task OR spec outcome). */
|
|
190
190
|
emittedSlug?: string;
|
|
191
|
-
/** Repo-relative path of the emitted artifact (task OR
|
|
191
|
+
/** Repo-relative path of the emitted artifact (task OR spec outcome). */
|
|
192
192
|
emitted?: string;
|
|
193
193
|
/** True iff a comment was posted on the issue (ask / bounce outcomes). */
|
|
194
194
|
commented?: boolean;
|
|
195
195
|
/**
|
|
196
196
|
* True iff the ISSUE was closed (the BOUNCE outcome — a terminal bounce closes
|
|
197
197
|
* the issue atomically as `not planned`). Additive (mirrors {@link commented}),
|
|
198
|
-
* so CI / callers can observe the close. Never set on ask/task/
|
|
198
|
+
* so CI / callers can observe the close. Never set on ask/task/spec.
|
|
199
199
|
*/
|
|
200
200
|
closed?: boolean;
|
|
201
201
|
/** Human-readable summary of the terminal condition. */
|
|
@@ -253,10 +253,10 @@ export interface PerformIntakeOptions {
|
|
|
253
253
|
/** The HOST-ONLY sessions root for the pi session file. */
|
|
254
254
|
sessionsDir?: string;
|
|
255
255
|
/**
|
|
256
|
-
* The PER-OUTCOME integration modes (
|
|
256
|
+
* The PER-OUTCOME integration modes (spec `issue-intake` US #9) the emitted artifact integrates
|
|
257
257
|
* THROUGH the shared core with. Because `intake` decides the artifact TYPE at
|
|
258
258
|
* RUNTIME, the mode is keyed per type: an emitted task integrates with
|
|
259
|
-
* `integration.task`, an emitted
|
|
259
|
+
* `integration.task`, an emitted spec with `integration.prd` (`propose` =
|
|
260
260
|
* push the `work/<slug>` branch + open a PR, NO `main` touch; `merge` = land on
|
|
261
261
|
* `main`). The CLI resolves this from the granular + aggregate flags via
|
|
262
262
|
* {@link resolveIntakeIntegrationModes}; ask/bounce emit nothing, so the modes
|
|
@@ -266,7 +266,7 @@ export interface PerformIntakeOptions {
|
|
|
266
266
|
/**
|
|
267
267
|
* **The ORIGIN-TRUST verdict, passed IN** (task
|
|
268
268
|
* `untrusted-origin-forces-build-propose`; the `--origin-trust <trusted|untrusted>`
|
|
269
|
-
* CLI flag). `intake` STAMPS `origin: issue` + this `originTrust` onto every
|
|
269
|
+
* CLI flag). `intake` STAMPS `origin: issue` + this `originTrust` onto every spec/
|
|
270
270
|
* task it emits, so the author-trust signal SURVIVES the prd/task merge
|
|
271
271
|
* boundary (a landed-on-main artifact otherwise erases how it was born, the
|
|
272
272
|
* laundering gap). `intake` does NOT resolve trust itself: the verdict is CI's
|
|
@@ -285,7 +285,7 @@ export interface PerformIntakeOptions {
|
|
|
285
285
|
*/
|
|
286
286
|
noPR?: boolean;
|
|
287
287
|
/**
|
|
288
|
-
* **The per-repo
|
|
288
|
+
* **The per-repo SPEC-PLACEMENT default, passed IN** (spec
|
|
289
289
|
* `staging-pool-position-gate-and-trust-model` US #2/#5, task
|
|
290
290
|
* `pre-prd-staging-pool-split-and-untrusted-prd-placement`). The resolved
|
|
291
291
|
* per-repo default landing for `intake`-authored prds (`pre-proposed` =
|
|
@@ -293,8 +293,8 @@ export interface PerformIntakeOptions {
|
|
|
293
293
|
* into the shared placement resolver (`src/placement.ts`). The resolver
|
|
294
294
|
* overlays an EXPLICIT operator flag ({@link explicitSpecsLandIn}, top) and
|
|
295
295
|
* the UNTRUSTED-ORIGIN force (`originTrust: untrusted` ⇒ staging) on top.
|
|
296
|
-
* Unset ⇒ the resolver's built-in floor applies (`staging` = `
|
|
297
|
-
* the conservative landing). The
|
|
296
|
+
* Unset ⇒ the resolver's built-in floor applies (`staging` = `specs/proposed/`,
|
|
297
|
+
* the conservative landing). The SPEC TWIN of `tasksLandIn` on the tasker
|
|
298
298
|
* path — one resolver, two lifecycles.
|
|
299
299
|
*/
|
|
300
300
|
specsLandIn?: SpecsLandIn;
|
|
@@ -334,15 +334,15 @@ export interface PerformIntakeOptions {
|
|
|
334
334
|
const DEFAULT_ARBITER = 'origin';
|
|
335
335
|
|
|
336
336
|
/**
|
|
337
|
-
* **The STAGED-prds dir** (
|
|
337
|
+
* **The STAGED-prds dir** (spec `staging-pool-position-gate-and-trust-model`,
|
|
338
338
|
* task `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing
|
|
339
339
|
* ADR `placement-is-runner-deterministic-humanonly-is-agent-judgement`). When
|
|
340
340
|
* the runner-deterministic placement resolver picks the staging side for an
|
|
341
|
-
* `intake`-authored
|
|
342
|
-
* `work/
|
|
343
|
-
* the tasking candidate POOL (`work/
|
|
344
|
-
* ({@link promoteFromPreSpec} in `needs-attention.ts`) moves an approved
|
|
345
|
-
* `
|
|
341
|
+
* `intake`-authored spec, the runner writes the spec file HERE instead of in
|
|
342
|
+
* `work/specs/ready/`. An item born in `specs/proposed/` is durable + readable but NOT in
|
|
343
|
+
* the tasking candidate POOL (`work/specs/ready/` is the pool). A runner/human-owned promotion
|
|
344
|
+
* ({@link promoteFromPreSpec} in `needs-attention.ts`) moves an approved spec
|
|
345
|
+
* `specs/proposed/ → specs/ready/` to make it taskable.
|
|
346
346
|
*/
|
|
347
347
|
export const STAGED_SPECS_DIR = workFolderRel('specs-proposed');
|
|
348
348
|
|
|
@@ -377,19 +377,19 @@ function specLandingToSide(
|
|
|
377
377
|
|
|
378
378
|
/**
|
|
379
379
|
* The emitted artifact TYPE `intake` decides at RUNTIME — a `task` verdict emits
|
|
380
|
-
* `work/backlog/<slug>.md`, a `prd` verdict emits the
|
|
380
|
+
* `work/backlog/<slug>.md`, a `prd` verdict emits the spec file (`work/specs/ready/<slug>.md`). The two
|
|
381
381
|
* granular flag axes (`--merge-task`/`--propose-task` vs `--merge-spec`/
|
|
382
382
|
* `--propose-spec`) are keyed on this. (ask/bounce emit NOTHING, so the modes are
|
|
383
383
|
* no-ops for them.)
|
|
384
384
|
*/
|
|
385
385
|
export type IntakeArtifactType = 'task' | 'spec';
|
|
386
|
-
// prd → spec
|
|
387
|
-
// `'prd'`
|
|
386
|
+
// `prd` → `spec` HARD CUTOVER: `'spec'` is the ONLY spec artifact type value; the
|
|
387
|
+
// legacy `'prd'` alias is GONE (the contract task removed it).
|
|
388
388
|
|
|
389
389
|
/**
|
|
390
|
-
* The PER-OUTCOME integration mode FLAG SET (
|
|
390
|
+
* The PER-OUTCOME integration mode FLAG SET (spec `issue-intake` US #9). Because
|
|
391
391
|
* `intake` decides the artifact TYPE at runtime, a single `--merge`/`--propose`
|
|
392
|
-
* cannot express a type-conditional policy ("merge a
|
|
392
|
+
* cannot express a type-conditional policy ("merge a spec but propose a task") —
|
|
393
393
|
* hence the four GRANULAR per-type flags layered over the two AGGREGATES:
|
|
394
394
|
*
|
|
395
395
|
* - **granular:** `--merge-spec`/`--propose-spec` apply iff the outcome is a spec;
|
|
@@ -400,9 +400,9 @@ export type IntakeArtifactType = 'task' | 'spec';
|
|
|
400
400
|
* author-trust) is CI's POLICY, authored in `runner-in-ci` — NOT here.
|
|
401
401
|
*/
|
|
402
402
|
export interface IntakeIntegrationFlags {
|
|
403
|
-
/** Aggregate: merge BOTH a task and a
|
|
403
|
+
/** Aggregate: merge BOTH a task and a spec (the broad knob, overridden per type). */
|
|
404
404
|
merge?: boolean;
|
|
405
|
-
/** Aggregate: propose BOTH a task and a
|
|
405
|
+
/** Aggregate: propose BOTH a task and a spec. */
|
|
406
406
|
propose?: boolean;
|
|
407
407
|
/** Granular: merge a spec (overrides the aggregate for the spec outcome). */
|
|
408
408
|
mergeSpec?: boolean;
|
|
@@ -419,7 +419,7 @@ export interface IntakeIntegrationModes {
|
|
|
419
419
|
/** The mode an EMITTED task integrates with. */
|
|
420
420
|
task: IntegrationMode;
|
|
421
421
|
/**
|
|
422
|
-
* The mode an EMITTED spec integrates with. `spec` is the CANONICAL key (
|
|
422
|
+
* The mode an EMITTED spec integrates with. `spec` is the CANONICAL key (spec →
|
|
423
423
|
* spec cutover); the user-facing `--merge-spec`/`--propose-spec` flags that FEED
|
|
424
424
|
* it carry the same `spec` spelling (the cli-flag rename landed in batch 4f).
|
|
425
425
|
*/
|
|
@@ -453,10 +453,10 @@ function granularFromFlags(
|
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
/**
|
|
456
|
-
* The PURE per-outcome integration mode resolution (
|
|
456
|
+
* The PURE per-outcome integration mode resolution (spec `issue-intake` US #9 —
|
|
457
457
|
* the canonical table). Given ONLY the flag set, resolve BOTH per-type modes in
|
|
458
458
|
* one eager pass (so a usage error is caught before the runtime verdict is even
|
|
459
|
-
* known). The rules, all decided in the
|
|
459
|
+
* known). The rules, all decided in the spec:
|
|
460
460
|
*
|
|
461
461
|
* - **unset ⇒ propose for BOTH** (conservative default; matches `do`).
|
|
462
462
|
* - **aggregates:** `--merge` ⇒ merge both; `--propose` ⇒ propose both (this axis
|
|
@@ -574,7 +574,7 @@ export async function performIntake(
|
|
|
574
574
|
return {exitCode: 1, outcome: 'usage-error', issueNumber, message};
|
|
575
575
|
}
|
|
576
576
|
|
|
577
|
-
// 2. ACQUIRE the `processing` LOCK (
|
|
577
|
+
// 2. ACQUIRE the `processing` LOCK (spec `issue-intake` US #10): a TRANSIENT concurrency mutex
|
|
578
578
|
// that serialises two concurrent runs on the SAME issue. Read the labels; if
|
|
579
579
|
// the lock is ALREADY present, BACK OFF (do nothing — another run owns it). The
|
|
580
580
|
// winner ADDS the label and proceeds; the label is REMOVED on finish (success
|
|
@@ -815,12 +815,12 @@ async function decideAndDispatch(
|
|
|
815
815
|
return {exitCode: 1, outcome: 'agent-failed', issueNumber, message};
|
|
816
816
|
}
|
|
817
817
|
|
|
818
|
-
// DISPATCH on the verdict — the FULL four-outcome decision table (
|
|
818
|
+
// DISPATCH on the verdict — the FULL four-outcome decision table (spec
|
|
819
819
|
// `issue-intake`). The agent only DRAFTED the verdict; the runner owns every
|
|
820
820
|
// git/seam side-effect below (the in-band boundary): the write + integrate
|
|
821
|
-
// (task/
|
|
821
|
+
// (task/spec) and the `postIssueComment` (ask/bounce).
|
|
822
822
|
//
|
|
823
|
-
// PER-OUTCOME integration (
|
|
823
|
+
// PER-OUTCOME integration (spec `issue-intake` US #9): the resolved mode is keyed on the runtime
|
|
824
824
|
// artifact TYPE — a `task` verdict integrates with the task mode, a `spec`
|
|
825
825
|
// verdict with the spec mode. Unset ⇒ propose for both. ask/bounce never
|
|
826
826
|
// integrate, so the modes are no-ops for them.
|
|
@@ -863,7 +863,7 @@ async function decideAndDispatch(
|
|
|
863
863
|
cwd,
|
|
864
864
|
arbiter,
|
|
865
865
|
integration: modes.spec,
|
|
866
|
-
// Same origin-trust stamp on the
|
|
866
|
+
// Same origin-trust stamp on the spec outcome (propagated onto its tasks
|
|
867
867
|
// later by the tasker). Passed IN; not resolved here.
|
|
868
868
|
originTrust: options.originTrust,
|
|
869
869
|
noPR: options.noPR,
|
|
@@ -871,7 +871,7 @@ async function decideAndDispatch(
|
|
|
871
871
|
// `pre-prd-staging-pool-split-and-untrusted-prd-placement`): the
|
|
872
872
|
// configured-default + explicit-flag rungs, fed into the SHARED placement
|
|
873
873
|
// resolver alongside the `originTrust` stamp above. The resolver decides
|
|
874
|
-
// `
|
|
874
|
+
// `specs/proposed/` (staging) vs `specs/ready/` (the tasking pool); `intake` never
|
|
875
875
|
// places itself.
|
|
876
876
|
specsLandIn: options.specsLandIn,
|
|
877
877
|
explicitSpecsLandIn: options.explicitSpecsLandIn,
|
|
@@ -931,7 +931,7 @@ async function decideAndDispatch(
|
|
|
931
931
|
*
|
|
932
932
|
* - **ask** (non-terminal): `postIssueComment` the drafted question, emit NOTHING,
|
|
933
933
|
* and LEAVE THE ISSUE OPEN — it waits for the thread to be answered (a later run
|
|
934
|
-
* resumes from it). The task/
|
|
934
|
+
* resumes from it). The task/spec path also never closes (CI's close-job does,
|
|
935
935
|
* via the `issue:` field). Intake closes ONLY on BOUNCE.
|
|
936
936
|
* - **bounce** (TERMINAL): the asks are unrelated and must be re-filed, so an OPEN
|
|
937
937
|
* issue is a dishonest "still in play" signal. Intake CLOSES the issue
|
|
@@ -1028,7 +1028,7 @@ async function dispatchComment(params: {
|
|
|
1028
1028
|
|
|
1029
1029
|
/**
|
|
1030
1030
|
* DISPATCH the `task` outcome: derive a content-derived slug, write
|
|
1031
|
-
* `work/backlog/<slug>.md` (`covers: []`, NO `
|
|
1031
|
+
* `work/backlog/<slug>.md` (`covers: []`, NO `spec:`) carrying `issue: N` (the
|
|
1032
1032
|
* lone-task closure link, NOT `Fixes #N`), and integrate via {@link
|
|
1033
1033
|
* performIntegration}. The runner owns the git: it onboards a
|
|
1034
1034
|
* `work/<slug>` branch off fresh `<arbiter>/main`, then the lifecycle `stage`
|
|
@@ -1074,7 +1074,7 @@ async function dispatchTask(params: {
|
|
|
1074
1074
|
note,
|
|
1075
1075
|
} = params;
|
|
1076
1076
|
|
|
1077
|
-
// A content-derived slug — NEVER a counter (
|
|
1077
|
+
// A content-derived slug — NEVER a counter (spec `issue-intake` US #8). Prefer the drafted
|
|
1078
1078
|
// `taskSlug`, else derive from the drafted title; sanitise either through
|
|
1079
1079
|
// `paramCase` so the filename + frontmatter slug are well-formed.
|
|
1080
1080
|
const slug = resolveSlug(verdict);
|
|
@@ -1089,7 +1089,7 @@ async function dispatchTask(params: {
|
|
|
1089
1089
|
|
|
1090
1090
|
// BOUNDED INTERNAL REVIEW (observation
|
|
1091
1091
|
// `intake-lone-task-skips-adversarial-review-the-prd-path-gets`, rulings A/B/C):
|
|
1092
|
-
// the `do
|
|
1092
|
+
// the `do spec:` path gets `runTaskReviewLoop`; the lone-TASK path got NOTHING.
|
|
1093
1093
|
// AFTER the `task` verdict and BEFORE the write/integrate, run a bounded (3-round,
|
|
1094
1094
|
// HARD-CAPPED) adversarial self-review on the SINGLE drafted task. It mutates the
|
|
1095
1095
|
// candidate body IN MEMORY (no `work/backlog/` write pre-convergence). A launch/
|
|
@@ -1266,7 +1266,7 @@ async function dispatchSpec(params: {
|
|
|
1266
1266
|
note,
|
|
1267
1267
|
} = params;
|
|
1268
1268
|
|
|
1269
|
-
// A content-derived slug — NEVER a counter (
|
|
1269
|
+
// A content-derived slug — NEVER a counter (spec `issue-intake` US #8). Prefer the drafted
|
|
1270
1270
|
// `specSlug`, else derive from the drafted title.
|
|
1271
1271
|
const slug = resolveSpecSlug(verdict);
|
|
1272
1272
|
if (slug === '') {
|
|
@@ -1279,7 +1279,7 @@ async function dispatchSpec(params: {
|
|
|
1279
1279
|
// RUNNER-DETERMINISTIC PLACEMENT (task
|
|
1280
1280
|
// `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing ADR
|
|
1281
1281
|
// `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Resolve
|
|
1282
|
-
// which folder the runner writes the intake-authored
|
|
1282
|
+
// which folder the runner writes the intake-authored spec into BEFORE handing
|
|
1283
1283
|
// it to the shared integrate band: the SAME precedence chain the tasker uses
|
|
1284
1284
|
// (`explicit > untrusted-origin ⇒ staging > specsLandIn > built-in (staging)`),
|
|
1285
1285
|
// the SAME shared resolver — only the lifecycle SLOTS differ. The agent
|
|
@@ -1317,7 +1317,7 @@ async function dispatchSpec(params: {
|
|
|
1317
1317
|
slug,
|
|
1318
1318
|
source: 'in-progress',
|
|
1319
1319
|
recovering: false,
|
|
1320
|
-
// An intake-emitted
|
|
1320
|
+
// An intake-emitted spec has no `verify` floor of its own (it is a new spec,
|
|
1321
1321
|
// not a build), exactly as the task branch + the tasking transition skip it.
|
|
1322
1322
|
skipVerify: true,
|
|
1323
1323
|
mode: integration,
|
|
@@ -1325,8 +1325,8 @@ async function dispatchSpec(params: {
|
|
|
1325
1325
|
providerInstance,
|
|
1326
1326
|
type: 'feat',
|
|
1327
1327
|
lifecycle: {
|
|
1328
|
-
// The emitted
|
|
1329
|
-
// race as the task path: `stage()` writes the
|
|
1328
|
+
// The emitted spec IS the title source. Pass the DRAFTED title EXPLICITLY (same
|
|
1329
|
+
// race as the task path: `stage()` writes the spec file AFTER the title
|
|
1330
1330
|
// read). `titlePath` stays set but is IGNORED while `title` is present.
|
|
1331
1331
|
titlePath: join(cwd, relPath),
|
|
1332
1332
|
title: verdict.specTitle ?? slug,
|
|
@@ -1384,9 +1384,9 @@ async function integrationToIntakeResult(
|
|
|
1384
1384
|
core.integration?.mode === 'merge'
|
|
1385
1385
|
? 'landed it on the arbiter main'
|
|
1386
1386
|
: 'opened a PR carrying it (main untouched)';
|
|
1387
|
-
// Both a lone task and a
|
|
1388
|
-
// closes its own issue; a
|
|
1389
|
-
// task/
|
|
1387
|
+
// Both a lone task and a spec carry `issue: N` as their closure link (the task
|
|
1388
|
+
// closes its own issue; a spec is reached via `task.spec: → spec issue:`). On the
|
|
1389
|
+
// task/spec path `intake` never closes the issue (CI's close-job does, via the
|
|
1390
1390
|
// `issue:` field; intake closes ONLY on BOUNCE) and emits no `Fixes #N` (a
|
|
1391
1391
|
// deferred GitHub-only optimisation).
|
|
1392
1392
|
const link = `issue: ${issueNumber}`;
|
|
@@ -1456,7 +1456,7 @@ async function integrationToIntakeResult(
|
|
|
1456
1456
|
* `commit` (the additive {@link IntegrateResult.commit}) in merge. A degraded
|
|
1457
1457
|
* propose (no `url`) or a failed merge-tip read (no `commit`) simply OMITS the
|
|
1458
1458
|
* link — the comment still confirms what was created (the artifact is safe on the
|
|
1459
|
-
* branch/main regardless). No
|
|
1459
|
+
* branch/main regardless). No spec link beyond the slug.
|
|
1460
1460
|
* - carries the FULL intake MARKER via the SHARED {@link stampIntakeMarker} helper
|
|
1461
1461
|
* (`kind=created slug=<slug> seen=<id>,…`) so the triage's `already-terminal`
|
|
1462
1462
|
* branch consumes it — the comment cannot re-trigger intake.
|
|
@@ -1497,7 +1497,7 @@ export function composeIntakeCompletionComment(params: {
|
|
|
1497
1497
|
* does, via the `issue:` field); this comment changes NO issue state.
|
|
1498
1498
|
* - LINKS the artifact by INTEGRATION MODE: the PR `url` in propose, the landed
|
|
1499
1499
|
* `commit` (the additive {@link IntegrateResult.commit} this task surfaces) in
|
|
1500
|
-
* merge. No
|
|
1500
|
+
* merge. No spec link beyond the slug.
|
|
1501
1501
|
* - carries the FULL intake MARKER via the SHARED {@link stampIntakeMarker} helper
|
|
1502
1502
|
* (`kind=created slug=<slug> seen=<id>,…`). `kind=created` is TERMINAL, so the
|
|
1503
1503
|
* triage's `already-terminal` branch then treats the issue as already-transformed
|
|
@@ -1558,7 +1558,7 @@ async function postCompletionComment(params: {
|
|
|
1558
1558
|
}
|
|
1559
1559
|
|
|
1560
1560
|
/**
|
|
1561
|
-
* Resolve a content-derived slug from the verdict — NEVER a counter (
|
|
1561
|
+
* Resolve a content-derived slug from the verdict — NEVER a counter (spec `issue-intake` US #8).
|
|
1562
1562
|
* Prefer the drafted `taskSlug`, else derive from the drafted title; both go
|
|
1563
1563
|
* through `paramCase` (the brand case-transform) so the result is a clean
|
|
1564
1564
|
* lowercase-`-`-joined slug. An empty result (no slug AND no title) signals the
|
|
@@ -1573,7 +1573,7 @@ function resolveSlug(verdict: IntakeVerdict): string {
|
|
|
1573
1573
|
}
|
|
1574
1574
|
|
|
1575
1575
|
/**
|
|
1576
|
-
* Resolve a content-derived slug for the spec outcome — NEVER a counter (
|
|
1576
|
+
* Resolve a content-derived slug for the spec outcome — NEVER a counter (spec `issue-intake` US #8).
|
|
1577
1577
|
* Prefer the drafted `specSlug`, else derive from the drafted spec title; both go
|
|
1578
1578
|
* through `paramCase`. An empty result signals the caller to refuse.
|
|
1579
1579
|
*/
|
|
@@ -1587,13 +1587,13 @@ function resolveSpecSlug(verdict: IntakeVerdict): string {
|
|
|
1587
1587
|
|
|
1588
1588
|
/**
|
|
1589
1589
|
* Render the backlog task file: the frontmatter (`title`/`slug`/`covers: []`, NO
|
|
1590
|
-
* `
|
|
1590
|
+
* `spec:` — its own source of truth, spec `issue-intake` decision table) carrying the lone-task
|
|
1591
1591
|
* `issue: N` closure link + the drafted body. The task closes its source issue
|
|
1592
1592
|
* via its `issue:` field (the provider-agnostic link a FUTURE CI close-job reads
|
|
1593
1593
|
* from folder + field state); it carries NO `Fixes #N` (a deferred GitHub-only
|
|
1594
1594
|
* optimisation, structurally unplaceable on the `--merge` path). The number is
|
|
1595
|
-
* the task's own closure path — `issue:` XOR `
|
|
1596
|
-
* `
|
|
1595
|
+
* the task's own closure path — `issue:` XOR `spec:`; a lone task never carries a
|
|
1596
|
+
* `spec:` (spec `issue-intake` decision table). When the agent drafted no body, a thin default
|
|
1597
1597
|
* scaffold keeps the file a valid task.
|
|
1598
1598
|
*/
|
|
1599
1599
|
export function renderBacklogTask(params: {
|
|
@@ -1623,7 +1623,7 @@ export function renderBacklogTask(params: {
|
|
|
1623
1623
|
const frontmatter = lines.join('\n');
|
|
1624
1624
|
// The drafted body (agent-authored, headings and all) is wrapped VERBATIM.
|
|
1625
1625
|
// Only the empty-body DEFAULT SCAFFOLD is sourced from the shared section
|
|
1626
|
-
// skeleton owner (`renderTaskBody`,
|
|
1626
|
+
// skeleton owner (`renderTaskBody`, spec
|
|
1627
1627
|
// `centralize-buildable-task-renderer-shared-by-intake-and-promotion` US #2),
|
|
1628
1628
|
// so intake's fallback and promotion's body cannot drift on section
|
|
1629
1629
|
// names/order. The shared renderer ends its body with a trailing newline (its
|
|
@@ -1642,16 +1642,16 @@ export function renderBacklogTask(params: {
|
|
|
1642
1642
|
}
|
|
1643
1643
|
|
|
1644
1644
|
/**
|
|
1645
|
-
* Render the emitted
|
|
1646
|
-
* `issue: N` + the gate axes the prompt JUDGED) followed by the drafted
|
|
1647
|
-
* For a FANNED
|
|
1648
|
-
* the N fanned tasks, which reach it via `task.
|
|
1649
|
-
* task carries `
|
|
1650
|
-
* one that puts `issue:` on a task). The close JOB reaches the
|
|
1651
|
-
* `task.
|
|
1645
|
+
* Render the emitted spec file: the frontmatter (`title`/`slug` + the loop-closure
|
|
1646
|
+
* `issue: N` + the gate axes the prompt JUDGED) followed by the drafted spec body.
|
|
1647
|
+
* For a FANNED spec the `issue: N` lives ONLY on the spec — never duplicated across
|
|
1648
|
+
* the N fanned tasks, which reach it via `task.spec: → spec issue:` (a fanned
|
|
1649
|
+
* task carries `spec:`, NOT its own `issue:`; the lone-task outcome is the only
|
|
1650
|
+
* one that puts `issue:` on a task). The close JOB reaches the spec's number via
|
|
1651
|
+
* `task.spec: → spec issue:`. The gate axes (`humanOnly`/`needsAnswers`) are emitted ONLY when the
|
|
1652
1652
|
* verdict declared them `true` — an omitted axis is `undefined` (undeclared), the
|
|
1653
1653
|
* same convention `frontmatter.ts` parses. When the agent drafted no body, a thin
|
|
1654
|
-
* default scaffold keeps the file a valid
|
|
1654
|
+
* default scaffold keeps the file a valid spec that `do spec:` can later task.
|
|
1655
1655
|
*/
|
|
1656
1656
|
export function renderSpec(params: {
|
|
1657
1657
|
slug: string;
|
|
@@ -1682,7 +1682,7 @@ export function renderSpec(params: {
|
|
|
1682
1682
|
if (originTrust !== undefined) {
|
|
1683
1683
|
lines.push('origin: issue', `originTrust: ${originTrust}`);
|
|
1684
1684
|
}
|
|
1685
|
-
// Surface the gate axes AS THE PROMPT JUDGED THEM (
|
|
1685
|
+
// Surface the gate axes AS THE PROMPT JUDGED THEM (spec `issue-intake` US #8). Only emit a `true`
|
|
1686
1686
|
// axis — an undeclared axis stays absent (parsed as `undefined`).
|
|
1687
1687
|
if (humanOnly === true) {
|
|
1688
1688
|
lines.push('humanOnly: true');
|
|
@@ -1692,11 +1692,11 @@ export function renderSpec(params: {
|
|
|
1692
1692
|
}
|
|
1693
1693
|
lines.push('---');
|
|
1694
1694
|
const frontmatter = lines.join('\n');
|
|
1695
|
-
// As with `renderBacklogTask`: the drafted
|
|
1695
|
+
// As with `renderBacklogTask`: the drafted SPEC body is wrapped VERBATIM; only
|
|
1696
1696
|
// the empty-body DEFAULT SCAFFOLD is sourced from the shared section skeleton
|
|
1697
|
-
// owner (`renderSpecBody` with `solution` + `userStories`,
|
|
1697
|
+
// owner (`renderSpecBody` with `solution` + `userStories`, spec
|
|
1698
1698
|
// `centralize-buildable-task-renderer-shared-by-intake-and-promotion` US #2),
|
|
1699
|
-
// so intake's
|
|
1699
|
+
// so intake's SPEC fallback and promotion's SPEC body cannot drift. `trimEnd()`
|
|
1700
1700
|
// drops the renderer's trailing blank line so intake's single trailing `\n`
|
|
1701
1701
|
// (owned by the join below) keeps the bytes identical to the pre-rewire literal.
|
|
1702
1702
|
const drafted =
|
|
@@ -1704,7 +1704,7 @@ export function renderSpec(params: {
|
|
|
1704
1704
|
? body.trim()
|
|
1705
1705
|
: renderSpecBody({
|
|
1706
1706
|
problemStatement: `Transformed from issue #${issueNumber}: ${title}`,
|
|
1707
|
-
solution: '(to be detailed; this
|
|
1707
|
+
solution: '(to be detailed; this spec needs tasking via `do spec:`).',
|
|
1708
1708
|
userStories: `1. As a user, I want issue #${issueNumber} addressed.`,
|
|
1709
1709
|
}).trimEnd();
|
|
1710
1710
|
return `${frontmatter}\n\n${drafted}\n`;
|
|
@@ -1737,7 +1737,7 @@ async function stageIntakeContent(params: {
|
|
|
1737
1737
|
* `intake-` PRODUCER prefix keeps this short-lived "create the item" branch
|
|
1738
1738
|
* DISTINCT from the later build branch (`work/task-<slug>`) for the same slug
|
|
1739
1739
|
* — the firing `intake` × `do task:` collision the observation traced. The
|
|
1740
|
-
* task-emit path passes `'task'`, the
|
|
1740
|
+
* task-emit path passes `'task'`, the spec-emit path `'prd'`. A pre-existing
|
|
1741
1741
|
* local branch (a re-run) is force-recreated off fresh main.
|
|
1742
1742
|
*/
|
|
1743
1743
|
async function switchToWorkBranch(
|
|
@@ -1782,7 +1782,7 @@ async function runDecision(
|
|
|
1782
1782
|
if (options.decide) {
|
|
1783
1783
|
return options.decide({cwd, issue, comments, prompt, env: options.env});
|
|
1784
1784
|
}
|
|
1785
|
-
// PRODUCTION: launch the harness with the decision
|
|
1785
|
+
// PRODUCTION: launch the harness with the decision spec, then PARSE the verdict
|
|
1786
1786
|
// the agent emitted out of its ANSWER channel (`launched.output`) — the SAME wire
|
|
1787
1787
|
// the review gate runs (launch → `parseReviewVerdict(readOutput(launched.output))`;
|
|
1788
1788
|
// `harnessReviewGate`). The agent emits a single fenced ```json block (the OUTPUT
|
|
@@ -1905,7 +1905,7 @@ export function parseIntakeVerdict(output: string): IntakeVerdict {
|
|
|
1905
1905
|
// The LONE-TASK bounded internal review (observation
|
|
1906
1906
|
// `intake-lone-task-skips-adversarial-review-the-prd-path-gets`, rulings A/B/C).
|
|
1907
1907
|
//
|
|
1908
|
-
// Give intake's lone-TASK outcome the adversarial refinement the `do
|
|
1908
|
+
// Give intake's lone-TASK outcome the adversarial refinement the `do spec:` path
|
|
1909
1909
|
// already gets — but as a small intake-NATIVE bounded review, NOT by integrating
|
|
1910
1910
|
// the tasker loop. This is a NEW prompt + a small loop + an injectable gate seam,
|
|
1911
1911
|
// MIRRORING the tasker loop's verdict/output CONVENTIONS (fenced JSON
|
|
@@ -2293,20 +2293,20 @@ export function buildLoneTaskReviewPrompt(
|
|
|
2293
2293
|
export const parseLoneTaskReviewVerdict = parseReviewVerdict;
|
|
2294
2294
|
|
|
2295
2295
|
/**
|
|
2296
|
-
* Build the intake decision
|
|
2296
|
+
* Build the intake decision SPEC (an inline prompt builder, like `buildTaskingPrd`
|
|
2297
2297
|
* in `tasking.ts` / the reviewer prompts in `review-gate.ts` — NOT a standalone
|
|
2298
2298
|
* asset/`.md` file; no such convention exists in this package). It encodes the FULL
|
|
2299
|
-
* four-outcome decision table (
|
|
2299
|
+
* four-outcome decision table (spec `issue-intake` — the source of truth) and the
|
|
2300
2300
|
* three DECISION AIDS stated once there:
|
|
2301
2301
|
*
|
|
2302
2302
|
* 1. the **"clear?" bar** = `to-task`/`needsAnswers`' "would I build the wrong
|
|
2303
2303
|
* thing if I guessed?" — if a material requirement/scope/acceptance question is
|
|
2304
2304
|
* unanswered, ASK (never guess a spec from a vague issue);
|
|
2305
2305
|
* 2. the **"one task?" bar** = `to-task`' tracer-bullet test (one thin end-to-end
|
|
2306
|
-
* path, demoable on its own) — fits → TASK, needs splitting →
|
|
2307
|
-
* 3. **
|
|
2306
|
+
* path, demoable on its own) — fits → TASK, needs splitting → SPEC;
|
|
2307
|
+
* 3. **SPEC vs BOUNCE** turns on a **SHARED VISION**: coupled (even if small) → SPEC;
|
|
2308
2308
|
* genuinely unrelated → BOUNCE. Size NEVER forces a bounce — only unrelatedness
|
|
2309
|
-
* (the over-bounce guard: a coupled-but-small pair gets a light
|
|
2309
|
+
* (the over-bounce guard: a coupled-but-small pair gets a light SPEC, never a
|
|
2310
2310
|
* bounce).
|
|
2311
2311
|
*
|
|
2312
2312
|
* The prompt anchors to `to-task`/`to-spec` for the task/spec SHAPES it drafts. Its
|
|
@@ -2328,7 +2328,7 @@ export function buildIntakeDecisionSpec(
|
|
|
2328
2328
|
`#${i + 1} ${c.author ? `@${c.author}` : '(unknown)'}: ${c.body}`,
|
|
2329
2329
|
)
|
|
2330
2330
|
.join('\n\n');
|
|
2331
|
-
// TRIAGE ENRICHMENT (
|
|
2331
|
+
// TRIAGE ENRICHMENT (spec `issue-intake`): on the raced PROCEED path the prompt is
|
|
2332
2332
|
// told which comment(s) PRE-DATE intake's last turn (context for a prior state,
|
|
2333
2333
|
// not necessarily a fresh answer) and — only then — how many previously-SEEN
|
|
2334
2334
|
// comments were DELETED (a flag + count; the bodies are gone, so do not name them).
|
|
@@ -2378,42 +2378,42 @@ export function buildIntakeDecisionSpec(
|
|
|
2378
2378
|
' (a single thin end-to-end path, demoable on its own — `to-task`’ criterion).',
|
|
2379
2379
|
' Draft that ONE task in the `to-task` shape (a `## What to build`,',
|
|
2380
2380
|
' `## Acceptance criteria`, and `## Prompt`). The runner writes',
|
|
2381
|
-
' `work/backlog/<slug>.md` (`covers: []`, NO `
|
|
2381
|
+
' `work/backlog/<slug>.md` (`covers: []`, NO `spec:`) carrying `issue: N` (the',
|
|
2382
2382
|
' lone-task closure link, NOT `Fixes #N`) and integrates it.',
|
|
2383
2383
|
'',
|
|
2384
|
-
'- **
|
|
2384
|
+
'- **SPEC** — the issue is CLEAR *and* coherent but needs MORE THAN ONE task (it',
|
|
2385
2385
|
' cannot be one tracer-bullet path — it splits for scope/architecture). >1 task',
|
|
2386
2386
|
' ⟺ a shared vision worth recording ⟺ a spec. Draft a spec in the `to-spec` shape',
|
|
2387
2387
|
' (`## Problem Statement`, `## Solution`, `## User Stories`, `## Out of Scope`).',
|
|
2388
|
-
|
|
2389
|
-
' TASKING the
|
|
2388
|
+
` The runner writes the spec file (\`${workFolderPrefix('specs-ready')}<slug>.md\`) with \`issue: N\` and integrates it;`,
|
|
2389
|
+
' TASKING the spec is a SEPARATE later step (`do spec:`) — do not task it here.',
|
|
2390
2390
|
' **INCLUDES a coupled-but-SMALL pair: if two asks share a vision they get a',
|
|
2391
|
-
' (light)
|
|
2391
|
+
' (light) spec — they are NEVER bounced.**',
|
|
2392
2392
|
'',
|
|
2393
2393
|
'- **BOUNCE** — the issue is really MULTIPLE UNRELATED concerns wearing one issue:',
|
|
2394
2394
|
' you cannot articulate a SINGLE shared vision tying them together. Draft a short',
|
|
2395
2395
|
' message asking the author to file separate issues. A bounce is TERMINAL, so the',
|
|
2396
2396
|
' runner CLOSES the issue ATOMICALLY — your message as the closing comment +',
|
|
2397
2397
|
' reason "not planned" (the honest signal that the asks must be re-filed). Intake',
|
|
2398
|
-
' closes on BOUNCE only; never on task/
|
|
2398
|
+
' closes on BOUNCE only; never on task/spec (CI’s close-job) / ask.',
|
|
2399
2399
|
'',
|
|
2400
2400
|
'## The three decision aids (apply them in order)',
|
|
2401
2401
|
'',
|
|
2402
2402
|
'1. **"clear?"** (ASK vs the rest): the `needsAnswers` bar — would acting now risk',
|
|
2403
2403
|
' building the wrong thing? If yes → ASK. Otherwise it is clear; continue.',
|
|
2404
|
-
'2. **"one task?"** (TASK vs
|
|
2405
|
-
' end-to-end path, demoable alone? Fits → TASK; needs splitting →
|
|
2406
|
-
'3. **"shared vision?"** (
|
|
2404
|
+
'2. **"one task?"** (TASK vs SPEC): the `to-task` tracer-bullet test — one thin',
|
|
2405
|
+
' end-to-end path, demoable alone? Fits → TASK; needs splitting → SPEC.',
|
|
2406
|
+
'3. **"shared vision?"** (SPEC vs BOUNCE): coupled (even if small) → SPEC; genuinely',
|
|
2407
2407
|
' unrelated → BOUNCE. SIZE NEVER forces a bounce — only UNRELATEDNESS does. Do',
|
|
2408
|
-
' not over-bounce a small coupled pair: it is a light
|
|
2408
|
+
' not over-bounce a small coupled pair: it is a light spec.',
|
|
2409
2409
|
'',
|
|
2410
2410
|
'## Boundary',
|
|
2411
2411
|
'',
|
|
2412
|
-
'You only DRAFT the verdict + its content (the task/
|
|
2412
|
+
'You only DRAFT the verdict + its content (the task/spec body, or the comment',
|
|
2413
2413
|
'text). You do NOT perform ANY git operation and you do NOT post any comment — the',
|
|
2414
|
-
'runner owns every git/seam side-effect (write, integrate, postComment). For a
|
|
2414
|
+
'runner owns every git/seam side-effect (write, integrate, postComment). For a spec',
|
|
2415
2415
|
'verdict, also judge its gate axes (humanOnly / needsAnswers) so the runner can',
|
|
2416
|
-
'surface them on the emitted
|
|
2416
|
+
'surface them on the emitted spec.',
|
|
2417
2417
|
'',
|
|
2418
2418
|
'## Output — hand the verdict back as ONE fenced JSON block',
|
|
2419
2419
|
'',
|