@garygentry/feature-forge 0.2.1 → 0.2.3

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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/adapters/claude/references/forge-config-schema.json +20 -3
  3. package/adapters/claude/references/shared-conventions.md +3 -0
  4. package/adapters/claude/scripts/forge-init.sh +7 -1
  5. package/adapters/claude/scripts/forge-session.py +491 -0
  6. package/adapters/claude/skills/forge/SKILL.md +43 -1
  7. package/adapters/claude/skills/forge-5-loop/SKILL.md +2 -1
  8. package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +41 -15
  9. package/adapters/claude/skills/forge-init/SKILL.md +3 -0
  10. package/adapters/codex/references/forge-config-schema.json +20 -3
  11. package/adapters/codex/references/shared-conventions.md +3 -0
  12. package/adapters/codex/scripts/forge-init.sh +7 -1
  13. package/adapters/codex/scripts/forge-session.py +491 -0
  14. package/adapters/codex/skills/forge/SKILL.md +43 -1
  15. package/adapters/codex/skills/forge-5-loop/SKILL.md +2 -1
  16. package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +41 -15
  17. package/adapters/codex/skills/forge-init/SKILL.md +3 -0
  18. package/adapters/copilot/references/forge-config-schema.json +20 -3
  19. package/adapters/copilot/references/shared-conventions.md +3 -0
  20. package/adapters/copilot/scripts/forge-init.sh +7 -1
  21. package/adapters/copilot/scripts/forge-session.py +491 -0
  22. package/adapters/copilot/skills/forge/forge.md +43 -1
  23. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +2 -1
  24. package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +41 -15
  25. package/adapters/copilot/skills/forge-init/forge-init.md +3 -0
  26. package/adapters/cursor/references/forge-config-schema.json +20 -3
  27. package/adapters/cursor/references/shared-conventions.md +3 -0
  28. package/adapters/cursor/scripts/forge-init.sh +7 -1
  29. package/adapters/cursor/scripts/forge-session.py +491 -0
  30. package/adapters/cursor/skills/forge/forge.mdc +43 -1
  31. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +2 -1
  32. package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +41 -15
  33. package/adapters/cursor/skills/forge-init/forge-init.mdc +3 -0
  34. package/adapters/gemini/references/forge-config-schema.json +20 -3
  35. package/adapters/gemini/references/shared-conventions.md +3 -0
  36. package/adapters/gemini/scripts/forge-init.sh +7 -1
  37. package/adapters/gemini/scripts/forge-session.py +491 -0
  38. package/adapters/gemini/skills/forge/forge.md +43 -1
  39. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +2 -1
  40. package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +41 -15
  41. package/adapters/gemini/skills/forge-init/forge-init.md +3 -0
  42. package/dist/manifest.d.ts +1 -1
  43. package/dist/rauf.d.ts +4 -4
  44. package/dist/rauf.js +3 -3
  45. package/dist/types.d.ts +1 -1
  46. package/package.json +1 -1
@@ -121,8 +121,7 @@ user requests additional flags, append them to the rendered run command.
121
121
  ## Launch detail (Step 3b — background process)
122
122
 
123
123
  Launch the loop **backgrounded** so it survives session end and does not block the
124
- session, and prefer the machine-readable event stream so the session can supervise
125
- it live.
124
+ session, then supervise it live via the runner's structured event file.
126
125
 
127
126
  > **Clean-tree precondition.** rauf refuses to run with uncommitted changes
128
127
  > (*"Refusing to run the loop with uncommitted changes… pass --force"*). Step 3a's
@@ -132,22 +131,41 @@ it live.
132
131
  > changes after that commit, surface it and let the user commit/stash or pass
133
132
  > `--force`; never auto-pass `--force`.
134
133
 
135
- - **If `loopRunner.eventStreamCommand` is configured (default for rauf):** render it
136
- (it appends `--ndjson` to the run) and launch via the Bash tool with
137
- `run_in_background: true`, redirecting stdout to a stable events file:
134
+ **Do NOT redirect the run's stdout into `{loopRunner.stateDir}`.** rauf **persists
135
+ its own** `{stateDir}/events.ndjson` (structured) and `{stateDir}/{logFile}` (human)
136
+ natively, and **rotates** them at the start of every run (the prior run's files are
137
+ renamed into `{stateDir}/archive/`). A redirect like `… --ndjson >
138
+ {stateDir}/events.ndjson` therefore (a) is **redundant** — the runner writes that
139
+ file regardless — and (b) **collides** with the runner's own writer: the shell holds
140
+ a descriptor on the file the runner immediately rotates away, so the redirected
141
+ `--ndjson` stdout is orphaned into a bogus `archive/` file while the live
142
+ `events.ndjson` is the runner's native stream. It only *looks* clean by accident of
143
+ rotation timing. So:
144
+
145
+ - **Self-persisting runner (default — rauf writes `{stateDir}/events.ndjson`):**
146
+ launch the **plain `runCommand`** with `run_in_background: true` and **no
147
+ redirect** — the Bash tool already captures the run's stdout/stderr to the
148
+ background task's output file (use it to diagnose a launch refusal). Supervise by
149
+ arming the Monitor on the runner's **native** `{backlogDir}/{stateDir}/events.ndjson`
150
+ (Step 3d). Guard the very first run with the state dir:
138
151
 
139
152
  ```
140
- mkdir -p {backlogDir}/{loopRunner.stateDir} && {rendered eventStreamCommand} > {backlogDir}/{loopRunner.stateDir}/events.ndjson 2>&1
153
+ mkdir -p {backlogDir}/{loopRunner.stateDir} && {rendered runCommand}
141
154
  ```
142
155
 
143
- (The `mkdir -p` guards the very first run, before the runner has created its
144
- state dir.) This emits one JSON event per line **and** keeps the loop detached. The background
145
- task's exit notification remains the single authoritative terminal signal (Step 4).
146
- - **Fallback (runner has no `eventStreamCommand`):** launch the plain `runCommand`
147
- with `run_in_background: true`. The session will then supervise by tailing the
148
- human log (3d fallback) instead of the NDJSON file.
156
+ (Note: the `--ndjson` stdout stream and `loopRunner.eventStreamCommand` are **not**
157
+ used on this path — the native file already carries the same structured records.)
158
+ - **Stdout-only runner (no native event file):** render `eventStreamCommand` (it adds
159
+ `--ndjson`) and redirect its stdout to a file **outside `{stateDir}`** so it cannot
160
+ collide with any native file or be swept into `archive/`, then Monitor that file:
149
161
 
150
- Loop runs can take significant time (minutes to hours depending on backlog size).
162
+ ```
163
+ mkdir -p {backlogDir}/{loopRunner.stateDir} && {rendered eventStreamCommand} > {backlogDir}/forge-events.ndjson 2>&1
164
+ ```
165
+
166
+ The background task's exit notification remains the single authoritative terminal
167
+ signal (Step 4). Loop runs can take significant time (minutes to hours depending on
168
+ backlog size).
151
169
 
152
170
  ## Arm a Monitor on the event stream (Step 3d)
153
171
 
@@ -161,16 +179,24 @@ terminal and exception state, not just the happy path — otherwise a crash or h
161
179
  looks identical to "still running." Monitor command (NDJSON path):
162
180
 
163
181
  ```
164
- tail -n +1 -f {backlogDir}/{loopRunner.stateDir}/events.ndjson 2>&1 \
182
+ tail -n +1 -F {backlogDir}/{loopRunner.stateDir}/events.ndjson 2>/dev/null \
165
183
  | jq -rc --unbuffered 'select(.type | test("item_completed|item_blocked|needs_human|signal_parsed|loop_completed|loop_error|loop_cancelled|llm_stuck_warning"))'
166
184
  ```
167
185
 
186
+ > **Use `tail -F` (follow by name), not `-f` (follow by descriptor).** The runner
187
+ > **rotates** `events.ndjson` at the start of each run (renames the prior file into
188
+ > `archive/`, creates a fresh one). A Monitor that attaches with `-f` during that
189
+ > brief rotation window would follow the **archived** inode and then see silence —
190
+ > indistinguishable from a healthy quiet loop. `-F` re-opens the live file by name,
191
+ > so it always tracks the runner's current native stream. (Send `tail`'s own
192
+ > rotation chatter to `/dev/null` so it can't reach the `jq` filter.)
193
+
168
194
  - **Fallback (log tail, no NDJSON):** match the runner's **structured prose
169
195
  prefixes**, never the `RAUF_*` tokens (those leak inside agent output and
170
196
  false-match). For rauf:
171
197
 
172
198
  ```
173
- tail -n +1 -f {backlogDir}/{loopRunner.stateDir}/{loopRunner.logFile} \
199
+ tail -n +1 -F {backlogDir}/{loopRunner.stateDir}/{loopRunner.logFile} 2>/dev/null \
174
200
  | grep -E --line-buffered 'Item [^ ]+ (completed|blocked):|Item [^ ]+ needs human input|Loop completed|Loop error:|Circuit breaker:'
175
201
  ```
176
202
 
@@ -23,6 +23,9 @@ After initialization, the config file will contain defaults for:
23
23
  - `stack`: `null` (detected during `/feature-forge:forge-2-tech`)
24
24
  - `typeCheckCommand`: `null` (set during `/feature-forge:forge-2-tech`)
25
25
  - `testCommand`: `null` (set during `/feature-forge:forge-2-tech`)
26
+ - `autoInvokeNextStage`: `true` (the navigator auto-starts the next stage after you confirm; set `false` to only print the command)
27
+ - `contextWindowTokens`: `null` (the navigator infers the context window; set to your model's window, e.g. `1000000` for a 1M-context model, for accurate context-usage advice)
28
+ - `contextWarnThreshold`: `0.7` (fraction of the window past which the navigator suggests a clean session)
26
29
 
27
30
  If `forge.config.json` already exists, the script will not overwrite it.
28
31
 
@@ -28,7 +28,7 @@ export interface BuildManifestArgs {
28
28
  readonly skills: readonly string[];
29
29
  /** SHA-256 over the source bundle's canonical (sorted-path) file set — drift anchor (spec 03). */
30
30
  readonly sourceHash: string;
31
- /** Recorded pinned rauf coordinate (e.g. "@garygentry/rauf@0.8.1"); `null` when `--skip-rauf` (spec 06). */
31
+ /** Recorded pinned rauf coordinate (e.g. "@garygentry/rauf@0.11.0"); `null` when `--skip-rauf` (spec 06). */
32
32
  readonly raufPin: string | null;
33
33
  /** Symlink mode only: the source bundle the namespace dir links to (REQ-SAFE-02). */
34
34
  readonly link?: {
package/dist/rauf.d.ts CHANGED
@@ -19,13 +19,13 @@ import { type Result } from "./types.js";
19
19
  *
20
20
  * Shape: `<name>@<version>` — the SCOPED package `@garygentry/rauf` (the unscoped `rauf` name is
21
21
  * blocked by npm's similarity filter). Advanced on each feature-forge release to a new
22
- * known-compatible rauf (REQ-RAUF-03). The current rauf version is 0.8.1.
22
+ * known-compatible rauf (REQ-RAUF-03). The current rauf version is 0.11.0.
23
23
  *
24
- * rauf is now PUBLISHED (rauf#28): `@garygentry/rauf@0.8.1` resolves from the npm registry, so the
24
+ * rauf is now PUBLISHED (rauf#28): `@garygentry/rauf@0.11.0` resolves from the npm registry, so the
25
25
  * preflight below passes by default. (Historically this pin pointed at an unpublished package and
26
26
  * the preflight was a designed-to-fail check — see the `--skip-rauf` escape hatch.)
27
27
  */
28
- export declare const RAUF_PIN = "@garygentry/rauf@0.8.1";
28
+ export declare const RAUF_PIN = "@garygentry/rauf@0.11.0";
29
29
  /**
30
30
  * An injectable, READ-ONLY registry query (D1). Given a coordinate `name@version`, returns the
31
31
  * resolved version string on success, or an `InstallerError` if it is not resolvable.
@@ -37,7 +37,7 @@ export declare const RAUF_PIN = "@garygentry/rauf@0.8.1";
37
37
  * Contract: the query MUST be read-only — it MUST NOT install, MUST NOT mutate global npm
38
38
  * state, and MUST NOT execute rauf. `npm view` satisfies this (it only reads registry metadata).
39
39
  *
40
- * @param coordinate - the `name@version` to resolve, e.g. "@garygentry/rauf@0.8.1"
40
+ * @param coordinate - the `name@version` to resolve, e.g. "@garygentry/rauf@0.11.0"
41
41
  * @returns Result<string> — the resolved version on success; RAUF_UNRESOLVABLE on failure.
42
42
  */
43
43
  export type RegistryQuery = (coordinate: string) => Result<string>;
package/dist/rauf.js CHANGED
@@ -20,13 +20,13 @@ import { err, ok } from "./types.js";
20
20
  *
21
21
  * Shape: `<name>@<version>` — the SCOPED package `@garygentry/rauf` (the unscoped `rauf` name is
22
22
  * blocked by npm's similarity filter). Advanced on each feature-forge release to a new
23
- * known-compatible rauf (REQ-RAUF-03). The current rauf version is 0.8.1.
23
+ * known-compatible rauf (REQ-RAUF-03). The current rauf version is 0.11.0.
24
24
  *
25
- * rauf is now PUBLISHED (rauf#28): `@garygentry/rauf@0.8.1` resolves from the npm registry, so the
25
+ * rauf is now PUBLISHED (rauf#28): `@garygentry/rauf@0.11.0` resolves from the npm registry, so the
26
26
  * preflight below passes by default. (Historically this pin pointed at an unpublished package and
27
27
  * the preflight was a designed-to-fail check — see the `--skip-rauf` escape hatch.)
28
28
  */
29
- export const RAUF_PIN = "@garygentry/rauf@0.8.1";
29
+ export const RAUF_PIN = "@garygentry/rauf@0.11.0";
30
30
  /**
31
31
  * Resolvability preflight for the pinned default loop runner (D1; REQ-RAUF-01/02/03, OQ-1).
32
32
  *
package/dist/types.d.ts CHANGED
@@ -216,7 +216,7 @@ export interface InstallManifest {
216
216
  readonly featureForgeVersion: string | null;
217
217
  /** SHA-256 over the source bundle's canonical (sorted-path) file set — drift anchor (OQ-4, spec 03). */
218
218
  readonly sourceHash: string;
219
- /** Pinned rauf coordinate recorded at install, e.g. "@garygentry/rauf@0.8.1"; `null` if `--skip-rauf` (spec 06). */
219
+ /** Pinned rauf coordinate recorded at install, e.g. "@garygentry/rauf@0.11.0"; `null` if `--skip-rauf` (spec 06). */
220
220
  readonly raufPin: string | null;
221
221
  /** ISO-8601 timestamps. */
222
222
  readonly installedAt: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garygentry/feature-forge",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Cross-agent installer for the feature-forge skill suite — installs the canonical forge pipeline into Claude, Codex, Copilot, Cursor, or Gemini.",
5
5
  "license": "MIT",
6
6
  "type": "module",