@garygentry/feature-forge 0.2.9 → 0.2.11
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/adapters/claude/.feature-forge-bundle.json +1 -1
- package/adapters/claude/references/pipeline-state-schema.json +37 -1
- package/adapters/claude/references/shared-conventions.md +22 -8
- package/adapters/claude/references/stage-exit-protocol.md +18 -0
- package/adapters/claude/references/templates/specs-hygiene/AGENTS.md +9 -0
- package/adapters/claude/references/templates/specs-hygiene/CLAUDE.md +9 -0
- package/adapters/claude/scripts/forge-session.py +41 -0
- package/adapters/claude/skills/forge-0-epic/SKILL.md +2 -0
- package/adapters/claude/skills/forge-1-prd/SKILL.md +1 -1
- package/adapters/claude/skills/forge-2-tech/SKILL.md +2 -0
- package/adapters/claude/skills/forge-3-specs/SKILL.md +3 -1
- package/adapters/claude/skills/forge-4-backlog/SKILL.md +2 -0
- package/adapters/claude/skills/forge-5-loop/SKILL.md +1 -1
- package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +22 -2
- package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +11 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +11 -0
- package/adapters/codex/.feature-forge-bundle.json +1 -1
- package/adapters/codex/references/pipeline-state-schema.json +37 -1
- package/adapters/codex/references/shared-conventions.md +22 -8
- package/adapters/codex/references/stage-exit-protocol.md +18 -0
- package/adapters/codex/references/templates/specs-hygiene/AGENTS.md +9 -0
- package/adapters/codex/references/templates/specs-hygiene/CLAUDE.md +9 -0
- package/adapters/codex/scripts/forge-session.py +41 -0
- package/adapters/codex/skills/forge-0-epic/SKILL.md +2 -0
- package/adapters/codex/skills/forge-1-prd/SKILL.md +1 -1
- package/adapters/codex/skills/forge-2-tech/SKILL.md +2 -0
- package/adapters/codex/skills/forge-3-specs/SKILL.md +3 -1
- package/adapters/codex/skills/forge-4-backlog/SKILL.md +2 -0
- package/adapters/codex/skills/forge-5-loop/SKILL.md +1 -1
- package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +22 -2
- package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +11 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +11 -0
- package/adapters/copilot/.feature-forge-bundle.json +1 -1
- package/adapters/copilot/references/pipeline-state-schema.json +37 -1
- package/adapters/copilot/references/shared-conventions.md +22 -8
- package/adapters/copilot/references/stage-exit-protocol.md +18 -0
- package/adapters/copilot/references/templates/specs-hygiene/AGENTS.md +9 -0
- package/adapters/copilot/references/templates/specs-hygiene/CLAUDE.md +9 -0
- package/adapters/copilot/scripts/forge-session.py +41 -0
- package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +2 -0
- package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +1 -1
- package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +2 -0
- package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +3 -1
- package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +2 -0
- package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +1 -1
- package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +22 -2
- package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +11 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +11 -0
- package/adapters/cursor/.feature-forge-bundle.json +1 -1
- package/adapters/cursor/references/pipeline-state-schema.json +37 -1
- package/adapters/cursor/references/shared-conventions.md +22 -8
- package/adapters/cursor/references/stage-exit-protocol.md +18 -0
- package/adapters/cursor/references/templates/specs-hygiene/AGENTS.md +9 -0
- package/adapters/cursor/references/templates/specs-hygiene/CLAUDE.md +9 -0
- package/adapters/cursor/scripts/forge-session.py +41 -0
- package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +2 -0
- package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +1 -1
- package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +2 -0
- package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +3 -1
- package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +2 -0
- package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +1 -1
- package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +22 -2
- package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +11 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +11 -0
- package/adapters/gemini/.feature-forge-bundle.json +1 -1
- package/adapters/gemini/gemini-extension.json +1 -1
- package/adapters/gemini/references/pipeline-state-schema.json +37 -1
- package/adapters/gemini/references/shared-conventions.md +22 -8
- package/adapters/gemini/references/stage-exit-protocol.md +18 -0
- package/adapters/gemini/references/templates/specs-hygiene/AGENTS.md +9 -0
- package/adapters/gemini/references/templates/specs-hygiene/CLAUDE.md +9 -0
- package/adapters/gemini/scripts/forge-session.py +41 -0
- package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +2 -0
- package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +1 -1
- package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +2 -0
- package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +3 -1
- package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +2 -0
- package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +1 -1
- package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +22 -2
- package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +11 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +11 -0
- package/package.json +1 -1
|
@@ -19,4 +19,13 @@ traceability matrices, and per-feature `backlog.json` files).
|
|
|
19
19
|
skills/agents, configs, docs) should be self-contained and should **not** reference
|
|
20
20
|
files under `specs/`, which may be archived or deleted after a feature ships.
|
|
21
21
|
|
|
22
|
+
## Tooling feedback
|
|
23
|
+
|
|
24
|
+
Friction with the feature-forge pipeline or the rauf loop — anything confusing, buggy, or
|
|
25
|
+
missing? Help me capture it while fresh and file it (feature-forge →
|
|
26
|
+
https://github.com/garygentry/feature-forge/issues, rauf →
|
|
27
|
+
https://github.com/garygentry/rauf/issues). See the project-root `CLAUDE.md` "Tooling
|
|
28
|
+
feedback" section for the full flow. In an autonomous rauf iteration, note it in
|
|
29
|
+
`progress.md` instead of opening an issue mid-loop.
|
|
30
|
+
|
|
22
31
|
This file was generated by feature-forge. Edit or remove it to suit your project.
|
|
@@ -66,6 +66,7 @@ from __future__ import annotations
|
|
|
66
66
|
|
|
67
67
|
import argparse
|
|
68
68
|
import json
|
|
69
|
+
import os
|
|
69
70
|
import subprocess
|
|
70
71
|
import sys
|
|
71
72
|
from datetime import datetime, timezone
|
|
@@ -210,6 +211,12 @@ def next_stage(state: dict) -> str | None:
|
|
|
210
211
|
status is not ``complete`` (a missing/pending/in-progress/stale stage all
|
|
211
212
|
count as "not done"). Returns ``None`` when every production stage is
|
|
212
213
|
complete (nothing left to run).
|
|
214
|
+
|
|
215
|
+
This is the derived "what runs next" value — the single source of truth for
|
|
216
|
+
the next stage. It is intentionally distinct from the stored
|
|
217
|
+
``currentStage`` field ("where the pipeline IS"; see the schema): the next
|
|
218
|
+
stage is computed from ``stages[].status`` here, never read from
|
|
219
|
+
``currentStage``.
|
|
213
220
|
"""
|
|
214
221
|
for stage in PRODUCTION_STAGES:
|
|
215
222
|
if _stage_status(state, stage) != _DONE_STATUS:
|
|
@@ -348,6 +355,9 @@ def build_rows(specs_dir: Path, config: dict | None = None) -> list[FeatureRow]:
|
|
|
348
355
|
rows.append({
|
|
349
356
|
"name": name,
|
|
350
357
|
"epic": epic,
|
|
358
|
+
# currentStage = "where the pipeline IS" (the recorded field). When a
|
|
359
|
+
# legacy/absent state omits it, fall back to the DERIVED next stage
|
|
360
|
+
# for display only — never conflate the two elsewhere (schema O1).
|
|
351
361
|
"currentStage": state.get("currentStage") or (nxt or "complete"),
|
|
352
362
|
"branch": branch if isinstance(branch, str) else None,
|
|
353
363
|
"updatedAt": updated if isinstance(updated, str) else None,
|
|
@@ -710,6 +720,27 @@ def doctor_report(specs_dir: Path, config_path: Path) -> dict:
|
|
|
710
720
|
"counts": _counts(specs_dir),
|
|
711
721
|
"features": features,
|
|
712
722
|
"invalidAutoVerifyKeys": invalid_auto_verify_keys(config),
|
|
723
|
+
"rootSandbox": _root_sandbox_status(),
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
def _root_sandbox_status() -> dict:
|
|
728
|
+
"""Report the root/sandbox launch condition for forge-5-loop (issue #99).
|
|
729
|
+
|
|
730
|
+
On a hosted remote (e.g. Claude.ai) the loop runs as root, where rauf's
|
|
731
|
+
``claude --dangerously-skip-permissions`` is refused unless ``IS_SANDBOX``
|
|
732
|
+
is set. forge-5-loop exports ``IS_SANDBOX=${IS_SANDBOX:-1}`` at launch when
|
|
733
|
+
root; this surfaces the same condition as a diagnosable check. ``geteuid``
|
|
734
|
+
is absent on Windows — treat that as non-root.
|
|
735
|
+
"""
|
|
736
|
+
geteuid = getattr(os, "geteuid", None)
|
|
737
|
+
is_root = geteuid() == 0 if geteuid is not None else False
|
|
738
|
+
is_sandbox_set = os.environ.get("IS_SANDBOX") not in (None, "")
|
|
739
|
+
return {
|
|
740
|
+
"isRoot": is_root,
|
|
741
|
+
"isSandboxSet": is_sandbox_set,
|
|
742
|
+
# True only when the loop would need to supply the default at launch.
|
|
743
|
+
"loopWillSetSandbox": is_root and not is_sandbox_set,
|
|
713
744
|
}
|
|
714
745
|
|
|
715
746
|
|
|
@@ -756,6 +787,16 @@ def _print_doctor(report: dict) -> None:
|
|
|
756
787
|
invalid = report.get("invalidAutoVerifyKeys") or []
|
|
757
788
|
if invalid:
|
|
758
789
|
print(" ! invalid autoVerifyStages keys (ignored): " + ", ".join(invalid))
|
|
790
|
+
rs = report.get("rootSandbox") or {}
|
|
791
|
+
if rs.get("isRoot"):
|
|
792
|
+
if rs.get("isSandboxSet"):
|
|
793
|
+
print("root/sandbox: running as root; IS_SANDBOX already set — loop launch OK")
|
|
794
|
+
else:
|
|
795
|
+
print(
|
|
796
|
+
"root/sandbox: running as root; IS_SANDBOX not set — forge-5-loop will "
|
|
797
|
+
"export IS_SANDBOX=1 at launch so rauf's "
|
|
798
|
+
"--dangerously-skip-permissions is not refused"
|
|
799
|
+
)
|
|
759
800
|
|
|
760
801
|
|
|
761
802
|
# --------------------------------------------------------------------------- #
|
|
@@ -68,6 +68,8 @@ Resolve the epic subtree path `{specsDir}/{epic}/` and decide which branch to ru
|
|
|
68
68
|
- **NEW** (no `epic-manifest.json`) → **Creation branch** (Step C1 onward).
|
|
69
69
|
- **EXISTS** → **Edit branch** (§ Edit Mode below).
|
|
70
70
|
|
|
71
|
+
This manifest-existence dispatch **is** forge-0-epic's stage-entry guard: a re-entry on an existing epic lands in Edit Mode (helper-mutated, re-validated) rather than re-running the creation interview, so the **Stage-Entry Guard** block used by `forge-1-prd`..`forge-4-backlog` does not apply here (an epic has no self `.pipeline-state.json` to stamp — it writes member states).
|
|
72
|
+
|
|
71
73
|
3. **Pre-flight epic-name uniqueness (creation only).** Before composing anything for a NEW
|
|
72
74
|
epic, confirm the epic name itself does not collide with any existing feature or epic:
|
|
73
75
|
|
|
@@ -19,7 +19,7 @@ Invoke the **Branch Setup** block in `references/shared-conventions.md` with `{l
|
|
|
19
19
|
|
|
20
20
|
Set the working directory by invoking the **Feature Directory Resolution** block in `references/shared-conventions.md`, which yields `{resolvedFeatureDir}`. Note one PRD-specific caveat: at PRD time a brand-new standalone feature may have NO directory yet, so resolution is expected to fail `not-found` for a never-started standalone feature — in that case forge-1 creates `{specsDir}/{feature}/` as today. For an epic member the directory already exists (created empty by forge-0-epic with an `epic` back-pointer), so resolution succeeds and yields the nested path.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
After resolution, invoke the **Stage-Entry Guard** block in `references/shared-conventions.md` with `{stage}` = `forge-1-prd`. It classifies re-entry (fresh / interrupted / re-authoring), runs the resume-vs-restart gate and the "create a new version?" warning as applicable, and applies the entry stamp on the authoring paths. For a brand-new standalone feature there is no state file yet, so the guard's **fresh** arm applies with nothing to prompt; the entry stamp lands when the state file is first created in Step 6.
|
|
23
23
|
|
|
24
24
|
## Step 2: Examine Existing Context
|
|
25
25
|
|
|
@@ -18,6 +18,8 @@ Read and follow `references/shared-conventions.md` for feature name validation,
|
|
|
18
18
|
|
|
19
19
|
**Prerequisite check:** Read `{resolvedFeatureDir}/.pipeline-state.json`. If not in force mode and `forge-1-prd` is not `complete`, STOP and tell the user: "The PRD for '{feature}' isn't complete yet. Run `/feature-forge:forge-1-prd {feature}` first."
|
|
20
20
|
|
|
21
|
+
After the prerequisite check, invoke the **Stage-Entry Guard** block in `references/shared-conventions.md` with `{stage}` = `forge-2-tech` — it detects an interrupted or already-complete tech-spec, runs the resume/restart or new-version gate, and stamps `status: "in-progress"` + `startedAt` + `currentStage` before the research and interview.
|
|
22
|
+
|
|
21
23
|
Read `{resolvedFeatureDir}/PRD.md` into context. This is your foundation — every technology decision must trace back to a PRD requirement.
|
|
22
24
|
|
|
23
25
|
After reading the PRD, invoke the **Epic Context Injection** block in `references/shared-conventions.md`. It self-gates on the resolved feature's `epic` back-pointer: for a standalone feature it is a no-op; for an epic member it loads EPIC.md, this feature's charter, and the completed direct dependencies' specs into context before the research and interview.
|
|
@@ -20,6 +20,8 @@ Read and follow `references/shared-conventions.md` for feature name validation,
|
|
|
20
20
|
|
|
21
21
|
**Prerequisite check:** Read `{resolvedFeatureDir}/.pipeline-state.json`. If not in force mode, both `forge-1-prd` and `forge-2-tech` must be `complete`. If not, STOP and tell the user which prerequisites are missing.
|
|
22
22
|
|
|
23
|
+
After the prerequisite check, invoke the **Stage-Entry Guard** block in `references/shared-conventions.md` with `{stage}` = `forge-3-specs`. Because this stage writes a suite incrementally, the guard's **interrupted** arm uses the `stages.forge-3-specs.artifacts` array (already updated after each spec file — Step 3) to resume from the first unwritten document rather than regenerating the whole suite.
|
|
24
|
+
|
|
23
25
|
Read both `{resolvedFeatureDir}/PRD.md` and `{resolvedFeatureDir}/tech-spec.md` into context.
|
|
24
26
|
|
|
25
27
|
After reading the PRD and tech spec, invoke the **Epic Context Injection** block in `references/shared-conventions.md`. It self-gates on the resolved feature's `epic` back-pointer: for a standalone feature it is a no-op; for an epic member it loads EPIC.md, this feature's charter, and the completed direct dependencies' specs into context before the spec suite is planned.
|
|
@@ -55,7 +57,7 @@ Feature-specific:
|
|
|
55
57
|
|
|
56
58
|
**Then call the host's question mechanism** following the **Decision Support** protocol in `references/shared-conventions.md`: recommend this plan as the default (it's your evidence-backed read of the feature's complexity) and name the trade-off so the user can push back knowingly — more documents means finer separation of concerns but more to keep in sync; fewer means tighter docs but risks one document carrying multiple concerns. Lead with: "I recommend this plan. Add or remove any documents?" Note the guidance below — resist splitting a concern into a sub-50-line document.
|
|
57
59
|
|
|
58
|
-
**Incremental artifact tracking:** After each spec document is written (by you or a writer subagent), immediately update the `artifacts` array in `.pipeline-state.json` with the new file path. This enables crash recovery if the session is interrupted mid-suite (see shared-conventions.md "
|
|
60
|
+
**Incremental artifact tracking:** After each spec document is written (by you or a writer subagent), immediately update the `artifacts` array in `.pipeline-state.json` with the new file path. This enables crash recovery if the session is interrupted mid-suite (see shared-conventions.md "Stage-Entry Guard").
|
|
59
61
|
|
|
60
62
|
## Step 4: Write the Spec Suite
|
|
61
63
|
|
|
@@ -38,6 +38,8 @@ Resolve the **loop runner** from the `loopRunner` block in `forge.config.json`,
|
|
|
38
38
|
|
|
39
39
|
**Prerequisite check:** Read `{resolvedFeatureDir}/.pipeline-state.json`. If not in force mode, stages `forge-1-prd`, `forge-2-tech`, and `forge-3-specs` must all be `complete`. If not, STOP and tell the user which prerequisites are missing.
|
|
40
40
|
|
|
41
|
+
After the prerequisite check, invoke the **Stage-Entry Guard** block in `references/shared-conventions.md` with `{stage}` = `forge-4-backlog` — it detects an interrupted or complete `backlog.json`, runs the resume/restart or new-version gate, and stamps entry before Step 2 loads the specs. (The backlog is a single artifact, so "resume" means: reuse the existing `backlog.json` if the previous run wrote it, rather than re-authoring from scratch.)
|
|
42
|
+
|
|
41
43
|
**Verification check.** Check whether the specs have been verified. If not, use the host's question mechanism to warn with the cost of skipping: "Specs haven't been verified yet. Recommended: run `/feature-forge:forge-verify {feature}` first — unverified specs can carry gaps or contradictions that get baked into backlog items and only surface mid-loop, where they're far more expensive to fix. Continue anyway?" Offer **Verify first (recommended)** · **Continue without verifying**.
|
|
42
44
|
|
|
43
45
|
## Step 2: Load All Specs
|
|
@@ -196,7 +196,7 @@ Then commit this state write before launching (mandatory). The runner refuses to
|
|
|
196
196
|
|
|
197
197
|
### 3b. Launch Background Process
|
|
198
198
|
|
|
199
|
-
Launch the loop **backgrounded** (the host's background-execution mechanism) so it survives session end and does not block the session. For a runner that **persists its own structured event file** (the default — rauf writes `{stateDir}/events.ndjson` natively and rotates it per run), launch the **plain `runCommand`** with **no stdout redirect** and supervise the runner's **native** `events.ndjson` directly; do **not** redirect `--ndjson` into `{stateDir}` (it is redundant and collides with the runner's own writer — see `references/runner-contract.md`). Only a stdout-only runner (no native event file) uses `eventStreamCommand`, redirected to a file **outside** `{stateDir}`. The background task's exit notification is the single authoritative terminal signal (Step 4). Loop runs can take significant time (minutes to hours depending on backlog size). For the exact launch commands (incl. the `mkdir -p` state-dir guard) and the self-persisting vs. stdout-only detail, read `references/runner-contract.md`.
|
|
199
|
+
Launch the loop **backgrounded** (the host's background-execution mechanism) so it survives session end and does not block the session. For a runner that **persists its own structured event file** (the default — rauf writes `{stateDir}/events.ndjson` natively and rotates it per run), launch the **plain `runCommand`** with **no stdout redirect** and supervise the runner's **native** `events.ndjson` directly; do **not** redirect `--ndjson` into `{stateDir}` (it is redundant and collides with the runner's own writer — see `references/runner-contract.md`). Only a stdout-only runner (no native event file) uses `eventStreamCommand`, redirected to a file **outside** `{stateDir}`. The background task's exit notification is the single authoritative terminal signal (Step 4). Loop runs can take significant time (minutes to hours depending on backlog size). For the exact launch commands (incl. the `mkdir -p` state-dir guard and the root→`IS_SANDBOX` sandbox guard) and the self-persisting vs. stdout-only detail, read `references/runner-contract.md`.
|
|
200
200
|
|
|
201
201
|
### 3c. Inform User
|
|
202
202
|
|
|
@@ -101,6 +101,13 @@ default / `claude-cli` path skips this guard (the aliases are valid there).
|
|
|
101
101
|
> rauf `author-backlog` skill to keep `model` **provider-neutral** by default (or to
|
|
102
102
|
> document that writing a tier alias binds the backlog to Claude agents). That lives
|
|
103
103
|
> in the separate rauf plugin/repo, not feature-forge; tracked as a follow-up.
|
|
104
|
+
>
|
|
105
|
+
> **Follow-up (out of scope here — rauf repo).** The durable fix for the root/sandbox
|
|
106
|
+
> refusal (see "Root/sandbox env guard" under Step 3b) is for **rauf itself** to honor
|
|
107
|
+
> `IS_SANDBOX` when it launches `claude --dangerously-skip-permissions` as root (or to
|
|
108
|
+
> detect root+flag-refused and emit a clear error instead of an opaque circuit-break).
|
|
109
|
+
> feature-forge's launch-time export is the mitigation; the upstream fix lives in the
|
|
110
|
+
> rauf plugin/repo. Track as a follow-up.
|
|
104
111
|
|
|
105
112
|
## Optional flags catalog (Step 2d, rauf)
|
|
106
113
|
|
|
@@ -131,6 +138,19 @@ session, then supervise it live via the runner's structured event file.
|
|
|
131
138
|
> changes after that commit, surface it and let the user commit/stash or pass
|
|
132
139
|
> `--force`; never auto-pass `--force`.
|
|
133
140
|
|
|
141
|
+
> **Root/sandbox env guard.** On a hosted remote (e.g. Claude.ai) the loop often runs
|
|
142
|
+
> **as root**. rauf's default Claude launch is `claude -p --dangerously-skip-permissions
|
|
143
|
+
> …`, which the Claude CLI **refuses under root unless `IS_SANDBOX` is set** — the remote
|
|
144
|
+
> container is a legitimate ephemeral sandbox, but without the flag every spawn exits and
|
|
145
|
+
> rauf circuit-breaks (*"3 consecutive infra failures — halting"*) with no hint of the
|
|
146
|
+
> cause. So when — and only when — the launcher is root (`[ "$(id -u)" = 0 ]`), export
|
|
147
|
+
> `IS_SANDBOX="${IS_SANDBOX:-1}"` in front of the launch (an explicitly-set value is
|
|
148
|
+
> honored; the `:-1` only supplies a default). Non-root/local runs are unaffected — the
|
|
149
|
+
> guard is a no-op. **Surface a one-line note** when you set it — e.g. *"running as root →
|
|
150
|
+
> setting IS_SANDBOX=1 so the sandboxed runner can use --dangerously-skip-permissions"* —
|
|
151
|
+
> so the behavior is never silent. `forge-session.py doctor` also reports this condition.
|
|
152
|
+
> Both launch commands below already carry the guard.
|
|
153
|
+
|
|
134
154
|
**Do NOT redirect the run's stdout into `{loopRunner.stateDir}`.** rauf **persists
|
|
135
155
|
its own** `{stateDir}/events.ndjson` (structured) and `{stateDir}/{logFile}` (human)
|
|
136
156
|
natively, and **rotates** them at the start of every run (the prior run's files are
|
|
@@ -150,7 +170,7 @@ rotation timing. So:
|
|
|
150
170
|
(Step 3d). Guard the very first run with the state dir:
|
|
151
171
|
|
|
152
172
|
```
|
|
153
|
-
mkdir -p {backlogDir}/{loopRunner.stateDir} && {rendered runCommand}
|
|
173
|
+
mkdir -p {backlogDir}/{loopRunner.stateDir} && { [ "$(id -u)" = 0 ] && export IS_SANDBOX="${IS_SANDBOX:-1}" || true; } && {rendered runCommand}
|
|
154
174
|
```
|
|
155
175
|
|
|
156
176
|
(Note: the `--ndjson` stdout stream and `loopRunner.eventStreamCommand` are **not**
|
|
@@ -160,7 +180,7 @@ rotation timing. So:
|
|
|
160
180
|
collide with any native file or be swept into `archive/`, then Monitor that file:
|
|
161
181
|
|
|
162
182
|
```
|
|
163
|
-
mkdir -p {backlogDir}/{loopRunner.stateDir} && {rendered eventStreamCommand} > {backlogDir}/forge-events.ndjson 2>&1
|
|
183
|
+
mkdir -p {backlogDir}/{loopRunner.stateDir} && { [ "$(id -u)" = 0 ] && export IS_SANDBOX="${IS_SANDBOX:-1}" || true; } && {rendered eventStreamCommand} > {backlogDir}/forge-events.ndjson 2>&1
|
|
164
184
|
```
|
|
165
185
|
|
|
166
186
|
The background task's exit notification remains the single authoritative terminal
|
|
@@ -22,3 +22,14 @@ This project was scaffolded by forge-bootstrap. To continue development:
|
|
|
22
22
|
- Documents under `specs/` (PRDs, tech specs, numbered implementation specs) establish the backlog. They are **not** kept in sync with the code as it evolves.
|
|
23
23
|
- Do not flag or "fix" divergence between a finalized spec and the implementation — code is the source of truth for behavior.
|
|
24
24
|
- It's fine for `specs/` artifacts and `backlog.json` to reference specs for provenance, but implementation artifacts (source code, generated skills/agents, configs, docs) must not reference spec files, which may be archived or deleted after a feature ships.
|
|
25
|
+
|
|
26
|
+
## Tooling feedback (feature-forge / rauf)
|
|
27
|
+
|
|
28
|
+
This project is driven by the feature-forge pipeline and the rauf loop. Help improve those tools by capturing friction as you hit it — papercuts included, not just outright bugs.
|
|
29
|
+
|
|
30
|
+
- **When to flag:** any forge/rauf command, skill, agent, or prompt that is confusing, buggy, missing a capability, forces a workaround, or produces a surprising result.
|
|
31
|
+
- **Where to file** — route by which tool the friction is with:
|
|
32
|
+
- feature-forge (pipeline stages, forge skills/agents): https://github.com/garygentry/feature-forge/issues
|
|
33
|
+
- rauf (the autonomous loop runner, `rauf` CLI): https://github.com/garygentry/rauf/issues
|
|
34
|
+
- **How:** capture it while fresh — *what you ran / what you expected / what actually happened / a fix idea* — then propose a titled issue and file it with `gh issue create` **on the human's go-ahead, not silently.**
|
|
35
|
+
- **In an autonomous rauf iteration:** do **not** open issues mid-loop. Note the friction in `progress.md` for the human to triage later.
|
|
@@ -23,3 +23,14 @@ This project was scaffolded by forge-bootstrap. To continue development:
|
|
|
23
23
|
- Documents under `specs/` (PRDs, tech specs, numbered implementation specs) establish the backlog. They are **not** kept in sync with the code as it evolves.
|
|
24
24
|
- Don't flag or "fix" divergence between a finalized spec and the implementation — code is the source of truth for behavior.
|
|
25
25
|
- It's fine for `specs/` artifacts and `backlog.json` to reference specs for provenance, but implementation artifacts (source code, generated skills/agents, configs, docs) must not reference spec files, which may be archived or deleted after a feature ships.
|
|
26
|
+
|
|
27
|
+
## Tooling feedback (feature-forge / rauf)
|
|
28
|
+
|
|
29
|
+
I'm driving this project with the feature-forge pipeline and the rauf loop, and I want to keep improving them. When you hit friction with either tool, help me capture it — papercuts included, not just outright bugs.
|
|
30
|
+
|
|
31
|
+
- **When to flag:** any forge/rauf command, skill, agent, or prompt that is confusing, buggy, missing a capability, forces a workaround, or produces a surprising result.
|
|
32
|
+
- **Where to file** — route by which tool the friction is with:
|
|
33
|
+
- feature-forge (pipeline stages, `/feature-forge:*`, forge skills/agents): https://github.com/garygentry/feature-forge/issues
|
|
34
|
+
- rauf (the autonomous loop runner, `rauf` CLI): https://github.com/garygentry/rauf/issues
|
|
35
|
+
- **How:** capture it while fresh — *what you ran / what you expected / what actually happened / a fix idea* — then propose a titled issue and file it with `gh issue create` **once I give the go-ahead, not silently.**
|
|
36
|
+
- **In an autonomous rauf iteration:** don't open issues mid-loop. Note the friction in `progress.md` for me to triage later.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@garygentry/feature-forge",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
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",
|