feature-factory 0.8.4 → 0.8.6

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/WORKFLOW.md CHANGED
@@ -132,8 +132,10 @@ remainder.
132
132
  - With no admitted mode token, omit `--mode`; existing `factory init` records
133
133
  `interactive`.
134
134
 
135
- Those three compatibility phrases name init command stems, not runnable invocations. The selected
136
- fresh-run invocation is fully qualified in Step 0 and ends with `--repo "$RUN_REPO"`.
135
+ Those three compatibility phrases name init command stems, not runnable invocations. The one runnable
136
+ fresh-run invocation is the fully qualified command block in Step 0; copy that block rather than
137
+ assembling init from the phrases here. It is the single factory invocation whose repository flag is
138
+ `--repo "$O"`, and it ends with `--json`.
137
139
 
138
140
  Repeated copies of one mode token are idempotent: the skill consumes them all and this workflow
139
141
  selects that mode once. A mode token the skill did not admit, standing after the first request token,
@@ -293,8 +295,12 @@ fresh run; an existing run follows these rules solely because its manifest alrea
293
295
  every acceptance criterion maps to a slice, and same-wave slices are file-disjoint.
294
296
  - **Gate 3 (pre-PR)**: approve only on a GO or GO-WITH-NITS validator verdict with `review_ready`
295
297
  observed evidence for the integrated branch. A NO-GO is a NO-GO.
296
- - **Never auto-merge.** The draft PR is the last externally publishing side effect an autonomous run
297
- may perform. After it is recorded, the mandatory local completed handoff in Step 7 still follows and
298
+ - **Never auto-merge.** Recording the pull request is the last externally publishing side effect an
299
+ autonomous run may perform. Whether that PR is a draft is the repository's `pr_draft` choice and is
300
+ independent of the run mode: autonomous does not imply draft, and `pr_draft: false` is a supported
301
+ configuration that publishes ready-for-review in every mode. The constraint here is about stopping
302
+ after publication, not about draft-ness.
303
+ After it is recorded, the mandatory local completed handoff in Step 7 still follows and
298
304
  is required in every mode: terminalize, fetch the permitted local refs, archive and verify the control
299
305
  plane, and remove only the guarded sandbox. Autonomous mode never merges an external PR or performs
300
306
  unrelated work after PR recording.
@@ -560,7 +566,7 @@ After derivation, `O` is the physically resolved operator checkout. During boots
560
566
  execution, do not switch, reset, clean, stash, create a branch or worktree, write Git configuration, or
561
567
  initialize factory state directly in `O`. The only operator-checkout operations before the completed
562
568
  handoff are reads and the Step 6 forge command. The explicit Step 7 exclusion applies only after the
563
- draft PR is recorded: its guarded local-ref fetch, archive, verification, and deterministic sandbox
569
+ pull request is recorded: its guarded local-ref fetch, archive, verification, and deterministic sandbox
564
570
  removal remain the sole completed-handoff exception to bootstrap/refusal state preservation.
565
571
 
566
572
  ### Resume or collision
@@ -675,11 +681,19 @@ present and every other result is a lookup error; either refuses before init.
675
681
 
676
682
  An explicit `PR_BASE` wins. Otherwise require the symbolic branch in the configured operator worktree;
677
683
  detached, missing, escaping, or unprovable worktree state is refused by init. Request one fresh sandbox
678
- with the operator repository as `--repo`, command first and repository flag last, and include issue and
679
- admitted mode flags only when present:
684
+ by running exactly the command below, command first, including each bracketed flag only when its value
685
+ is present. Do not reconstruct this command from prose anywhere in this document: the block is the only
686
+ shape, and every host skill carries it verbatim because a driver must run it before this file exists.
687
+
688
+ Two properties of it are not guesses. Init is the one factory command whose repository flag is the
689
+ operator repository `$O` rather than `$RUN_REPO`, because `RUN_REPO` does not exist until this response
690
+ binds it. And `--json` is mandatory and terminal: without it a successful init still changes state and
691
+ publishes `run.json`, but this workflow binds paths only from a JSON response, repeating init is
692
+ forbidden, and the run can then do nothing but stop -- a live sandbox with `status: running` and no
693
+ driver, which is the worst outcome this document has.
680
694
 
681
695
  ```sh
682
- INIT_RESPONSE="$(factory init "$R" --branch "$FEATURE_BRANCH" [--worktree "$WORKTREE"] [--pr-base "$PR_BASE"] [--issue "$KEY"] [--mode "$MODE"] --repo "$O" --json)"
696
+ INIT_RESPONSE="$(factory init "$R" --branch "$FEATURE_BRANCH" [--worktree "$WORKTREE"] [--pr-base "$PR_BASE"] [--issue "$KEY"] [--mode "$MODE"] [--max-retries "$MAX_RETRIES"] --repo "$O" --json)"
683
697
  ```
684
698
 
685
699
  The init request pre-reserves the deterministic sandbox, performs exactly one
@@ -1806,10 +1820,10 @@ command; never move it earlier or present stale evidence.
1806
1820
  The compatibility transition name is `factory gate <run-id> pre_pr pending`; the runnable form is the
1807
1821
  repository-qualified command above.
1808
1822
 
1809
- The draft publication signature is `gh pr create --draft --base "<pr_base>" --head "<branch>" --title "<title>" --body-file "<body-file>"`.
1810
- The ready-for-review publication signature is `gh pr create --base "<pr_base>" --head "<branch>" --title "<title>" --body-file "<body-file>"`.
1823
+ The `PR_DRAFT=true` draft publication signature is `gh pr create --draft --base "<pr_base>" --head "<branch>" --title "<title>" --body-file "<body-file>"`.
1824
+ The `PR_DRAFT=false` ready-for-review publication signature is `gh pr create --base "<pr_base>" --head "<branch>" --title "<title>" --body-file "<body-file>"`.
1811
1825
 
1812
- ## Step 6 — Draft PR
1826
+ ## Step 6 — Draft PR (ready-for-review when `pr_draft` is false)
1813
1827
 
1814
1828
  Immediately before any publication effect, read the delivery intent from the selected run repository,
1815
1829
  then, for a sandbox-selected run, repeat the operator exact-ref-absent and sandbox
@@ -1941,12 +1955,13 @@ whatever mapping the repository documents, and update the tracker only through *
1941
1955
 
1942
1956
  ## Step 7 — Summary and completed sandbox handoff
1943
1957
 
1944
- After draft PR recording, `interactive`, `headless`, and `autonomous` modes all enter this same mandatory
1958
+ After the pull request is recorded -- draft or ready for review, as `pr_draft`
1959
+ selected -- `interactive`, `headless`, and `autonomous` modes all enter this same mandatory
1945
1960
  local completed handoff. In autonomous mode this is the sole narrow exception to the external-side-effect
1946
1961
  stop: perform only the terminalize, local-ref fetch, archive, verification, and guarded sandbox-removal
1947
1962
  sequence below, with no external PR merge or unrelated work after PR recording.
1948
1963
 
1949
- After `factory pr` records the draft PR, stop the heartbeat loop and wait for any heartbeat call already
1964
+ After `factory pr` records the pull request, stop the heartbeat loop and wait for any heartbeat call already
1950
1965
  in flight to return. Before terminalization or any filesystem or Git side effect, require that the loop
1951
1966
  is no longer active and no dispatched agent call remains in flight, directly read and validate exactly
1952
1967
  `RUN_MANIFEST`, and require no step with status `running` and no slice with status `running` or `review`.
@@ -1965,6 +1980,12 @@ Terminalize before any housekeeping, through the repository selected in Step 0:
1965
1980
  factory terminal "$R" completed --reason "draft-pr-recorded" --repo "$RUN_REPO"
1966
1981
  ```
1967
1982
 
1983
+ `draft-pr-recorded` is a fixed protocol token meaning this run's pull request was created and recorded.
1984
+ It does not assert the PR is a draft: a `pr_draft: false` run records a ready-for-review PR and
1985
+ terminalizes with this same reason. Never vary it by mode or by `pr_draft`; downstream consumers match
1986
+ it exactly.
1987
+
1988
+
1968
1989
  Do not replay or retry any handoff phase. A later invocation that finds a completed sandbox reports its
1969
1990
  path for manual recovery and leaves it intact. For the same reason, do not invent durable phase state or
1970
1991
  infer that an interrupted effect is safe to repeat.
@@ -2105,7 +2126,11 @@ Never re-do a side effect the manifest shows already done — ticket creation, p
2105
2126
  answer; do not work around it by editing state.
2106
2127
  - **Bounded loops.** `max_retries` per slice and per step, recorded as attempts. On exhaustion mark
2107
2128
  `blocked` or `partial` with a reason and stop. A bounded loop parks top-level needs-human; explicit resume may repark it if the external cause remains unfixed.
2108
- - **Draft PR only.** Never merge, force-push, or close tickets. Humans merge.
2129
+ Qualified status reports the run's `max_retries`, so the budget a run is actually bounded by is
2130
+ observable rather than assumed: a forwarded `--max-retries` that never reached the manifest is visible
2131
+ as a different number instead of silently running at the default.
2132
+ - **Publish a PR and stop.** Never merge, force-push, or close tickets. Humans merge. Draft or
2133
+ ready-for-review is `pr_draft`'s decision, not this rule's.
2109
2134
  - **Scope discipline and no fabrication.** Flag out-of-scope work at the next gate. Never invent paths,
2110
2135
  keys, versions, or test passes — if the evidence is thin, say so and ask.
2111
2136
  - **A repository may lock its own scope, and a lock is not a defect.** A check whose assertion *is* a
package/bin/factory.js CHANGED
@@ -953,6 +953,11 @@ const HANDLERS = {
953
953
  mode: run.mode,
954
954
  branch: run.branch,
955
955
  pr_base: run.pr_base ?? null,
956
+ // Reported, not defaulted: `max_retries` is a required schema-validated positive integer, so an
957
+ // absent value is an invalid manifest that never reaches here. An operator forwarding
958
+ // `--max-retries` previously had no way to confirm the budget took effect -- init recorded it and
959
+ // nothing read it back.
960
+ max_retries: run.max_retries,
956
961
  publishing_identity: run.publishing_identity ?? null,
957
962
  park_snapshot: run.status === "needs-human" ? observedParkSnapshot(resolve(flags.repo ?? process.cwd()), runId, runDir) : null,
958
963
  pr_draft: run.pr_draft ?? true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feature-factory",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Durable, observed control plane for /feature runs. Host-agnostic: no opencode dependency.",
5
5
  "type": "module",
6
6
  "license": "MIT",