feature-factory 0.8.3 → 0.8.5
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 +47 -20
- package/bin/factory.js +5 -0
- package/package.json +1 -1
package/WORKFLOW.md
CHANGED
|
@@ -99,36 +99,52 @@ must APPROVE before you accept that step. Story, research, and design are not au
|
|
|
99
99
|
|
|
100
100
|
Before any intake action, including ticket, story, or design detection, branch intent, run-id
|
|
101
101
|
derivation, manifest or state reads, and every `factory` command, process the raw invocation arguments
|
|
102
|
-
as follows.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
as follows.
|
|
103
|
+
|
|
104
|
+
**The platform skill owns invocation-option admission, and this workflow never parses the
|
|
105
|
+
invocation.** Each host skill defines the complete leading option prefix its `/feature` invocation
|
|
106
|
+
accepts -- placement, mode, and host options such as `--base` and `--max-retries` -- consumes exactly
|
|
107
|
+
those spans and their separators, and supplies this workflow two things: the **admitted mode tokens**,
|
|
108
|
+
which are the exact case-sensitive `--autonomous` and `--headless` tokens it consumed, and the
|
|
109
|
+
**admitted remainder**, the request bytes beginning at the first token it did not consume, preserved
|
|
110
|
+
unchanged. This workflow never decides where that prefix ends. Placement is not a run mode.
|
|
111
|
+
|
|
112
|
+
Defining a terminator here would contradict the skill that already applied one, and every option later
|
|
113
|
+
added to a host would become request content on this side only. That is not hypothetical. `--base` and
|
|
114
|
+
`--max-retries` were added to the host skills while this section still ended the prefix at the first
|
|
115
|
+
non-mode token, so the two documents disagreed over whether `--max-retries 5 <run-id>` was an option
|
|
116
|
+
pair or part of the run id. Read alone, this section silently derived the run id `max-retries-5-1606`;
|
|
117
|
+
read alongside the skill, a driver correctly refused to run at all. Both documents governing the same
|
|
118
|
+
bytes is the defect, so only one of them does.
|
|
119
|
+
|
|
120
|
+
The rules below are host-independent and are stated over the admitted mode tokens and the admitted
|
|
121
|
+
remainder.
|
|
122
|
+
|
|
123
|
+
1. If both distinct mode tokens were admitted, in either order, return exactly:
|
|
110
124
|
`conflicting mode flags: --autonomous and --headless; choose one`. Return immediately, before any
|
|
111
125
|
intake, run-id derivation, state read, or CLI action. Never fall back to interactive or another
|
|
112
126
|
mode.
|
|
113
|
-
2. Otherwise
|
|
114
|
-
|
|
115
|
-
run-id derivation.
|
|
127
|
+
2. Otherwise use only the unchanged admitted remainder for ticket detection, story content, design
|
|
128
|
+
detection, branch intent, and run-id derivation.
|
|
116
129
|
3. Apply exactly one mapping for a new manifest:
|
|
117
130
|
- `--autonomous` maps only to `factory init --mode autonomous`.
|
|
118
131
|
- `--headless` maps only to `factory init --mode headless`.
|
|
119
|
-
- With no
|
|
132
|
+
- With no admitted mode token, omit `--mode`; existing `factory init` records
|
|
120
133
|
`interactive`.
|
|
121
134
|
|
|
122
|
-
Those three compatibility phrases name init command stems, not runnable invocations. The
|
|
123
|
-
fresh-run invocation is fully qualified in Step 0
|
|
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`.
|
|
124
139
|
|
|
125
|
-
Repeated copies of one
|
|
126
|
-
|
|
140
|
+
Repeated copies of one mode token are idempotent: the skill consumes them all and this workflow
|
|
141
|
+
selects that mode once. A mode token the skill did not admit, standing after the first request token,
|
|
142
|
+
is request content and neither selects nor conflicts.
|
|
127
143
|
Natural-language intent, `--interactive`, capitalization variants, abbreviations, assignment or
|
|
128
144
|
punctuation forms, quoted lookalikes, and near misses are request content, not selectors. Do not add a
|
|
129
145
|
generic malformed-option rejection.
|
|
130
146
|
|
|
131
|
-
After successful nonconflicting admission, reject an empty
|
|
147
|
+
After successful nonconflicting admission, reject an empty or whitespace-only admitted remainder
|
|
132
148
|
with exactly `missing /feature request; no run created.` This rejection and a mode conflict precede
|
|
133
149
|
run-id derivation and every tool, client, state, or CLI action.
|
|
134
150
|
|
|
@@ -661,11 +677,19 @@ present and every other result is a lookup error; either refuses before init.
|
|
|
661
677
|
|
|
662
678
|
An explicit `PR_BASE` wins. Otherwise require the symbolic branch in the configured operator worktree;
|
|
663
679
|
detached, missing, escaping, or unprovable worktree state is refused by init. Request one fresh sandbox
|
|
664
|
-
|
|
665
|
-
|
|
680
|
+
by running exactly the command below, command first, including each bracketed flag only when its value
|
|
681
|
+
is present. Do not reconstruct this command from prose anywhere in this document: the block is the only
|
|
682
|
+
shape, and every host skill carries it verbatim because a driver must run it before this file exists.
|
|
683
|
+
|
|
684
|
+
Two properties of it are not guesses. Init is the one factory command whose repository flag is the
|
|
685
|
+
operator repository `$O` rather than `$RUN_REPO`, because `RUN_REPO` does not exist until this response
|
|
686
|
+
binds it. And `--json` is mandatory and terminal: without it a successful init still changes state and
|
|
687
|
+
publishes `run.json`, but this workflow binds paths only from a JSON response, repeating init is
|
|
688
|
+
forbidden, and the run can then do nothing but stop -- a live sandbox with `status: running` and no
|
|
689
|
+
driver, which is the worst outcome this document has.
|
|
666
690
|
|
|
667
691
|
```sh
|
|
668
|
-
INIT_RESPONSE="$(factory init "$R" --branch "$FEATURE_BRANCH" [--worktree "$WORKTREE"] [--pr-base "$PR_BASE"] [--issue "$KEY"] [--mode "$MODE"] --repo "$O" --json)"
|
|
692
|
+
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)"
|
|
669
693
|
```
|
|
670
694
|
|
|
671
695
|
The init request pre-reserves the deterministic sandbox, performs exactly one
|
|
@@ -2091,6 +2115,9 @@ Never re-do a side effect the manifest shows already done — ticket creation, p
|
|
|
2091
2115
|
answer; do not work around it by editing state.
|
|
2092
2116
|
- **Bounded loops.** `max_retries` per slice and per step, recorded as attempts. On exhaustion mark
|
|
2093
2117
|
`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.
|
|
2118
|
+
Qualified status reports the run's `max_retries`, so the budget a run is actually bounded by is
|
|
2119
|
+
observable rather than assumed: a forwarded `--max-retries` that never reached the manifest is visible
|
|
2120
|
+
as a different number instead of silently running at the default.
|
|
2094
2121
|
- **Draft PR only.** Never merge, force-push, or close tickets. Humans merge.
|
|
2095
2122
|
- **Scope discipline and no fabrication.** Flag out-of-scope work at the next gate. Never invent paths,
|
|
2096
2123
|
keys, versions, or test passes — if the evidence is thin, say so and ask.
|
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,
|