forge-orkes 0.77.0 → 0.80.0
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/bin/create-forge.js +27 -0
- package/experimental/m10/README.md +4 -4
- package/experimental/m10/install.sh +10 -9
- package/experimental/m10/source/hooks/protect-primary-checkout.sh +149 -0
- package/package.json +1 -1
- package/template/.claude/hooks/forge-context-migrate.sh +297 -0
- package/template/.claude/hooks/forge-size-gate.sh +175 -0
- package/template/.claude/hooks/forge-state-rollup.sh +135 -2
- package/template/.claude/hooks/protect-primary-checkout.sh +149 -0
- package/template/.claude/hooks/skill-gate-tiers.txt +6 -0
- package/template/.claude/hooks/tests/forge-context-migrate.test.sh +166 -0
- package/template/.claude/hooks/tests/forge-size-gate.test.sh +132 -0
- package/template/.claude/hooks/tests/protect-primary-checkout.test.sh +147 -0
- package/template/.claude/settings.json +14 -1
- package/template/.claude/skills/discussing/SKILL.md +30 -31
- package/template/.claude/skills/executing/SKILL.md +3 -3
- package/template/.claude/skills/forge/SKILL.md +112 -170
- package/template/.claude/skills/forge/references/manual-fallback-procedures.md +54 -0
- package/template/.claude/skills/initializing/SKILL.md +20 -1
- package/template/.claude/skills/planning/SKILL.md +11 -9
- package/template/.claude/skills/researching/SKILL.md +2 -0
- package/template/.claude/skills/reviewing/SKILL.md +17 -0
- package/template/.claude/skills/upgrading/SKILL.md +22 -2
- package/template/.claude/skills/verifying/SKILL.md +2 -2
- package/template/.forge/FORGE.md +81 -90
- package/template/.forge/bin/new-worktree.sh +61 -0
- package/template/.forge/bin/tests/new-worktree.test.sh +70 -0
- package/template/.forge/checks/forge-jarvis-awareness.sh +46 -2
- package/template/.forge/checks/forge-jarvis-relay.sh +64 -16
- package/template/.forge/checks/tests/forge-jarvis-awareness.test.sh +58 -0
- package/template/.forge/checks/tests/forge-jarvis-relay.test.sh +50 -0
- package/template/.forge/git-hooks/pre-commit +57 -0
- package/template/.forge/git-hooks/tests/pre-commit.test.sh +97 -0
- package/template/.forge/migrations/0.78.0-weld-primary-checkout.md +66 -0
- package/template/.forge/migrations/0.80.0-context-md-sharding.md +158 -0
- package/template/.forge/migrations/0.80.0-size-gate-wiring.md +145 -0
- package/template/.forge/templates/constitution.md +1 -1
- package/template/.forge/templates/context-milestone.md +30 -0
- package/template/.forge/templates/slice-runner/config.yml +7 -1
- package/template/.forge/templates/state/desire-path.yml +3 -0
- package/experimental/m10/source/hooks/forge-branch-guard.sh +0 -61
|
@@ -390,7 +390,26 @@ User selects per stack.
|
|
|
390
390
|
|
|
391
391
|
**Confirm with the user first** in brownfield (this edits a user-owned file). In greenfield with no existing `.gitignore`, write it directly. Re-run is idempotent — the carve-out lines `grep` to themselves.
|
|
392
392
|
|
|
393
|
-
8. **
|
|
393
|
+
8. **Wire the primary-checkout weld (`core.hooksPath`).** Welds the primary checkout to the default branch so all branch work happens in worktrees — every tier (issue #21, ADR-031). The tracked `.forge/git-hooks/pre-commit` backstop only fires once `core.hooksPath` points at it. This is per-clone git config, so init owns it. **Detect + warn, never clobber:**
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
want=".forge/git-hooks"
|
|
397
|
+
cur=$(git config --get core.hooksPath 2>/dev/null || true)
|
|
398
|
+
if [ -z "$cur" ] || [ "$cur" = "$want" ]; then
|
|
399
|
+
git config core.hooksPath "$want" # repo-relative → resolves inside every worktree
|
|
400
|
+
echo "[Forge] core.hooksPath → $want (primary-checkout weld active)."
|
|
401
|
+
else
|
|
402
|
+
echo "[Forge] core.hooksPath is already set to '$cur' (Husky/lefthook?). NOT overwriting."
|
|
403
|
+
echo " The primary-checkout pre-commit backstop (.forge/git-hooks/pre-commit) is"
|
|
404
|
+
echo " therefore inactive. To keep the weld, chain it into your existing hooks dir"
|
|
405
|
+
echo " (call .forge/git-hooks/pre-commit from your pre-commit), or accept the"
|
|
406
|
+
echo " PreToolUse-only coverage (Claude sessions are still guarded)."
|
|
407
|
+
fi
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**WHY repo-relative** (`.forge/git-hooks`, not an absolute path): an absolute `core.hooksPath` silently skips in linked worktrees (the documented Husky/lefthook worktree hazard — see `orchestrating/bootstrap-checks.md`); a repo-relative path resolves under each worktree checkout. **WHY never clobber:** silently disabling a consumer's existing hook framework is unacceptable.
|
|
411
|
+
|
|
412
|
+
9. **State-sync commit**: `git add .gitignore .claude/settings.json .claude/skills/ .claude/agents/ .claude/hooks/ .forge/` then `git commit -m "chore(forge): initialize forge state + track product files"` (scoped; never `git add .`) — so the new project's state and Forge product files are both in git from the start. (The tracked `.forge/git-hooks/` is included by the `.forge/` path; `core.hooksPath` itself is local git config, not a tracked file, so it needs no staging.)
|
|
394
413
|
|
|
395
414
|
*"Initialized. Ready?"*
|
|
396
415
|
|
|
@@ -31,20 +31,22 @@ If you find yourself writing a plan that only touches `src/models/`, `src/db/`,
|
|
|
31
31
|
|
|
32
32
|
## Step 1: Resolution Gate
|
|
33
33
|
|
|
34
|
-
Read `.forge/context.md` **Needs Resolution
|
|
34
|
+
Read `.forge/context-log.md` **Needs Resolution** (Needs Resolution is not milestone-scoped — it lives in the log, not a per-milestone file). If unchecked `- [ ]` items:
|
|
35
35
|
*"{N} items need input: [list]. For each: lock, defer, fix, or drop?"*
|
|
36
36
|
|
|
37
|
-
Load `.forge/context.md` as the active decision set
|
|
37
|
+
Load `.forge/context/{id}.md` as the active decision set for milestone `{id}`. Consult
|
|
38
38
|
`.forge/context-archive.md` only when the current milestone, stream, or
|
|
39
39
|
requirement cites an older milestone decision (for example M9 e2e policy or M14
|
|
40
|
-
backlog lifecycle).
|
|
40
|
+
backlog lifecycle) — check `.forge/context.md` (the derived index) first; if the
|
|
41
|
+
cited milestone has a row there, read its `context/{id}.md` directly instead of
|
|
42
|
+
the archive. Do not load archived decision blocks wholesale.
|
|
41
43
|
|
|
42
44
|
| Choice | Action |
|
|
43
45
|
|--------|--------|
|
|
44
46
|
| Lock | Record in Locked Decisions |
|
|
45
47
|
| Defer | Move to Deferred Ideas + revisit date |
|
|
46
48
|
| Fix | Add as FR-xxx in `.forge/requirements/m{N}.yml` (current milestone) |
|
|
47
|
-
| Drop | Note in Amendment Log |
|
|
49
|
+
| Drop | Note in Amendment Log (`.forge/context-log.md`) |
|
|
48
50
|
|
|
49
51
|
Mark resolved `- [x]`. Target: 2-5 min.
|
|
50
52
|
Scan **Carried Forward** -- items affecting current phase get same triage.
|
|
@@ -60,17 +62,17 @@ Record results in plan frontmatter.
|
|
|
60
62
|
|
|
61
63
|
## Step 3: Lock Decisions
|
|
62
64
|
|
|
63
|
-
If missing, create `.forge/context.md` from
|
|
65
|
+
If missing, create `.forge/context/{id}.md` from `.forge/templates/context-milestone.md`:
|
|
64
66
|
1. Ask user key decisions (framework, constraints, preferences)
|
|
65
67
|
2. **Locked Decisions** (contracts)
|
|
66
68
|
3. **Deferred Ideas** (out of scope)
|
|
67
69
|
4. **Discretion Areas** (agent picks)
|
|
68
70
|
|
|
69
|
-
Must complete BEFORE plans. Plans reference context.md.
|
|
71
|
+
Must complete BEFORE plans. Plans reference context/{id}.md.
|
|
70
72
|
|
|
71
73
|
If a plan depends on an archived decision, cite the archive section in the plan
|
|
72
74
|
or active context summary; do not copy the historical block back into
|
|
73
|
-
`.forge/context.md`.
|
|
75
|
+
`.forge/context/{id}.md`.
|
|
74
76
|
|
|
75
77
|
## Step 4: Structure Requirements
|
|
76
78
|
|
|
@@ -396,7 +398,7 @@ Prompt pattern:
|
|
|
396
398
|
> *"UI work detected. Invoke `testing` skill for e2e/integration coverage? (yes/no/later)"*
|
|
397
399
|
|
|
398
400
|
- **yes** — defer to `testing` after planning completes; note in plan frontmatter
|
|
399
|
-
- **no** — document rationale in `context.md` Discretion Areas
|
|
401
|
+
- **no** — document rationale in `context/{id}.md` Discretion Areas (or `context/_shared.md` if cross-cutting)
|
|
400
402
|
- **later** — rides on the verifying **Interface Testing Gate**: when `interface` is declared in `project.yml`, that gate already BLOCKS at verifying if UI tests are still missing (no separate planning hook needed)
|
|
401
403
|
|
|
402
404
|
Decision captured once, pre-code. Does not block planning.
|
|
@@ -472,7 +474,7 @@ Done when approved.
|
|
|
472
474
|
|
|
473
475
|
## Handoff
|
|
474
476
|
|
|
475
|
-
1. **Persist** -- plans `.forge/phases/`, reqs `.forge/requirements/m{N}.yml`, roadmap `.forge/roadmap.yml`, context `.forge/context.md`
|
|
477
|
+
1. **Persist** -- plans `.forge/phases/`, reqs `.forge/requirements/m{N}.yml`, roadmap `.forge/roadmap.yml`, context `.forge/context/{id}.md`
|
|
476
478
|
2. **Reserve version (if delivery bumps the version)** -- if any plan in this milestone will bump `package.json`/the project version: pull first, derive `version` = highest reserved `max()` bumped by this change's semver level, then **claim it in the ledger BEFORE editing releases.yml**: `.claude/hooks/forge-reserve.sh version --value <X.Y.Z> --milestone m-{N}` — a non-zero exit names the sibling milestone already holding that number (its reservation may be worktree-only and invisible in any file you can read): re-read `max()` counting the ledger's version claims and bump again (ADR-029). Then append ONE entry to `.forge/releases.yml` (Version Reservation Protocol, FORGE.md): `{milestone, version, bump, reserved_at, summary}`. **Never edit prior entries.** No version bump in scope → skip. Surface the reserved number to the user.
|
|
477
479
|
3. **State** -- `current.status` = `executing` in `.forge/state/milestone-{id}.yml`
|
|
478
480
|
4. **State-sync commit** (State Commit Protocol): `git -C {worktree_path} add .forge/` then `git -C {worktree_path} commit -m "chore(forge): sync state after planning — m{N} {phase-name}"` (worktree form — recorded `lifecycle.worktree_path` is authoritative over cwd; see FORGE.md State Commit Protocol. Scoped; never `git add .`). The `releases.yml` reservation rides in this commit — **push it** so a parallel session sees the number taken before they reserve.
|
|
@@ -9,6 +9,8 @@ Gather context before planning. Bad research leads to bad plans.
|
|
|
9
9
|
|
|
10
10
|
> Entered via a worktree already, for new work (R10, `forge/SKILL.md` Step 3) — research writes `.forge/research/` state, so if this skill is somehow invoked directly on the main checkout for new work, enter one now before writing anything.
|
|
11
11
|
|
|
12
|
+
If resuming research on an existing milestone, skim `.forge/context/{id}.md` first (if present) — decisions already locked there are out of scope for research now; don't re-investigate what's already settled.
|
|
13
|
+
|
|
12
14
|
## Research Types
|
|
13
15
|
|
|
14
16
|
### 1. Codebase Research
|
|
@@ -312,6 +312,22 @@ Deferred issues triage: Glob `.forge/deferred-issues/*.md` (else legacy `.forge/
|
|
|
312
312
|
- **Fix-now** → route to `planning` fix mode before completing milestone
|
|
313
313
|
- **Dismiss** → set `status: dismissed` + `dismissed_reason` in the issue's file (or the legacy file)
|
|
314
314
|
|
|
315
|
+
Close-the-loop triage (advisory — never blocks): catches shipped-but-still-open GitHub issues. Forge produces resolution artifacts (ADRs, desire-paths, CHANGELOG/commits) that cite the issue they resolve, but nobody circles back to close the issue — the open list accumulates already-done work. This step cross-references those artifacts against **open** issues and surfaces likely-resolved ones for the operator to close. **Detect-and-surface only — NEVER auto-close** (closing a GitHub issue is outward-facing → operator confirmation, agent safety rules).
|
|
316
|
+
|
|
317
|
+
1. **Gate / degrade first.** Resolve `forge.upstream_repo` from `project.yml`. If absent, OR `gh` not on PATH, OR `gh auth status` fails, OR offline → **skip the whole step** (at most one log line: *"close-the-loop: gh unavailable — skipped"*). Never blocks reviewing or completion. (Same posture as `forge/desire-paths-review.md`'s resolve→check-gh→offer and notion-integration's advisory-everywhere.)
|
|
318
|
+
2. **Collect resolution-intent `#N` refs produced THIS milestone** (milestone-scoped default — cheap, fires when the artifact is fresh):
|
|
319
|
+
- **ADRs** authored/touched this milestone whose `**Context source:**` / `resolves` / `closes` line cites `forge#N` (or the `…/issues/N` URL). **Exclude bare supersession / see-also mentions** — a *"Superseded by ADR-021 ([forge#19](…))"* note references #19, it does not resolve it. Only resolution-intent lines count.
|
|
320
|
+
- **desire-path** files with `resolves_issue: N`.
|
|
321
|
+
- **CHANGELOG / commit** lines landed this milestone with `closes|fixes|resolves #N`.
|
|
322
|
+
Scope by this milestone's git range / this milestone's artifacts — prose-directed grep, no executable.
|
|
323
|
+
3. **Intersect cited ∩ still-open.** `gh issue view N --json state,title` each; **keep only `state == OPEN`**. An `#N` gh can't resolve (nonexistent / transferred / errors on that call) OR reports CLOSED → **no candidate** (surface only gh-confirmed-open — zero false positives). Skip any `#N` with a `.forge/state/issue-loop/declined/{N}.yml` marker (glob first — mirrors the desire-path `declined/` skip).
|
|
324
|
+
4. **Surface survivors** (existing triage idiom): *"**Close-the-loop** ({N}): 1. #N '{title}' — looks resolved by {artifact} — close it? [y/N]"*.
|
|
325
|
+
- **y** (or "close") → **do NOT close autonomously.** Print the exact command for the operator to run (or to approve Forge running as an explicit per-action step): `gh issue close N --comment "Resolved by {artifact} ({ref}). Closing via Forge close-the-loop."`
|
|
326
|
+
- **N** (or "still open") → write `.forge/state/issue-loop/declined/{N}.yml` (`{issue: N, declined_at: <ISO date>, reason: "<one line>"}`; create the dir if absent) so it is not re-nagged. The marker is inert once the issue actually closes (gh stops returning it as open).
|
|
327
|
+
5. **Optional full sweep** (operator-invoked, natural language — no new command): if the operator asks *"run a full close-the-loop sweep"* / *"check for orphaned issues"*, run steps 1–4 over **all** open issues × **all** shipped resolution artifacts repo-wide (not just this milestone), same rules + `declined/` markers. This is the periodic-cleanup path; the milestone-scoped default stays quiet.
|
|
328
|
+
|
|
329
|
+
Zero candidates → silent (the common case). This step is **advisory — it never gates milestone completion** (see Gates).
|
|
330
|
+
|
|
315
331
|
## Step 7: Backlog + Route
|
|
316
332
|
|
|
317
333
|
### Backlog
|
|
@@ -371,6 +387,7 @@ Idempotent: a backlog with no terminal items and all-canonical statuses is left
|
|
|
371
387
|
- **Security/arch critical** -> soft gate (accept risk)
|
|
372
388
|
- **Warnings** -> advisory
|
|
373
389
|
- **Refactoring** -> never block
|
|
390
|
+
- **Close-the-loop** -> advisory, never blocks (detect-and-surface only; never auto-closes)
|
|
374
391
|
|
|
375
392
|
Report = audit trail.
|
|
376
393
|
|
|
@@ -119,6 +119,25 @@ Rebase now? (each / list-only / skip)
|
|
|
119
119
|
- **list-only / skip** → print the commands; the operator runs them at a safe stopping point.
|
|
120
120
|
- Gitignored carve-outs (`.mcp.json`, experimental hooks) are not carried by a rebase — whenever layer (b) re-synced anything, add: each worktree must re-run `experimental/{pkg}/install.sh`.
|
|
121
121
|
|
|
122
|
+
### e. Primary-checkout weld (`core.hooksPath`)
|
|
123
|
+
|
|
124
|
+
Runs on every upgrade (registry and Dev Mode alike) — the bin syncs the `.forge/git-hooks/` body, but `core.hooksPath` is per-clone git config the bin never touches (issue #21, ADR-031). Wire it with the **detect + warn, never clobber** policy — identical to `initializing` Finalize step 8. Main checkout only (`git rev-parse --git-dir` == `--git-common-dir`; from a worktree, skip — the primary checkout owns the config):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
want=".forge/git-hooks"
|
|
128
|
+
cur=$(git config --get core.hooksPath 2>/dev/null || true)
|
|
129
|
+
if [ -z "$cur" ] || [ "$cur" = "$want" ]; then
|
|
130
|
+
git config core.hooksPath "$want" # repo-relative → resolves inside every worktree
|
|
131
|
+
echo "[Forge] core.hooksPath → $want (primary-checkout weld active)."
|
|
132
|
+
else
|
|
133
|
+
echo "[Forge] core.hooksPath is already '$cur' (Husky/lefthook?). NOT overwriting — the"
|
|
134
|
+
echo " primary-checkout pre-commit backstop is inactive. Chain .forge/git-hooks/pre-commit"
|
|
135
|
+
echo " into your existing hooks dir to keep the weld, or accept PreToolUse-only coverage."
|
|
136
|
+
fi
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Idempotent — re-running an upgrade that already wired it is a silent no-op. **WHY repo-relative + never-clobber:** same reasons as `initializing` step 8 (worktree-resolvable path; a consumer's Husky/lefthook must never be silently disabled).
|
|
140
|
+
|
|
122
141
|
## Dev Mode (`/upgrading dev` — explicit only)
|
|
123
142
|
|
|
124
143
|
Local-clone sync for developing Forge itself: test framework changes in a project without publishing to npm. Presence of `.forge/dev-source` NEVER selects this mode — only the explicit `dev` argument does.
|
|
@@ -141,7 +160,7 @@ Dev mode syncs from a checkout, so it keeps file-classification semantics — **
|
|
|
141
160
|
|
|
142
161
|
- **Framework-owned** (`.claude/agents/*.md`, `.claude/skills/*/SKILL.md`, `.forge/FORGE.md`) → overwrite when different. Ownership is per top-level **unit** — a skill DIR under `.claude/skills/`, a flat agent FILE under `.claude/agents/`: a unit the template doesn't ship (user-authored, vendored-parity, or an opt-in experimental skill) is **preserved, never deleted**; only stale files *inside* a still-shipped skill dir are cleaned. Experimental skills additionally get the staleness pass below.
|
|
143
162
|
- **Template-only** (`.forge/templates/**`, `.forge/migrations/**`, `.forge/adapters/**`, `.forge/gitignore` → `.forge/.gitignore`) → overwrite; `.forge/FORGE.md` lands BEFORE the CLAUDE.md pass.
|
|
144
|
-
- **Additive** (`.claude/hooks/**` incl. `tests/`, `.claude/rules/**`, `.forge/checks/**`) → add + overwrite template-shipped files, never delete local extras, `chmod +x` synced `*.sh`.
|
|
163
|
+
- **Additive** (`.claude/hooks/**` incl. `tests/`, `.claude/rules/**`, `.forge/checks/**`, `.forge/git-hooks/**`) → add + overwrite template-shipped files, never delete local extras, `chmod +x` synced `*.sh` (and the extensionless git hooks under `.forge/git-hooks/`).
|
|
145
164
|
- **Import-managed** `CLAUDE.md` → the bin's `ensureClaudeMdImport()` cases verbatim; user content outside a forge section is never modified.
|
|
146
165
|
- **Merge-owned** `.claude/settings.json` → `forge.*` keys + additive hook-group wiring only; stamp `forge.version` last.
|
|
147
166
|
- **Never touch** user-generated files: `.forge/project.yml`, `.forge/state/`, `.forge/constitution.md`, `.forge/context.md`, `.forge/requirements/`, `.forge/roadmap.yml`, `.forge/design-system.md`, `.forge/refactor-backlog.yml`.
|
|
@@ -150,11 +169,12 @@ Render the same report shape as the default path, with `Source: {path}` instead
|
|
|
150
169
|
|
|
151
170
|
### Post-sync layers
|
|
152
171
|
|
|
153
|
-
Re-use layers (a)–(
|
|
172
|
+
Re-use layers (a)–(e) with dev-derived inputs — this is the one mode that computes them itself, since there is no engine JSON:
|
|
154
173
|
|
|
155
174
|
- **(a) Migrations** — the data-driven Detection loop: select freshly-synced guides `.forge/migrations/{v}-*.md` where `installed < v <= source` (semver on the PRE-stamp installed version), run each guide's `## Detection` bash block from the project root; `MIGRATE` on stdout → the layer-(a) prompt with the text after `MIGRATE —` as the reason; no output → `{v}: no action`; block errors → `{v}: detection error (skipped)`, never abort the loop. Range bookkeeping is implicit: once `forge.version` is stamped, crossed guides fall out of the next run's range — no ledger.
|
|
156
175
|
- **(b) Experimental staleness** — diff installed non-template skill dirs against `{source}/packages/create-forge/experimental/*/source/skills/{name}/`; stale → the layer-(b) offer with `{source}` as the source path.
|
|
157
176
|
- **(c) Codex** — presence glob (`.agents/` / `.codex/`) → the layer-(c) offer.
|
|
158
177
|
- **(d) Worktrees** — `git worktree list --porcelain` filtered to `refs/heads/forge/m-*`, main checkout only (`git rev-parse --git-dir` == `--git-common-dir`; from a worktree, skip and say so) → the layer-(d) offer.
|
|
178
|
+
- **(e) Primary-checkout weld** — wire `core.hooksPath` with the detect+warn+never-clobber policy above (main checkout only). Same behavior in Dev Mode as on the registry path.
|
|
159
179
|
|
|
160
180
|
Same consent gates, same report lines as the registry path.
|
|
@@ -19,7 +19,7 @@ After `/clear`, load with fresh eyes — don't carry the executor's assumptions:
|
|
|
19
19
|
Read: .forge/state/milestone-{id}.yml → current phase, plans completed
|
|
20
20
|
Read: .forge/project.yml → tech stack (for running tests)
|
|
21
21
|
Read: .forge/phases/milestone-{id}/{phase}-{name}/plan-{NN}.md → must_haves (truths, artifacts, key_links)
|
|
22
|
-
Read: .forge/context.md → locked decisions
|
|
22
|
+
Read: .forge/context/{id}.md → locked decisions for this milestone
|
|
23
23
|
Read: .forge/requirements/m{N}.yml → requirement IDs for coverage check (current milestone, resolved from state)
|
|
24
24
|
Read: .forge/deferred-issues/*.md → known pre-existing failures (glob the dir; else legacy .forge/deferred-issues.md; advisory)
|
|
25
25
|
```
|
|
@@ -295,7 +295,7 @@ After verification completes (PASSED or GAPS FOUND), run a quick retrospective o
|
|
|
295
295
|
|
|
296
296
|
**6. User corrections**: User correct the same thing multiple times? Implicit rules that should become explicit.
|
|
297
297
|
|
|
298
|
-
**Set `scope` on each observation** (see ADR-012): `framework` when the fix targets Forge's own skills/templates (tier heuristics, a skill's step, a template); `project` when it targets user-owned files (`constitution.md`, `design-system.md`, `context.md`). Record `suggestion_target` when known. This classifies the signal at write time so review can route `framework` signals upstream. Tier-override signals (#2) and the "constitution needs a new article" deviation case (#1) are usually `framework` and `project` respectively — judge by the file the fix touches, not the type.
|
|
298
|
+
**Set `scope` on each observation** (see ADR-012): `framework` when the fix targets Forge's own skills/templates (tier heuristics, a skill's step, a template); `project` when it targets user-owned files (`constitution.md`, `design-system.md`, `context/{id}.md`). Record `suggestion_target` when known. This classifies the signal at write time so review can route `framework` signals upstream. Tier-override signals (#2) and the "constitution needs a new article" deviation case (#1) are usually `framework` and `project` respectively — judge by the file the fix touches, not the type.
|
|
299
299
|
|
|
300
300
|
**Surfacing is owned by `forge` boot — not here** (single review owner, ADR-012). `verifying` only *records* observations; it does not surface recommendations, prompt for fixes, or archive. The 3+ aggregation, the type→evolution suggestion table, the decline-ledger, and upstream routing all live in `forge` Step 1.2. Write the observation files (with `scope`) and move on — the next `forge` boot reviews them.
|
|
301
301
|
|