forgetrail 0.5.4 → 0.5.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/CONTINUATION_PROMPT.md +3 -3
- package/INITIAL_PROMPT.md +7 -7
- package/README.md +3 -3
- package/TRY_FORGETRAIL.md +2 -2
- package/WORKFLOW.md +15 -15
- package/content/AGENT_INTEGRATION_claude.md +1 -1
- package/content/AGENT_INTEGRATION_cursor.md +2 -3
- package/content/AGENT_INTEGRATION_generic.md +4 -4
- package/content/AGENT_INTEGRATION_grok.md +6 -6
- package/content/COMPANION_TOOLS.md +3 -3
- package/content/FORGETRAIL_LITE.md +16 -17
- package/content/FORGETRAIL_PROGRESS.md +1 -1
- package/content/GENESIS_SPEC_PROMPT.md +1 -1
- package/content/GENESIS_STUB.md +1 -1
- package/content/GREENFIELD_INTAKE.md +2 -2
- package/content/KICKOFF_WITHOUT_MCP.md +1 -1
- package/content/NEW_PROJECT_BOOTSTRAP.md +13 -13
- package/content/ONE_CLICK_DEV_SETUP.md +1 -1
- package/content/PLAN_MODE_PATTERNS.md +2 -2
- package/content/POCKETBASE_SCHEMA_SCRIPT.md +1 -1
- package/content/POST_BOOTSTRAP_USER_MESSAGE.md +2 -2
- package/content/SESSION_RESUME_MCP.md +1 -2
- package/content/SYSTEM_HEALTH_CHECKS.md +1 -1
- package/content/companion-tools.json +6 -1
- package/content/cursor-rules/forgetrail-phase-status.mdc +3 -3
- package/content/examples/two-session-continuity.md +3 -5
- package/content/hooks/README.md +4 -3
- package/content/hooks/appledger-bin.mjs +33 -0
- package/content/hooks/session-start.mjs +6 -1
- package/content/hooks/session-stop.mjs +76 -4
- package/content/hooks/validate-tracking.mjs +26 -0
- package/content/scripts/forgetrail-dev-launcher.mjs +1 -1
- package/content/skills/forgetrail/SKILL.md +6 -8
- package/docs/NPM.md +3 -3
- package/docs/PHASE_1_BRIEF.md +2 -2
- package/docs/SPEC_FEATURE_TEMPLATE.md +1 -1
- package/package.json +1 -1
- package/prompts/propagate-to-forgetrail.md +7 -7
- package/prompts/second-family-critique.md +1 -1
- package/scripts/forgetrail-cli.mjs +1 -1
- package/scripts/install.mjs +5 -4
- package/scripts/tracking-cutover.test.mjs +132 -5
|
@@ -4,7 +4,7 @@ Use alongside **`getChecklist`** section `before-session-1`. That checklist cove
|
|
|
4
4
|
|
|
5
5
|
**Already have a written spec (e.g. `docs/GENESIS.md`)?** Feed it into **`ingestPlanArtifact`** first, then use this document only to fill gaps (delivery, tenancy, compliance, live search) it may not cover. If the user has only an idea, **`getGenesisSpecPrompt`** (or human recipe **`TRY_FORGETRAIL.md`**) produces a portable spec via an external LLM chat before you run through these questions.
|
|
6
6
|
|
|
7
|
-
**Agent:** Walk through these with the user (or infer from context and confirm). Record answers in **`docs/PHASE_1_BRIEF.md`** (§1–3, §6–8 as needed) and as **decision records in `appledger/`**.
|
|
7
|
+
**Agent:** Walk through these with the user (or infer from context and confirm). Record answers in **`docs/PHASE_1_BRIEF.md`** (§1–3, §6–8 as needed) and as **decision records in `appledger/`**.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ Use alongside **`getChecklist`** section `before-session-1`. That checklist cove
|
|
|
19
19
|
|
|
20
20
|
- **Is this a product, an internal tool, or a one-shot?** (product: others will use it, possibly pay; internal-tool: real recurring users, no market; one-shot: gift, event page, demo: one occasion, then done). Often obvious from the problem statement; confirm rather than interrogate.
|
|
21
21
|
- The archetype **prunes the lifecycle**: internal tools make Phase 6 optional and drop payments/business-plan criteria from Phase 7; one-shots collapse phases 5–7 into a single polish-and-ship gate. See **WORKFLOW.md §1d**.
|
|
22
|
-
- Record it in **`PHASE_1_BRIEF.md`**, as a decision record, and as **`archetype`** on **`appledger/profiles/forgetrail.yaml`**. Prune non-applicable criteria on that profile.
|
|
22
|
+
- Record it in **`PHASE_1_BRIEF.md`**, as a decision record, and as **`archetype`** on **`appledger/profiles/forgetrail.yaml`**. Prune non-applicable criteria on that profile.
|
|
23
23
|
|
|
24
24
|
## 1. Outputs and formats
|
|
25
25
|
|
|
@@ -7,7 +7,7 @@ Some Cursor sessions **do not expose MCP tools** to the agent (or only a subset)
|
|
|
7
7
|
**If you must replicate the kickoff bundle from this repo** (same sources as `buildNewProjectKickoff` in `mcp-server/src/index.ts`), read and apply in order:
|
|
8
8
|
|
|
9
9
|
1. `content/NEW_PROJECT_BOOTSTRAP.md` — methodology and next steps
|
|
10
|
-
2. If `appledger` is installed, run **`appledger init`** in the customer repo (pass **`--name`** when the name is known). Otherwise create the manifest, `profiles/forgetrail.yaml`, an application record, and a session record by hand.
|
|
10
|
+
2. If `appledger` is installed, run **`appledger init`** in the customer repo (pass **`--name`** when the name is known). Otherwise create the manifest, `profiles/forgetrail.yaml`, an application record, and a session record by hand.
|
|
11
11
|
3. `content/POST_BOOTSTRAP_USER_MESSAGE.md` — how the first user-facing reply should read
|
|
12
12
|
4. `content/cursor-rules/forgetrail-phase-status.mdc` — write to `.cursor/rules/forgetrail-phase-status.mdc` in the customer repo (Cursor only)
|
|
13
13
|
5. `content/cursor-rules/forgetrail-lessons-gate.mdc` and `forgetrail-lessons-mcp.mdc` — write to `.cursor/rules/` (lessons + anti-patterns gate before large work)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ForgeTrail — New project bootstrap (MCP-first)
|
|
2
2
|
|
|
3
|
-
Use this when **ForgeTrail is available via the MCP server** (recommended). The customer repo should **not** contain a copied `_forgetrail/` methodology tree — templates, audits, phase playbooks, and lessons are retrieved through MCP tools from the open-source ForgeTrail install. Project state lives in **`appledger/`**.
|
|
3
|
+
Use this when **ForgeTrail is available via the MCP server** (recommended). The customer repo should **not** contain a copied `_forgetrail/` methodology tree — templates, audits, phase playbooks, and lessons are retrieved through MCP tools from the open-source ForgeTrail install. Project state lives in **`appledger/`**. `.forgetrail/` is hooks and host rules.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ Use this when **ForgeTrail is available via the MCP server** (recommended). The
|
|
|
8
8
|
|
|
9
9
|
1. Follow the **7-phase lifecycle** (Plan → Build → Stabilize → Iterate → Refine → Align → Harden).
|
|
10
10
|
2. **Pause at phase transitions** for explicit user approval before advancing.
|
|
11
|
-
3. **Persist ForgeTrail state in `appledger/`** — manifest, `profiles/forgetrail.yaml`, and records.
|
|
11
|
+
3. **Persist ForgeTrail state in `appledger/`** — manifest, `profiles/forgetrail.yaml`, and records. Add **`.forgetrail/AGENTS.md`**, **`.forgetrail/CLAUDE.md`**, and **`.forgetrail/cursor/rules/`** (symlink `.mdc` files into **`.cursor/rules/`**) for host rules. Product docs (**`docs/`**, **`CONTEXT_PROMPT.md`**, **`README.md`**, **`TODO.md`**) stay at repo root. **Optionally gitignore `.forgetrail/`** if you want a cleaner public history or use MCP-only without a vendored Lite file (see **`FORGETRAIL_LITE.md` §1.5**). Commit **`appledger/`**. For **Cursor**, add **`.cursor/rules/forgetrail-phase-status.mdc`** from **`getNewProjectKickoff`** (bundled) or **`getForgeTrailCursorPhaseRule`** — it reads **`appledger/profiles/forgetrail.yaml`**. Also add **`forgetrail-lessons-gate.mdc`** and **`forgetrail-lessons-mcp.mdc`** from the same bundle or **`getForgeTrailCursorLessonsRules`** so agents call **`getAntiPatterns`** + **`searchLessons`** before substantial feature work.
|
|
12
12
|
4. **Pull methodology on demand** via ForgeTrail MCP tools (below). Do not ask the user to paste entire ForgeTrail files.
|
|
13
13
|
5. **User-facing replies:** After bootstrap files exist, **`getPostBootstrapUserMessage`** defines the **first** reply—plain language only: what you did, what happens next, and a **concrete “reply with”** (problem, audience, hero workflow, constraints, v1 scope). **No** MCP/tool names, methodology jargon, ForgeTrail footers, file inventories, or “reference only” tracking dumps unless the user asks for internals.
|
|
14
14
|
6. **Lists and choices:** When offering several next steps or options, follow **`USER_REPLY_FORMAT.md`** (ForgeTrail): **numbers** for ordered pipelines, **bullets** for parallel items, **letters** for pick-one / “which first—A/B/C?”—never hide multiple paths in one long sentence.
|
|
@@ -21,7 +21,7 @@ On a **new project folder**, commands like `git status`, `git log`, or `git rev-
|
|
|
21
21
|
|
|
22
22
|
**You** initialize git after bootstrap files exist (unless the user chose **no-git mode** — see **`FORGETRAIL_LITE.md` §4.1**):
|
|
23
23
|
|
|
24
|
-
1. Write kickoff artifacts first: **`appledger/`**, guardrails, optional Cursor rules.
|
|
24
|
+
1. Write kickoff artifacts first: **`appledger/`**, guardrails, optional Cursor rules.
|
|
25
25
|
2. Check with `git rev-parse --is-inside-work-tree`. If it returns false or errors, run **`git init -b main`** at the repo root (or `git init` + `git branch -m main` on older Git). **Never** re-init an existing repo.
|
|
26
26
|
3. Write a **minimal** `.gitignore` now — at least `node_modules/`, `.env`, `.DS_Store`. Add `.forgetrail/` **only** if you chose the gitignore branch in **`FORGETRAIL_LITE.md` §1.5** (default MCP greenfield: **commit `.forgetrail/`**).
|
|
27
27
|
4. Make a **first commit** when steps 1–3 are done so the user has a clean baseline (plain `-m` or `-F`). Skip if the repo already had history; skip entirely in no-git mode.
|
|
@@ -34,7 +34,7 @@ Do **not** treat an early missing-repo git error as blocking. Prefer **`git rev-
|
|
|
34
34
|
|
|
35
35
|
- **Phase 1:** Create and lock **`docs/PHASE_1_BRIEF.md`** (`getTemplate({ name: "PHASE_1_BRIEF" })`). Log major commitments as **decision records in `appledger/`**. If the host supports **native plan mode**, use **`getPlanModePatterns`** and WORKFLOW §1c — plan first, export to the brief on approval (no app code during planning).
|
|
36
36
|
- **App/code:** Phase 2 still means the **full runnable spine** in one pass: init, deps, data path, routes, components, hero flow **end-to-end**. Do **not** defer that spine.
|
|
37
|
-
- **Project archetype (Phase 1):** classify the project as **`product`** (default), **`internal-tool`**, or **`one-shot`** (gift / event / demo) — often inferable from the problem statement; confirm rather than interrogate. Record it in **`PHASE_1_BRIEF.md`**, as a decision record, and as **`archetype`** on **`appledger/profiles/forgetrail.yaml`**. Prune non-applicable criteria on that profile (internal tools: Phase 6 optional, no payments/business-plan rows; one-shots: phases 5–7 collapse into one polish-and-ship gate). Log the pruning as a decision.
|
|
37
|
+
- **Project archetype (Phase 1):** classify the project as **`product`** (default), **`internal-tool`**, or **`one-shot`** (gift / event / demo) — often inferable from the problem statement; confirm rather than interrogate. Record it in **`PHASE_1_BRIEF.md`**, as a decision record, and as **`archetype`** on **`appledger/profiles/forgetrail.yaml`**. Prune non-applicable criteria on that profile (internal tools: Phase 6 optional, no payments/business-plan rows; one-shots: phases 5–7 collapse into one polish-and-ship gate). Log the pruning as a decision. See **WORKFLOW §1d** and **`GREENFIELD_INTAKE.md`** §0.
|
|
38
38
|
- **Web-app sub-question (Phase 1, when app type = web app):** before locking PocketBase + auth, ask *"Does any state need to outlive the browser — accounts, cross-device sync, shared data — or is every user's state private and fine in `localStorage`?"* If local-only → **drop PocketBase and auth**, `adapter-static` becomes viable, no deploy-time secrets; persist via `localStorage` / `IndexedDB`. If persistent → the full Default-A stack applies. Record the choice as a decision record and in **`PHASE_1_BRIEF.md` §4 (`State persistence:` row)**. See **`FORGETRAIL_LITE.md` §7** (A-local vs A-persistent) and **`GREENFIELD_INTAKE.md`** §7.
|
|
39
39
|
- **Initial data (optional):** The user may create **JSON files** for seed, fixtures, or imports by using **any** LLM chat (including **local Ollama**) with the copy-paste prompt in **`FORGETRAIL_LITE.md` §4.3** (structured JSON only; save to `data/` or `fixtures/`). The agent **validates** shape before import; the user can repeat for multiple datasets. Not a replacement for the Phase 1 brief — only for bulk structured content.
|
|
40
40
|
- **Web search (optional):** If v1 needs **live internet search**, the user can sign up for **[Tavily](https://tavily.com/)** and/or the **[Brave Search API](https://api-dashboard.search.brave.com/)** (free or entry-level credits per vendor terms), add keys to **`.env`**, and the agent wires **server-side** clients. See **`FORGETRAIL_LITE.md` §4.4** and **`GREENFIELD_INTAKE.md`** §6.
|
|
@@ -57,12 +57,12 @@ Call **`getProgressiveDocSchedule`** for the canonical phase → doc matrix (WOR
|
|
|
57
57
|
- If **`docs/GENESIS.md`** already exists (Try path / human brought a what-not-how spec), call **`ingestPlanArtifact`** with that file’s contents as `planContent`, review the draft brief, then continue intake for gaps only (`getGreenfieldIntakePrompt`). Do **not** re-run a full blank Genesis prompt unless the user asks.
|
|
58
58
|
- If the user only has an **idea** (no file yet), especially one that wraps an existing app’s data/file format, offer **`getGenesisSpecPrompt`**: they paste it into an **external** LLM chat, save the result as **`docs/GENESIS.md`**, then you ingest as above. Humans without MCP can follow repo-root **`TRY_FORGETRAIL.md`** instead.
|
|
59
59
|
- Skip this step if the user wants straight Lite/MCP intake questions with no Genesis file.
|
|
60
|
-
1. Call **`getNewProjectKickoff`** (`includeCursorRule: false` if not using **Cursor**). It bundles this document, **`appledger/`** initialization, post-bootstrap user-message guidance, and optionally the Cursor rules (phase status + lessons gate + lessons MCP detail)—**or** call **`getNewProjectBootstrap`**, **`getInitialWorkflowTracking`**, **`getPostBootstrapUserMessage`**, **`getForgeTrailCursorPhaseRule`**, and **`getForgeTrailCursorLessonsRules`** separately if you need only one piece. **`getInitialWorkflowTracking` does not return a JSON file.** Write **`appledger/`**.
|
|
60
|
+
1. Call **`getNewProjectKickoff`** (`includeCursorRule: false` if not using **Cursor**). It bundles this document, **`appledger/`** initialization, post-bootstrap user-message guidance, and optionally the Cursor rules (phase status + lessons gate + lessons MCP detail)—**or** call **`getNewProjectBootstrap`**, **`getInitialWorkflowTracking`**, **`getPostBootstrapUserMessage`**, **`getForgeTrailCursorPhaseRule`**, and **`getForgeTrailCursorLessonsRules`** separately if you need only one piece. **`getInitialWorkflowTracking` does not return a JSON file.** Write **`appledger/`**. The **next message to the user** follows **`getPostBootstrapUserMessage`** (product-facing, no methodology leak).
|
|
61
61
|
2. **Initialize git if needed** (see **Greenfield git** above): after bootstrap files exist, `git init -b main` when `git rev-parse --is-inside-work-tree` fails; minimal `.gitignore`; optional first commit. Do not ask the user to run `git init`.
|
|
62
62
|
3. Call **`getProgressiveDocSchedule`** and keep it in mind for every phase transition.
|
|
63
63
|
4. Call **`getChecklist`** with section `before-session-1` — complete those items with the user (problem statement, stack, assets, hero flow).
|
|
64
64
|
5. Call **`getGreenfieldIntakePrompt`** — product/delivery questions: exports (PDF / DOCX / PPTX, etc.), tenancy (e.g. consultants × clients), hybrid vs full spec, compliance tier (even if “none yet”), hero flow, and registrar/DNS/git/hosting if still open. Capture answers in **`PHASE_1_BRIEF.md`** and as decision records. If using native plan mode, include these questions in the plan context (`getPlanModePatterns`). When a companion trigger is true later, call **`getCompanionSuggestions`**. Do not name companions in the first user-facing message.
|
|
65
|
-
6. Call **`getTrackingSchema`** — you will maintain **`appledger/`**.
|
|
65
|
+
6. Call **`getTrackingSchema`** — you will maintain **`appledger/`**. Optionally call **`getAgentIntegrationGuide`** for your host (`grok`, `cursor`, `claude`, `generic`) and **`getForgeTrailSkill`** if the agent supports persistent skills.
|
|
66
66
|
7. Call **`getPhaseGuidance`** with phase `1` (architecture). Summarize understanding and propose structure, data model, integrations, and v1 scope **before** writing app code.
|
|
67
67
|
8. During Phase 1, create **`docs/PHASE_1_BRIEF.md`** from **`getTemplate({ name: "PHASE_1_BRIEF" })`**, fill every section, and **lock** it; mirror major decisions as **appledger decision records**.
|
|
68
68
|
9. After architecture is confirmed and the brief is locked, call **`getPhaseGuidance`** with phase `2` (scaffolding). Read the brief and **`appledger/profiles/forgetrail.yaml`**, **merge the brief into `CONTEXT_PROMPT.md`**, then execute a **single-pass app skeleton** and the rest of the Phase 2 doc set (`README`, `TODO`, `.forgetrail/IDEAS.md`).
|
|
@@ -76,7 +76,7 @@ Call **`getProgressiveDocSchedule`** for the canonical phase → doc matrix (WOR
|
|
|
76
76
|
| **Pre-Phase-1 build spec (external LLM chat)** | **`getGenesisSpecPrompt`** → user saves **`docs/GENESIS.md`**; or human recipe **`TRY_FORGETRAIL.md`** (no MCP) |
|
|
77
77
|
| **Feature delivery SPEC template (Phase 4+)** | **`getTemplate({ name: "SPEC_FEATURE_TEMPLATE" })`** → write `specs/[feature].md`; lifecycle in WORKFLOW Phase 4 |
|
|
78
78
|
| **Approved Genesis / plan → brief + decisions** | **`ingestPlanArtifact`** — after plan approval or when `docs/GENESIS.md` exists |
|
|
79
|
-
| **One-call greenfield setup** (bootstrap +
|
|
79
|
+
| **One-call greenfield setup** (bootstrap + ledger + post-bootstrap guidance + optional Cursor rules) | **`getNewProjectKickoff`** — prefer over calling the granular tools separately |
|
|
80
80
|
| **Which docs in which phase** | **`getProgressiveDocSchedule`** (WORKFLOW §1a) |
|
|
81
81
|
| Phase playbooks, entry/exit criteria, patterns | `getPhaseGuidance` (phases 1–7 or keywords like `scaffolding`, `hardening`) |
|
|
82
82
|
| Milestone checklists | `getChecklist` (`before-session-1`, `session-1`, `session-2`, `full`, …) |
|
|
@@ -89,7 +89,7 @@ Call **`getProgressiveDocSchedule`** for the canonical phase → doc matrix (WOR
|
|
|
89
89
|
| **Native plan mode as Phase 1** | **`getPlanModePatterns`** — use before scaffolding when the host supports plan-before-code |
|
|
90
90
|
| **Agent-specific integration** (Grok, Cursor, Claude) | **`getAgentIntegrationGuide`** — primitive mappings and session openers |
|
|
91
91
|
| **Installable forgetrail skill** (Grok etc.) | **`getForgeTrailSkill`** — copy to host skill directory |
|
|
92
|
-
| **
|
|
92
|
+
| **Ledger check** | **`validateTracking`** — a missing file is expected |
|
|
93
93
|
| **Optional companion tools** (FilePress, LocalSlip, skills, xFacts, …) | **`getCompanionSuggestions`** — `phase` or `situation`; never required; not in the first user-facing message (WORKFLOW §1f) |
|
|
94
94
|
| **Parallel subagent recommendations** | **`suggestSubagentDecomposition`** — before spawning audits/research (WORKFLOW §1c) |
|
|
95
95
|
| **Ledger initialization** for a greenfield repo | `getInitialWorkflowTracking` — does **not** return JSON. Create **`appledger/`** |
|
|
@@ -106,7 +106,7 @@ Call **`getProgressiveDocSchedule`** for the canonical phase → doc matrix (WOR
|
|
|
106
106
|
|
|
107
107
|
**Immediately (greenfield):**
|
|
108
108
|
|
|
109
|
-
- **`appledger/`** — if the `appledger` command is installed, run **`appledger init`** and pass **`--name`** when the name is known. Init writes the manifest, profile, application record, and session record, and does not overwrite them. If the command is not installed, write those four files by hand.
|
|
109
|
+
- **`appledger/`** — if the `appledger` command is installed, run **`appledger init`** and pass **`--name`** when the name is known. Init writes the manifest, profile, application record, and session record, and does not overwrite them. If the command is not installed, write those four files by hand. Commit **`appledger/`**.
|
|
110
110
|
- **`docs/GENESIS.md`** (optional but preferred on the Try path) — what-not-how product spec from **`getGenesisSpecPrompt`** / **`TRY_FORGETRAIL.md`**. If present at kickoff, ingest with **`ingestPlanArtifact`** before locking the brief.
|
|
111
111
|
- **Git repo** — if `git rev-parse --is-inside-work-tree` fails, **`git init -b main`** after bootstrap files exist (see **Greenfield git**). A failed early `git status` on an empty folder is **not** an error. Add minimal **`.gitignore`** and an optional first commit before Phase 1 intake.
|
|
112
112
|
- **Cursor users:** `.cursor/rules/forgetrail-phase-status.mdc` — from **`getForgeTrailCursorPhaseRule`**. **`forgetrail-lessons-gate.mdc`** + **`forgetrail-lessons-mcp.mdc`** — from **`getForgeTrailCursorLessonsRules`** or **`getNewProjectKickoff`** (lessons workflow before substantial changes).
|
|
@@ -140,9 +140,9 @@ Call **`getProgressiveDocSchedule`** for the canonical phase → doc matrix (WOR
|
|
|
140
140
|
|
|
141
141
|
- At **each session start**, read **`appledger/profiles/forgetrail.yaml`**, the latest session record, and `CONTEXT_PROMPT.md` (if present). Use **`getPhaseGuidance`** for the current phase.
|
|
142
142
|
- When exit criteria for a phase appear satisfied, **state that explicitly** and **wait for user confirmation** before treating the next phase as active; change `current_phase_instance` only after approval.
|
|
143
|
-
- After substantive work, update **`appledger/`** (criteria, decision records, lessons, the session).
|
|
143
|
+
- After substantive work, update **`appledger/`** (criteria, decision records, lessons, the session).
|
|
144
144
|
- If a problem does not converge after **~5 turns**, propose a **different approach**, not more patches.
|
|
145
|
-
- **When the project ends** (shipped, delivered, shelved), run the **wrap protocol** (WORKFLOW §1e): sweep lesson and decision records for generalizable lessons, run the propagation prompt in **Harvest mode**, set **`project_status`** to **`wrapped`** on the profile, and add a final session record with end state and handoff pointers.
|
|
145
|
+
- **When the project ends** (shipped, delivered, shelved), run the **wrap protocol** (WORKFLOW §1e): sweep lesson and decision records for generalizable lessons, run the propagation prompt in **Harvest mode**, set **`project_status`** to **`wrapped`** on the profile, and add a final session record with end state and handoff pointers.
|
|
146
146
|
- **Git commits:** `git commit -F <file>` or plain `-m` at natural stopping points with concise summaries. Run verification checks prior to commit.
|
|
147
147
|
|
|
148
148
|
---
|
|
@@ -157,7 +157,7 @@ ForgeTrail’s reference implementation used **SvelteKit (Svelte 5), TypeScript,
|
|
|
157
157
|
|
|
158
158
|
If the user has [gstack](https://github.com/garrytan/gstack) installed (Claude Code slash-command skills), ForgeTrail and gstack are **complementary** — ForgeTrail provides the lifecycle methodology, project memory, and business/brand layer; gstack provides sprint execution, browser-based QA, and deploy automation. Use both:
|
|
159
159
|
|
|
160
|
-
**ForgeTrail owns the lifecycle.** Phase transitions, exit criteria, `appledger/`, progressive docs, lessons, and audits all come from ForgeTrail MCP.
|
|
160
|
+
**ForgeTrail owns the lifecycle.** Phase transitions, exit criteria, `appledger/`, progressive docs, lessons, and audits all come from ForgeTrail MCP.
|
|
161
161
|
|
|
162
162
|
**gstack owns the sprint inner loop.** Within a ForgeTrail phase, use gstack skills for the build → review → test → ship cycle:
|
|
163
163
|
|
|
@@ -171,7 +171,7 @@ If the user has [gstack](https://github.com/garrytan/gstack) installed (Claude C
|
|
|
171
171
|
| **Phase 6** (Align) | `/design-consultation` for design system, `/plan-ceo-review` for scope check | Create **`BRAND_AND_PRODUCT.md`** and restructure **`TODO.md`** via ForgeTrail templates — gstack doesn't have brand/strategy tooling. |
|
|
172
172
|
| **Phase 7** (Harden) | `/cso` for security audit, `/qa` for full regression, `/ship` + `/land-and-deploy` + `/canary` for production | ForgeTrail's `runAudit("black-hat")` and gstack's `/cso` are complementary — run both. ForgeTrail produces **`BLACK_HAT_REPORT.md`** and **`CODE_QUALITY.md`** as persistent docs; gstack's `/cso` catches runtime exploits. Use `/land-and-deploy` → `/canary` for the actual deploy pipeline, then fill ForgeTrail's **`DEPLOYMENT.md`** to document the process. |
|
|
173
173
|
|
|
174
|
-
**Key rule:** After every gstack sprint that completes meaningful work, **update `appledger/`** (criteria when evidence exists, decision records, lessons or questions, the session).
|
|
174
|
+
**Key rule:** After every gstack sprint that completes meaningful work, **update `appledger/`** (criteria when evidence exists, decision records, lessons or questions, the session). gstack persists some sprint artifacts (design docs from `/office-hours` in `~/.gstack/projects/`, retro snapshots in `.context/retros/`, review overrides, skill analytics), but it has **no lifecycle state, no decision rationale log, and no architecture context document**. ForgeTrail's `appledger/` plus `CONTEXT_PROMPT.md` are the system of record for the phase, the decisions, the lessons, and the architecture — none of which gstack tracks.
|
|
175
175
|
|
|
176
176
|
---
|
|
177
177
|
|
|
@@ -137,6 +137,6 @@ if errorlevel 1 pause
|
|
|
137
137
|
See **FORGETRAIL_LITE.md** §4.2.2 and **`SCAFFOLD_INSTALL.json`** (`versionPolicy`). Install scripts read `POCKETBASE_VERSION` from `.env`:
|
|
138
138
|
|
|
139
139
|
- unset or `latest` → resolve from GitHub **releases/latest** at setup time
|
|
140
|
-
- `0.26.2` (example) → pin that release; record
|
|
140
|
+
- `0.26.2` (example) → pin that release; record it as an appledger decision record when the user confirms a good boot
|
|
141
141
|
|
|
142
142
|
Never ship a stale semver only in methodology docs without an env override path.
|
|
@@ -14,7 +14,7 @@ When your host agent supports a first-class plan mode (Grok Build `/plan` + ente
|
|
|
14
14
|
3. On user approval (the agent's `exit_plan_mode` or equivalent):
|
|
15
15
|
- Immediately call `getTemplate({ name: "PHASE_1_BRIEF", mode: "full" })`.
|
|
16
16
|
- Map/synthesize the approved plan content into the brief template (especially sections on architecture, data model, state persistence, content generation, and v1 scope).
|
|
17
|
-
- Write each major decision as a decision record in `appledger/`.
|
|
17
|
+
- Write each major decision as a decision record in `appledger/`.
|
|
18
18
|
- Optionally call `ingestPlanArtifact` with the full approved plan text to produce a `PHASE_1_BRIEF.md` draft and decision records (review and lock before Phase 2).
|
|
19
19
|
|
|
20
20
|
4. The approved `docs/PHASE_1_BRIEF.md` and those decision records become the handoff so Phase 2 can begin "cold" without replaying the entire planning conversation.
|
|
@@ -35,7 +35,7 @@ When your host agent supports a first-class plan mode (Grok Build `/plan` + ente
|
|
|
35
35
|
## Artifacts That Must Result from Phase 1 (Plan or Not)
|
|
36
36
|
|
|
37
37
|
- `docs/PHASE_1_BRIEF.md` (locked)
|
|
38
|
-
- `appledger/` with the `plan` phase in progress and those decision records.
|
|
38
|
+
- `appledger/` with the `plan` phase in progress and those decision records.
|
|
39
39
|
- (Later) `CONTEXT_PROMPT.md` will merge the brief in Phase 2
|
|
40
40
|
|
|
41
41
|
Never proceed to scaffolding until the user confirms the plan/brief is locked.
|
|
@@ -18,7 +18,7 @@ Manual admin-UI collection setup (click-through wizards) does not scale across m
|
|
|
18
18
|
4. **Schema (agent or one terminal):** `pnpm run pocketbase:schema` after PocketBase is up — idempotent; replaces manual Admin UI collection wizards.
|
|
19
19
|
5. **PocketBase broken?** double-click **`test-pocketbase.bat`** / **`pnpm run test:pocketbase`** — isolated health check (**`SYSTEM_HEALTH_CHECKS.md`**).
|
|
20
20
|
6. **Check progress:** double-click **`status.bat`** / **`status.sh`** or open **`docs/FORGETRAIL_PROGRESS.md`**.
|
|
21
|
-
7. Walk the hero flow;
|
|
21
|
+
7. Walk the hero flow; mark Phase 2 criteria met in `appledger/profiles/forgetrail.yaml`, with evidence, when dev runs, data appears, CRUD works, and the full journey passes.
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Post-bootstrap: first reply to the user
|
|
2
2
|
|
|
3
|
-
**When:** Right after `appledger/` exists (and, for Cursor, the phase rule file if you use it).
|
|
3
|
+
**When:** Right after `appledger/` exists (and, for Cursor, the phase rule file if you use it).
|
|
4
4
|
|
|
5
5
|
**Purpose:** Confirm what happened in **plain language** and give **one clear ask**—what the human should do or answer next. This is not an implementation report.
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ Assume the reader is a **product owner**, not a methodology engineer. They shoul
|
|
|
12
12
|
|
|
13
13
|
- MCP or ForgeTrail server/tool names (`getChecklist`, `getGreenfieldIntakePrompt`, “bundle”, “methodology stays on the MCP side”, etc.)
|
|
14
14
|
- Paths like `.cursor/rules/…` unless they need to edit something themselves
|
|
15
|
-
- Field-by-field descriptions of `
|
|
15
|
+
- Field-by-field descriptions of `appledger/` files or other “for your reference only” inventories
|
|
16
16
|
- ForgeTrail **footers** (phase · exit criteria · “Next: …”)—those are for **agent** orientation in later turns, not for this first message
|
|
17
17
|
|
|
18
18
|
Agents keep planning steps **internal** until they turn user answers into `docs/PHASE_1_BRIEF.md`.
|
|
@@ -10,7 +10,6 @@ The user is **continuing** a project that uses ForgeTrail via the **MCP server**
|
|
|
10
10
|
2. If the current phase is **`plan`**, read **`docs/PHASE_1_BRIEF.md`** and continue planning toward a locked brief. Otherwise read **`CONTEXT_PROMPT.md`**. If a later phase is current but CONTEXT is missing and **`PHASE_1_BRIEF.md`** exists, **merge the brief into CONTEXT** first (see CONTEXT_PROMPT template).
|
|
11
11
|
3. Call **`getPhaseGuidance`** for that phase (`plan` through `harden`, or `1`–`7`). When a companion trigger is true, call **`getCompanionSuggestions`** for that phase or situation. Do not install unless the user asked.
|
|
12
12
|
4. If you need checklist context, call **`getChecklist`** (e.g. `every-session` or `full`).
|
|
13
|
-
5. If a **`workflow_tracking.json`** file exists and is not a pointer, do not update it. Run **`appledger migrate preview`**, then apply. Call **`validateTracking`** only to classify that file.
|
|
14
13
|
|
|
15
14
|
Do **not** require `_forgetrail/WORKFLOW.md` or `_forgetrail/TRACKING_SCHEMA.md` on disk — use the MCP tools above.
|
|
16
15
|
|
|
@@ -19,7 +18,7 @@ Do **not** require `_forgetrail/WORKFLOW.md` or `_forgetrail/TRACKING_SCHEMA.md`
|
|
|
19
18
|
## Rules for this session
|
|
20
19
|
|
|
21
20
|
- When exit criteria for the current phase appear met, say so explicitly and **wait for user confirmation** before changing `current_phase_instance`.
|
|
22
|
-
- After work, update the **session record** and any new **decision records** in **`appledger/`**.
|
|
21
|
+
- After work, update the **session record** and any new **decision records** in **`appledger/`**.
|
|
23
22
|
- Keep **`CONTEXT_PROMPT.md`** the source of truth for architecture; edit it when decisions change.
|
|
24
23
|
- If stuck after **~5 turns** on one issue, propose a **fundamentally different approach**.
|
|
25
24
|
- If the repo has **gstack** installed, use its skills for sprint execution (build/review/qa/ship) within ForgeTrail phases — see **WORKFLOW.md §1b** or call **`getPhaseGuidance`** for phase-specific gstack integration. After each gstack sprint, update the **appledger** session.
|
|
@@ -69,7 +69,7 @@ OLLAMA_MODEL=ibm/granite4.1:8b
|
|
|
69
69
|
# SKIP_OLLAMA_INSTALL=1 # skip entire setup
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
Pin **`OLLAMA_MODEL`** after a successful **test-ollama** run
|
|
72
|
+
Pin **`OLLAMA_MODEL`** after a successful **test-ollama** run, and record that pin as an appledger decision record.
|
|
73
73
|
|
|
74
74
|
---
|
|
75
75
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"Companions are optional. Decline is success. Never block a phase on an install.",
|
|
5
5
|
"Suggest at the moment of need. Do not dump the shelf at kickoff or in the first user-facing message.",
|
|
6
6
|
"Do not install, enroll, or publish unless the user asked.",
|
|
7
|
-
"After a companion run that matters, persist the outcome on the appledger session as data.companion_outcomes and in the matching progressive doc.
|
|
7
|
+
"After a companion run that matters, persist the outcome on the appledger session as data.companion_outcomes and in the matching progressive doc.",
|
|
8
8
|
"Do not mention the mapping file, spec paths, or MCP tool names in human-facing offers.",
|
|
9
9
|
"When wiring LocalSlip, follow that tool's how. Do not write ensure-lease.mjs. Do not add the localslip package just to read a port."
|
|
10
10
|
],
|
|
@@ -204,6 +204,11 @@
|
|
|
204
204
|
"name": "xFacts",
|
|
205
205
|
"homepage": "https://xfacts.dev",
|
|
206
206
|
"offer": "When the product is public or handed off, offer an xFacts label (AppFacts and neighbors). Record the subject disposition either way, and bind an existing label with appledger bind. A validator checks shape, not truth."
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "Efficacy",
|
|
210
|
+
"homepage": "https://efficacy.dev",
|
|
211
|
+
"offer": "When a later agent should inspect a measured use of this exact version, offer an Efficacy chain in .efficacy/. The chain is optional. Verify shows the record is intact and bound to its evidence. It does not show the claim is true."
|
|
207
212
|
}
|
|
208
213
|
]
|
|
209
214
|
},
|
|
@@ -5,7 +5,7 @@ alwaysApply: true
|
|
|
5
5
|
|
|
6
6
|
# ForgeTrail phase awareness
|
|
7
7
|
|
|
8
|
-
This repo uses **ForgeTrail**. **Source of truth:** `appledger/profiles/forgetrail.yaml` and the latest session record.
|
|
8
|
+
This repo uses **ForgeTrail**. **Source of truth:** `appledger/profiles/forgetrail.yaml` and the latest session record. If a legacy `.forgetrail/workflow_tracking.json` exists and is not a pointer, it is a legacy conflict: run `appledger migrate preview`, then apply.
|
|
9
9
|
|
|
10
10
|
## When to surface status
|
|
11
11
|
|
|
@@ -19,7 +19,7 @@ Include a short **ForgeTrail** footer in replies when it helps orientation—esp
|
|
|
19
19
|
|
|
20
20
|
Skip the footer for trivial one-line answers (typos, single-token replies) unless the user asked for status.
|
|
21
21
|
|
|
22
|
-
**Product-facing / non-technical users:** Do **not** show ForgeTrail footers, phase IDs, MCP/tool names, or internal checklists unless they ask how the workflow is wired up. Plain language only. For phase progress without an agent, point them to **`docs/FORGETRAIL_PROGRESS.md`**. The durable phase is `appledger/profiles/forgetrail.yaml
|
|
22
|
+
**Product-facing / non-technical users:** Do **not** show ForgeTrail footers, phase IDs, MCP/tool names, or internal checklists unless they ask how the workflow is wired up. Plain language only. For phase progress without an agent, point them to **`docs/FORGETRAIL_PROGRESS.md`**. The durable phase is `appledger/profiles/forgetrail.yaml`.
|
|
23
23
|
|
|
24
24
|
**Right after bootstrap:** **Omit** the footer entirely—user should get a simple “what’s done + what I need from you next,” not methodology. If you already followed **`getPostBootstrapUserMessage`** in the same turn, do not duplicate status blocks.
|
|
25
25
|
|
|
@@ -57,4 +57,4 @@ Do **not** bury three or more paths in a single long sentence—**list them**, t
|
|
|
57
57
|
|
|
58
58
|
## Phase transitions
|
|
59
59
|
|
|
60
|
-
Do **not** advance `current_phase_instance` or mark a phase completed without **explicit user confirmation**. If criteria look satisfied, say so and ask before updating the profile.
|
|
60
|
+
Do **not** advance `current_phase_instance` or mark a phase completed without **explicit user confirmation**. If criteria look satisfied, say so and ask before updating the profile.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This is a labeled example. The project is fictional. It shows how ForgeTrail Lite state survives a closed chat, and how the next session is supposed to consume it.
|
|
4
4
|
|
|
5
|
-
Nothing here is a benchmark, an adoption claim, or a client record. The record shape matches `appledger/` records
|
|
5
|
+
Nothing here is a benchmark, an adoption claim, or a client record. The record shape matches `appledger/` records.
|
|
6
6
|
|
|
7
7
|
## The job
|
|
8
8
|
|
|
@@ -14,12 +14,12 @@ The human created an empty folder, wrote `docs/GENESIS.md`, and added Lite by co
|
|
|
14
14
|
|
|
15
15
|
The human pasted the kickoff line from [TRY_FORGETRAIL.md](../../TRY_FORGETRAIL.md). The **agent** (not the CLI) then:
|
|
16
16
|
|
|
17
|
-
1. Created `appledger/` with a manifest, a ForgeTrail profile, an application record, and a session record.
|
|
17
|
+
1. Created `appledger/` with a manifest, a ForgeTrail profile, an application record, and a session record.
|
|
18
18
|
2. Drafted `docs/PHASE_1_BRIEF.md`.
|
|
19
19
|
3. Recorded one decision and one lesson.
|
|
20
20
|
4. Stopped after the human approved the brief. No application scaffold yet.
|
|
21
21
|
|
|
22
|
-
The CLI, if used instead of a hand copy, writes the Lite file, hook scripts, and an optional Genesis stub. It does not
|
|
22
|
+
The CLI, if used instead of a hand copy, writes the Lite file, hook scripts, and an optional Genesis stub. It does not fill in the phase, decisions, or session. Those writes depend on the agent following the protocol.
|
|
23
23
|
|
|
24
24
|
### What was left unfinished
|
|
25
25
|
|
|
@@ -67,8 +67,6 @@ That is the trail: a phase, a decision, a lesson, and a next step. The next chat
|
|
|
67
67
|
|
|
68
68
|
MCP tools can hand the agent the same protocol and a lessons search. They do not replace the files in the app repo.
|
|
69
69
|
|
|
70
|
-
An existing writable `.forgetrail/workflow_tracking.json` is legacy. `appledger migrate preview` writes nothing. `apply` imports decisions, sessions, resolved gotchas as lessons, unresolved gotchas as open questions, and `IDEAS.md` / `BUGS.md` from the repository root and from `.forgetrail/`, then replaces the file with a pointer. The `appledger` package is not a published npm release. Use the [repository](https://github.com/Catalyst-Forge-LLC/appledger).
|
|
71
|
-
|
|
72
70
|
## Catalog excerpt
|
|
73
71
|
|
|
74
72
|
Keep project decisions, development state, and lessons in the repository so the next session can continue. After one sitting you should see `appledger/` with a phase, a decision, and a session next step. Full walk-through: this file, and the [continuity](https://forgetrail.dev/docs/continuity) page. The live site still shows the previous pages until it is redeployed.
|
package/content/hooks/README.md
CHANGED
|
@@ -6,10 +6,11 @@ Enforces ForgeTrail rules and guards at the host tool level, rather than relying
|
|
|
6
6
|
|
|
7
7
|
- `guard-shell.mjs`: runs pre-commit verification (`pnpm run verify`), prevents npm/yarn when `pnpm-lock.yaml` is present, allows `ingotvault` (asks before `--force-with-lease`), asks before any `git push`, and prompts on destructive git or filesystem operations.
|
|
8
8
|
- `guard-edit.mjs`: guards `.env*` secrets files and `specs/completed/**` or `specs/canonical/**` records against accidental mutation.
|
|
9
|
-
- `session-start.mjs`: on session start, points the session at `appledger/`.
|
|
10
|
-
- `
|
|
9
|
+
- `session-start.mjs`: on session start, points the session at `appledger/`. When `appledger` is on PATH it appends `appledger orient --budget 300`.
|
|
10
|
+
- `appledger-bin.mjs`: finds the `appledger` command. A missing command is not a failure.
|
|
11
|
+
- `validate-tracking.mjs`: after an edit under `appledger/`, runs `appledger check` when the command is on PATH and reports warnings.
|
|
11
12
|
- `validate-tracking-core.mjs`: standalone zero-dependency tracking validator.
|
|
12
|
-
- `session-stop.mjs`:
|
|
13
|
+
- `session-stop.mjs`: when a turn ends, reminds the agent to update the appledger session record if project files changed after that record was last written. It stays quiet on follow-up turns, on read-only turns, and when only `appledger/`, `.forgetrail/`, `.cursor/`, or `.claude/` changed.
|
|
13
14
|
- `cursor-hooks.json`: standard Cursor hooks configuration.
|
|
14
15
|
- `claude-settings-hooks.json`: standard Claude Code configuration fragment.
|
|
15
16
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find and run the appledger CLI from PATH.
|
|
3
|
+
* A missing command is absent, not a failure. Hooks keep their previous text in that case.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
|
|
8
|
+
export function findAppledger() {
|
|
9
|
+
const finder = process.platform === "win32" ? "where.exe" : "which";
|
|
10
|
+
const found = spawnSync(finder, ["appledger"], { encoding: "utf8", windowsHide: true });
|
|
11
|
+
if (found.status !== 0) return null;
|
|
12
|
+
const line = found.stdout
|
|
13
|
+
.split(/\r?\n/)
|
|
14
|
+
.map((item) => item.trim())
|
|
15
|
+
.find(Boolean);
|
|
16
|
+
return line || null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function runAppledger(args, cwd) {
|
|
20
|
+
const bin = findAppledger();
|
|
21
|
+
if (!bin) return { absent: true, status: null, text: "" };
|
|
22
|
+
const script = /\.(cmd|bat)$/i.test(bin);
|
|
23
|
+
const result = spawnSync(bin, args, {
|
|
24
|
+
cwd,
|
|
25
|
+
encoding: "utf8",
|
|
26
|
+
timeout: 20_000,
|
|
27
|
+
windowsHide: true,
|
|
28
|
+
shell: script,
|
|
29
|
+
});
|
|
30
|
+
if (result.error?.code === "ENOENT") return { absent: true, status: null, text: "" };
|
|
31
|
+
const text = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
|
|
32
|
+
return { absent: false, status: result.status, text };
|
|
33
|
+
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { existsSync, readFileSync } from "node:fs";
|
|
10
10
|
import { join, resolve } from "node:path";
|
|
11
|
+
import { runAppledger } from "./appledger-bin.mjs";
|
|
11
12
|
|
|
12
13
|
function walkUp(startDir, found) {
|
|
13
14
|
let curr = resolve(startDir || process.cwd());
|
|
@@ -54,7 +55,11 @@ function main() {
|
|
|
54
55
|
lines.push("Project record: appledger/");
|
|
55
56
|
lines.push("Read appledger/profiles/forgetrail.yaml for the current phase.");
|
|
56
57
|
lines.push("Read the latest session record for left_off and next_steps.");
|
|
57
|
-
|
|
58
|
+
const orient = runAppledger(["orient", "--budget", "300"], ledgerRoot);
|
|
59
|
+
if (!orient.absent && orient.text) {
|
|
60
|
+
lines.push("");
|
|
61
|
+
lines.push(orient.text);
|
|
62
|
+
}
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
if (trackingPath) {
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* ForgeTrail Session Stop Check
|
|
5
5
|
* Hook event: stop (Cursor)
|
|
6
|
-
* Reminds the agent to update the AppLedger session
|
|
6
|
+
* Reminds the agent to update the AppLedger session record when work happened after it was last written.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { execFileSync } from "node:child_process";
|
|
10
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
10
11
|
import { join, resolve } from "node:path";
|
|
11
12
|
|
|
12
13
|
function walkUp(startDir, found) {
|
|
@@ -37,7 +38,78 @@ function isPointer(data) {
|
|
|
37
38
|
return data?.status === "pointer" && typeof data.record === "string" && data.record.replaceAll("\\", "/").includes("appledger");
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
function readHookInput() {
|
|
42
|
+
try {
|
|
43
|
+
const raw = readFileSync(0, "utf-8");
|
|
44
|
+
return raw.trim() ? JSON.parse(raw) : {};
|
|
45
|
+
} catch {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function latestSessionMs(root) {
|
|
51
|
+
const dir = join(root, "appledger", "records", "session");
|
|
52
|
+
if (!existsSync(dir)) return 0;
|
|
53
|
+
let latest = 0;
|
|
54
|
+
for (const name of readdirSync(dir)) {
|
|
55
|
+
if (!name.endsWith(".md")) continue;
|
|
56
|
+
latest = Math.max(latest, statSync(join(dir, name)).mtimeMs);
|
|
57
|
+
}
|
|
58
|
+
return latest;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function git(root, args) {
|
|
62
|
+
return execFileSync("git", args, { cwd: root, encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const NOT_PROJECT_WORK = ["appledger/", ".forgetrail/", ".cursor/", ".claude/"];
|
|
66
|
+
|
|
67
|
+
function outsideLedger(path) {
|
|
68
|
+
const p = path.replaceAll("\\", "/");
|
|
69
|
+
return p !== "" && !NOT_PROJECT_WORK.some((prefix) => p.startsWith(prefix));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** True when project files changed after the newest session record, or when that cannot be told. Ledger and host-config paths do not count. */
|
|
73
|
+
function workSinceSession(root) {
|
|
74
|
+
const sessionMs = latestSessionMs(root);
|
|
75
|
+
if (sessionMs === 0) return true;
|
|
76
|
+
try {
|
|
77
|
+
const since = `@${Math.floor(sessionMs / 1000)}`;
|
|
78
|
+
const hasCommits = (() => {
|
|
79
|
+
try {
|
|
80
|
+
git(root, ["rev-parse", "--verify", "--quiet", "HEAD"]);
|
|
81
|
+
return true;
|
|
82
|
+
} catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
})();
|
|
86
|
+
if (hasCommits) {
|
|
87
|
+
const committed = git(root, ["log", `--since=${since}`, "--name-only", "--format="]).split("\n").filter(outsideLedger);
|
|
88
|
+
if (committed.length > 0) return true;
|
|
89
|
+
}
|
|
90
|
+
const pending = git(root, ["status", "--porcelain", "--untracked-files=all"])
|
|
91
|
+
.split("\n")
|
|
92
|
+
.map((line) => line.slice(3).split(" -> ").pop()?.replace(/^"|"$/g, "") ?? "")
|
|
93
|
+
.filter(outsideLedger);
|
|
94
|
+
return pending.some((path) => {
|
|
95
|
+
try {
|
|
96
|
+
return statSync(join(root, path)).mtimeMs > sessionMs;
|
|
97
|
+
} catch {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
} catch {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
40
106
|
function main() {
|
|
107
|
+
const input = readHookInput();
|
|
108
|
+
if ((input.loop_count ?? 0) > 0 || (input.status && input.status !== "completed")) {
|
|
109
|
+
console.log(JSON.stringify({}));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
41
113
|
const ledgerRoot = findLedger(process.cwd());
|
|
42
114
|
const trackingPath = findProjectTracking(process.cwd());
|
|
43
115
|
let legacy = false;
|
|
@@ -59,11 +131,11 @@ function main() {
|
|
|
59
131
|
return;
|
|
60
132
|
}
|
|
61
133
|
|
|
62
|
-
if (ledgerRoot) {
|
|
134
|
+
if (ledgerRoot && workSinceSession(ledgerRoot)) {
|
|
63
135
|
console.log(
|
|
64
136
|
JSON.stringify({
|
|
65
137
|
followup_message:
|
|
66
|
-
"ForgeTrail reminder:
|
|
138
|
+
"ForgeTrail reminder: files changed after the latest appledger session record. Update that record (what was accomplished, left_off, next_steps) before ending.",
|
|
67
139
|
})
|
|
68
140
|
);
|
|
69
141
|
return;
|
|
@@ -7,7 +7,17 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { readFileSync, existsSync } from "node:fs";
|
|
10
|
+
import { resolve } from "node:path";
|
|
10
11
|
import { validateTrackingData, formatValidationResult } from "./validate-tracking-core.mjs";
|
|
12
|
+
import { runAppledger } from "./appledger-bin.mjs";
|
|
13
|
+
|
|
14
|
+
function ledgerRoot(filePath) {
|
|
15
|
+
if (!filePath) return null;
|
|
16
|
+
const abs = resolve(filePath).replaceAll("\\", "/");
|
|
17
|
+
const at = abs.toLowerCase().lastIndexOf("/appledger/");
|
|
18
|
+
if (at === -1) return null;
|
|
19
|
+
return abs.slice(0, at);
|
|
20
|
+
}
|
|
11
21
|
|
|
12
22
|
function readStdin() {
|
|
13
23
|
try {
|
|
@@ -27,6 +37,22 @@ function main() {
|
|
|
27
37
|
payload.tool_input?.path ||
|
|
28
38
|
"";
|
|
29
39
|
|
|
40
|
+
const ledger = ledgerRoot(filePath);
|
|
41
|
+
if (ledger) {
|
|
42
|
+
const check = runAppledger(["check", "--root", ledger], ledger);
|
|
43
|
+
const noisy = !check.absent && (check.status !== 0 || /warning|error/i.test(check.text));
|
|
44
|
+
if (noisy && check.text) {
|
|
45
|
+
console.log(
|
|
46
|
+
JSON.stringify({
|
|
47
|
+
additional_context: `=== ForgeTrail ledger check ===\n${check.text}\n================================`,
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
console.log(JSON.stringify({}));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
30
56
|
if (!filePath.endsWith("workflow_tracking.json")) {
|
|
31
57
|
console.log(JSON.stringify({}));
|
|
32
58
|
return;
|
|
@@ -144,7 +144,7 @@ async function cmdRun() {
|
|
|
144
144
|
function renderProgress() {
|
|
145
145
|
if (!existsSync(trackingPath)) {
|
|
146
146
|
return {
|
|
147
|
-
text: "
|
|
147
|
+
text: "Phase state: appledger/profiles/forgetrail.yaml.",
|
|
148
148
|
md: null,
|
|
149
149
|
};
|
|
150
150
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: forgetrail
|
|
3
|
-
description: "Enforce the ForgeTrail 7-phase lifecycle (Plan → Build → Stabilize → Iterate → Refine → Align → Harden), maintain appledger/ as the system of record, pause at explicit phase transitions for user approval, prefer native plan modes when available, and use subagents for parallel audits/research where the host agent supports it.
|
|
3
|
+
description: "Enforce the ForgeTrail 7-phase lifecycle (Plan → Build → Stabilize → Iterate → Refine → Align → Harden), maintain appledger/ as the system of record, pause at explicit phase transitions for user approval, prefer native plan modes when available, and use subagents for parallel audits/research where the host agent supports it. Activate for any non-trivial full-stack app development. Follow progressive documentation rules and propagate lessons back."
|
|
4
4
|
user-invocable: true
|
|
5
5
|
argument-hint: "kickoff new project | resume session | Phase 4 feature work | run black-hat audit | stabilize current issues"
|
|
6
6
|
allowed-tools: "read_file, search_replace, run_terminal_command, todo_write, spawn_subagent, getPhaseGuidance, getCompanionSuggestions, runAudit, searchLessons, validateTracking, suggestSubagentDecomposition, getTemplate, getNewProjectKickoff, getResumeSessionInstructions"
|
|
@@ -21,14 +21,13 @@ You are operating under the ForgeTrail methodology. Your primary job is to give
|
|
|
21
21
|
- 6. Align (map to brand/strategy)
|
|
22
22
|
- 7. Harden (security, perf, docs, production readiness)
|
|
23
23
|
|
|
24
|
-
Phases 4 and 5 commonly alternate. Update `current_phase_instance` and criteria in `appledger/profiles/forgetrail.yaml`.
|
|
24
|
+
Phases 4 and 5 commonly alternate. Update `current_phase_instance` and criteria in `appledger/profiles/forgetrail.yaml`.
|
|
25
25
|
|
|
26
26
|
2. **At the start of every session or major turn**:
|
|
27
27
|
- Read `appledger/profiles/forgetrail.yaml` and the latest session record.
|
|
28
28
|
- Read `CONTEXT_PROMPT.md` and `TODO.md` if they exist.
|
|
29
29
|
- Call `getPhaseGuidance` for the current phase if needed.
|
|
30
30
|
- Summarize current phase, pending criteria, and recent decisions to the user briefly.
|
|
31
|
-
- If `workflow_tracking.json` exists and is not a pointer, do not edit it. Run `appledger migrate preview`, then apply.
|
|
32
31
|
|
|
33
32
|
3. **Pause at phase transitions**:
|
|
34
33
|
- When you believe exit criteria for the current phase are met, explicitly tell the user: "I think we have completed Phase X because [reasons]. The remaining exit criteria are [list]. Ready to move to Phase Y?"
|
|
@@ -39,10 +38,9 @@ You are operating under the ForgeTrail methodology. Your primary job is to give
|
|
|
39
38
|
- Mark a criterion `met` only when an evidence ref exists.
|
|
40
39
|
- Add a lesson or question record when something surprising or painful happens.
|
|
41
40
|
- Update the session record at natural breaks.
|
|
42
|
-
- Do not create or update `workflow_tracking.json`.
|
|
43
41
|
|
|
44
42
|
5. **Use native agent capabilities**:
|
|
45
|
-
- If the agent supports a native plan mode (e.g. Grok `/plan`), use it for Phase 1. On approval, export the plan into `docs/PHASE_1_BRIEF.md` (via `getTemplate`) and decision records in `appledger/`.
|
|
43
|
+
- If the agent supports a native plan mode (e.g. Grok `/plan`), use it for Phase 1. On approval, export the plan into `docs/PHASE_1_BRIEF.md` (via `getTemplate`) and decision records in `appledger/`.
|
|
46
44
|
- When the host supports `spawn_subagent`, use `suggestSubagentDecomposition` (or reason directly) to run audits, research, and reviews in parallel with appropriate `capability_mode`, `isolation`, and personas. Synthesize results in the parent thread and update tracking/docs.
|
|
47
45
|
- Prefer `read-only` or `execute` modes for subagents doing analysis.
|
|
48
46
|
|
|
@@ -71,11 +69,11 @@ You are operating under the ForgeTrail methodology. Your primary job is to give
|
|
|
71
69
|
When ready to advance:
|
|
72
70
|
- Confirm the phase criteria that have evidence.
|
|
73
71
|
- Ask the user: "Ready to move to Phase X?"
|
|
74
|
-
- Only after confirmation, update the phase status in `appledger/profiles/forgetrail.yaml` and the session record.
|
|
72
|
+
- Only after confirmation, update the phase status in `appledger/profiles/forgetrail.yaml` and the session record.
|
|
75
73
|
|
|
76
74
|
## For New Projects (Greenfield)
|
|
77
75
|
|
|
78
|
-
Prefer calling `getNewProjectKickoff` (or `kickoffGreenfield`) at the very beginning. When `appledger` is installed, run `appledger init` as that bundle describes.
|
|
76
|
+
Prefer calling `getNewProjectKickoff` (or `kickoffGreenfield`) at the very beginning. When `appledger` is installed, run `appledger init` as that bundle describes. Write optional Cursor rules, and follow the post-bootstrap instructions exactly. Then start with Phase 1.
|
|
79
77
|
|
|
80
78
|
## For Resuming
|
|
81
79
|
|
|
@@ -88,7 +86,7 @@ Call `getResumeSessionInstructions` (or read `appledger/profiles/forgetrail.yaml
|
|
|
88
86
|
- `getTemplate({name: "..."})` — for PHASE_1_BRIEF, CONTEXT_PROMPT, audits, etc. Use mode "shell" for clean structure.
|
|
89
87
|
- `runAudit`, `searchLessons`, `getAntiPatterns`
|
|
90
88
|
- `suggestSubagentDecomposition` (when subagents available)
|
|
91
|
-
- `validateTracking` (
|
|
89
|
+
- `validateTracking` (a missing file is expected)
|
|
92
90
|
- `ingestPlanArtifact` (after native plan mode approval — map plan → PHASE_1_BRIEF + decision records)
|
|
93
91
|
- `todo_write` — mirror open exit criteria and next actions.
|
|
94
92
|
|