release: v0.3.0 — IDEF0 composed-map program (render, drill-down, onboarding, 3D-iso) - #172
Merged
Merged
Conversation
…rrors Adopts forgeplan ≥ 0.28 slug-canonical identity in the Web viewer and replaces the generic 502 from /api/snapshot with a discriminated error envelope. One PR, one touch on shared/server/snapshot.ts (RFC-015 G-4). Changes: - ArtifactSummary / ArtifactDetail / ArtifactSnapshot extended with five optional identity fields (slug, predicted_number, assigned_number, id_canonical, id_display). Legacy artefacts without slug coexist via optional-field fallback. - New entities/artifact/lib/identity.ts — single displayId(a) helper used by every UI surface that renders an artefact identifier (7 graph view modes + InsightsRail + ArtifactPanel header + markdown export). Preserves the "?" marker for drafts verbatim from the CLI. - New entities/artifact/lib/identifier-guard.ts — three-shape route guard (display id / draft with marker / slug). /api/get/[id] now accepts slug input and PRD-74? without 400. - shared/server/snapshot.ts — reconstructFromWorktree returns a discriminated union with six error codes (host_config_missing, worktree_add_failed, reindex_failed, list_parse_failed, graph_parse_failed, commit_unreachable). Pre-flight git cat-file -e detects pruned SHAs explicitly. Two FIXME markers from PRD-008 (worktree-add, reindex-failure) replaced with explicit error returns. - New sanitizeStderr — strips host paths under /Users/, /home/, /private/var/, redacts env-style assignments, truncates at word boundary <= 1024 chars (RFC-015 D-5 + I-4). - /api/snapshot failure envelope adds error_code + stderr_excerpt; legacy `error: string` preserved for rollback path. Successful envelope unchanged (NFR-006). widgets/timeline/lib/snapshot-state forwards the new fields to the store. Why: - Pre-merge artifacts with slug-only identity returned 400 from /api/get/[id], leaking through silent type erasure to all 7 graph views. Drafts and activated artifacts looked identical (no `?` marker). PRD-016 §Problem. - Real-world incident on @gertsai/shared: host gitignored .forgeplan/config.yaml legitimately, reindex aborted with "os error 2", /api/snapshot returned a generic 502, ~60min spent narrowing the cause. The two FIXME markers in snapshot.ts (:268-270, :282-284) had documented this for months. Now the API surfaces host_config_missing with the literal "os error 2" excerpt preserved (PRD-016 AC-6) and points at guides/FORGEPLAN-GITIGNORE.md. Tests: - npm run check — 1052 files, 0 errors / 0 warnings (NFR-001 / AC-5). - npx vitest run — 18 files, 179 tests passed. - 33 new tests: 4 displayId, 18 identifier-guard, 11 sanitizeStderr + isHostConfigMissingError. Refs: PRD-016, RFC-015, EVID-021
## Summary Back-merge of v0.2.4 from `main` into `develop` — propagates the `0.2.4` version bump so subsequent feature branches start at the published SHA. Branch `release/v0.2.4` was auto-deleted after merging PR #149; this branch was created off `main` to perform the same back-merge per [`CLAUDE.md` Release procedure §10](../blob/develop/CLAUDE.md). ## Why Standard final step of the release flow. ## Notes - `v0.2.4` tag pushed on `main` ✅ - GitHub Release v0.2.4 published ✅ - `release.yml` ran but `npm publish` returned **404 PUT @forgeplan/web** — likely `NPM_TOKEN` repo secret needs rotation. Tag is intact; can rerun the workflow after the secret is refreshed, or publish manually. NOT a blocker for this PR. Refs: PRD-033, RFC-027, EVID-039
The /api/snapshot failure branch serialised only {ok, at, sha, error},
silently dropping the error_code + stderr_excerpt that getSnapshot()
already produces (RFC-015 D-4). The client store and Timeline never saw
them, so the structured-error UX (incl. the host_config_missing
remediation hint) was dead end-to-end. Forward both fields and render
them in Timeline (code badge + collapsible sanitized stderr). Add an
endpoint regression test that asserts the failure payload carries them.
Also reconcile the identity-field comments with the forgeplan 0.33
contract audit: the CLI never emits the identity triple — list/get --json
expose only a nullable top-level slug; id_display/id_canonical are
MCP-DTO-only (>= 0.31), predicted_number/assigned_number are frontmatter
only. The display-path stays as forward-compatible scaffolding (degrades
to raw id); the prior ">= 0.28 returns the triple" comments were false.
Refs: RFC-015, PRD-016
Referenced by the host_config_missing snapshot error now surfaced in the Timeline (RFC-015 D-4). Documents the canonical .forgeplan/.gitignore contract — why config.yaml / notes/ / state/ must be tracked and session.yaml must not — and the one-commit migration from a drifted state. Refs: RFC-015 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…apshot errors (#151) ## Summary - Adapts the `@forgeplan/web` viewer to forgeplan's **slug-canonical identity** (PROB-060): the `/api/get/[id]` guard now accepts slug / lowercase / draft-marker ids (no more false 400s); 5 optional identity fields are threaded through the artifact + snapshot types; node labels route through `displayId()`. - Adds **structured `/api/snapshot` failures** (RFC-015 D-4): `SnapshotErrorCode` + sanitized `stderr_excerpt`, with a `host_config_missing` detector that points users at the new `guides/FORGEPLAN-GITIGNORE.md`. - **Fixes a dead wire** caught by a forgeplan-0.33 contract audit: the endpoint dropped `error_code`/`stderr_excerpt` (serialised only `{ok,at,sha,error}`) although `getSnapshot()` produced them. Now forwarded + rendered in the Timeline, guarded by a regression test. - **Reconciles misleading comments.** The forgeplan **CLI** never emits the identity triple — `list`/`get --json` expose only a nullable top-level `slug`; `id_display`/`id_canonical` are MCP-DTO-only (>= 0.31), `predicted_number`/`assigned_number` are frontmatter-only. ## Why - forgeplan 0.31+ introduced slug-canonical identity so parallel branches stop colliding on sequential numbers. The viewer must not 400 on slug/draft ids and should surface actionable snapshot errors instead of a generic 502. - **Honest caveat for review:** against the CLI transport this app uses (rule 22), the identity *display* path (`displayId`, 7 graph views) is currently **dormant** — `id_display` never arrives, so labels degrade to the raw id (byte-identical to pre-PROB-060). It is kept as forward-compatible scaffolding (revert+re-add would cost more than the harmless sleep). The genuinely live new behaviour is the route-guard widening + the structured-error surfacing. Full audit verdict + delta in EVID-040. ## Test plan - `npm run check` -> 0 errors / 0 warnings (1082 files). - `npm test` -> 192/192 (21 files), incl. new `src/routes/api/snapshot/endpoint.test.ts` regression (asserts the failure payload carries `error_code`/`stderr_excerpt`; fails if the fix is reverted). - Independent code-review: PASS, 0 findings; rule 22 (GET-only read-only proxy) + rule 24 (no primitive overrides) verified. - Evidence: EVID-040 (CL3, verdict=supports, evidence_type=test); RFC-015 r_eff=1. Refs: PRD-016, RFC-015, EVID-040 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The PROB-060 fix evidence (EVID-040, code-review PASS of commit 0101560) and its informs-links to RFC-015 / PRD-016 were created in the workspace during the fix but never committed — PR #151 carried only template/ + the guide. Land the markdown so the artifact graph matches reality (markdown is source of truth; EVID-040 active, RFC-015 r_eff=1). Refs: RFC-015, PRD-016, EVID-040 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… links (#152) ## Summary Lands the PROB-060 fix evidence that PR #151 omitted. `EVID-040` (independent code-review PASS of commit `0101560`, RFC-015 D-4 wire fix) and its `informs` links to `RFC-015` / `PRD-016` were created in the `.forgeplan/` workspace during the fix but never committed — #151 carried only `template/` source + the guide. ## Why Markdown is the source of truth for the artifact graph (parent ADR-003). Every other EvidencePack (EVID-001..021) is tracked; EVID-040 must be too, or the graph on `develop` is incomplete and `RFC-015`'s evidence chain is missing its review. EVID-040 is active with structured fields (`verdict: supports`, `congruence_level: 3`, `evidence_type: test`); locally it gives RFC-015 `r_eff=1`. ## Test plan - Docs/artifact-only change (3 markdown files under `.forgeplan/`); no source touched. - `forgeplan validate EVID-040` → PASS; structured fields present. Refs: RFC-015, PRD-016, EVID-040 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Both features are already implemented on develop — the artifacts just lagged in draft. Verified by a per-feature implementation audit against the develop codebase: - version-footer (PRD-012 / RFC-011 / EVID-016): 5/5 FRs in code — widgets/version-footer/ui/VersionFooter.svelte (web version via __FORGEPLAN_WEB_VERSION__) + routes/api/version/+server.ts + getForgeplanVersion() in shared/server/forgeplan.ts. R_eff=1.00. - template-hardening (RFC-003 / EVID-006): runes migration (0 legacy export let / createEventDispatcher / slot / svelte/store across 84 .svelte files) + read-only proxy enforcement (READ_ONLY_SUBCOMMANDS allow-list in shared/server/forgeplan.ts). R_eff=1.00. Closes the stuck-draft EVID-006/EVID-016 anomalies (both ~1300h in draft). Refs: PRD-012, RFC-011, RFC-003, EVID-016, EVID-006 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "Update available" button reappeared on every poll/reload with no way to dismiss it — the last open FR of PRD-013 (shared-ui). The UpdateDialog now offers "Dismiss for this session", which resolves the modal promise with a 'dismiss' sentinel; VersionFooter records the dismissed `latest` version in sessionStorage and hides the button while it matches. A newer release re-surfaces it (stored version no longer matches); dialog content is never lost. Logic extracted to lib/session-dismiss.ts (pure, SSR-safe) with unit tests (shouldShowUpdate gate + persistence round-trip + throw/SSR fallbacks). svelte-check 0/0 (1084 files), vitest 198/198. With FR-011 done, shared-ui is feature-complete (9/9 MUST + 3/3 SHOULD) — activate its artifacts (EVID-017 → PRD-013 → RFC-012, R_eff=1.00). Clears the last stuck-draft EVID anomaly (EVID-017, ~1300h). Refs: PRD-013, RFC-012, EVID-017 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…g artifacts (#153) ## Summary Activates 5 forgeplan artifacts whose features are **already implemented on develop** but whose paperwork lagged in `draft`. Verified by a per-feature implementation audit against the develop codebase (no code change in this PR — `.forgeplan/` markdown only). | Feature | Artifacts | Evidence on develop | |---|---|---| | version-footer | PRD-012, RFC-011, EVID-016 | `widgets/version-footer/ui/VersionFooter.svelte` + `routes/api/version/+server.ts` + `getForgeplanVersion()`; 5/5 FRs; R_eff=1.00 | | template-hardening | RFC-003, EVID-006 | runes migration (0 legacy patterns / 84 .svelte) + `READ_ONLY_SUBCOMMANDS` allow-list (rule 22); R_eff=1.00 | ## Why Both EVID-006 and EVID-016 were stuck in draft ~1300h (flagged by `forgeplan anomalies`). The work shipped long ago under other PRs; this just reconciles the artifact graph with reality and clears the stuck-draft noise. ## Test plan - `forgeplan validate` PRD-012 / RFC-011 / RFC-003 → 0 errors (warnings only). - `forgeplan score` → R_eff 1.00 on all three after activating the evidence. - Implementation audit cited concrete file paths satisfying every MUST FR. Refs: PRD-012, RFC-011, RFC-003, EVID-016, EVID-006 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…shared-ui (#154) ## Summary Implements the last open requirement of **PRD-013 (shared-ui)** — **FR-011**: the "Update available" affordance can be dismissed for the session without losing the dialog content. With it done, shared-ui is feature-complete, so this PR also activates its artifacts. **Code (FR-011):** - `UpdateDialog.svelte` — new "Dismiss for this session" action → `modalManager.close(modalId, 'dismiss')`. - `VersionFooter.svelte` — awaits the dialog result; on `'dismiss'` records the dismissed `latest` in `sessionStorage` and hides the button while it matches. A newer release re-surfaces it. - `lib/session-dismiss.ts` (new, pure + SSR-safe) — `readDismissedVersion` / `writeDismissedVersion` / `shouldShowUpdate` gate. - `lib/session-dismiss.test.ts` (new) — gate logic + persistence round-trip + throw/SSR fallbacks. **Paperwork:** EVID-017 → PRD-013 → RFC-012 activated (R_eff=1.00). Clears the last stuck-draft EVID anomaly (EVID-017, ~1300h in draft). ## Why Per-feature audit found shared-ui at 9/9 MUST + 2/3 SHOULD, missing only FR-011 (a SHOULD). Rather than mark it won't-fix, we built it — a non-dismissible update nag is a real UX wart, and the fix is small. ## Test plan - `npm run check` → 0 errors / 0 warnings (1084 files). - `npm test` → 198/198 (22 files), incl. 6 new `session-dismiss` tests. - `forgeplan validate` PRD-013 / RFC-012 → 0 errors; R_eff 1.00 after EVID-017 active. Refs: PRD-013, RFC-012, EVID-017 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Toggle-gated risk overlay on the dependency graph: nodes whose R_eff is degraded (< 0.6) glow with a drop-shadow halo whose radius scales by a composite riskScore (RFC-008: (1-R_eff) × decay_factor over a 90-day window). Plus a "Risk anatomy" section in ArtifactPanel (composite score, decay timer, informing-evidence list with the weakest EVID marked). Implementation notes / deviations (all documented, justified): - rule 22: risk is computed CLIENT-SIDE from already-fetched /api/score + /api/graph — zero /api files changed, no /api/decay added. - rule 24: the on/off control uses the shared Toggle primitive, which grows a `dataAction` prop (no :global override). - Glow applies to the 4 box-views (Force/Tree/Radial/Lanes) only. Matrix (.cell grid) / Sankey (.bar) / Sunburst (.arc) have no per-node concept, so SC-9 "no glow on Sankey/Sunburst" holds unconditionally; the toolbar toggle disables when every visible pane is sankey/sunburst. - FR-003 uses filter: drop-shadow (clips to shape in SVG) instead of the PRD's box-shadow wording (which does not clip in SVG — RFC's rejected C). - FR-007 (Should) is degraded: per-EVID congruence_level/evidence_type live only in EVID body markdown, not in any allow-listed JSON, so they render as "—"; the SC-6 DOM contract (.weakest on lowest-R_eff EVID) is met via /api/score. Widening the allow-list was deliberately avoided. svelte-check 0/0 (1086 files); vitest 236/236 (+11 risk-score cases). Refs: PRD-009, RFC-008
EVID-041 records the design→build→verify result (svelte-check 0/0, vitest 236/236, rule 22/24 PASS, all Must FRs met; FR-007 degraded by rule-22 — documented). Linked informs→PRD-009/RFC-008, R_eff=1.00. Refs: PRD-009, RFC-008, EVID-041
…#155) ## Summary Implements **PRD-009 / RFC-008 — risk overlay**. A toggle-gated drop-shadow halo on dependency-graph nodes whose R_eff is degraded (`< 0.6`); halo radius scales by a composite `riskScore` (RFC-008: `(1 − R_eff) × decay_factor` over a 90-day window). Plus a "Risk anatomy" section in ArtifactPanel (composite score, decay timer, informing-evidence list with the weakest EVID flagged). Built design→build→verify via workflow; orchestrator re-verified on the tree. ## Verification - `npm run check` → **0 errors / 0 warnings** (1086 files). - `npm test` → **236/236** (23 files; +11 pure `risk-score` cases). - **rule 22** ✓ — 0 `/api` files changed; risk computed client-side from already-fetched `/api/score` + `/api/graph` (no `/api/decay`, no allow-list widening). - **rule 24** ✓ — on/off uses the shared `Toggle` primitive (grew a `dataAction` prop; no `:global()` override). - Evidence: **EVID-041** (CL3, verdict=supports), `informs`→PRD-009/RFC-008, R_eff=1.00. ## Decisions made autonomously (flag if you disagree — revertible) 1. **FR-007 (Should) degraded** — per-EVID `congruence_level`/`evidence_type` aren't in any allow-listed JSON (only in EVID body markdown). The SC-6 DOM contract (`.weakest` on the lowest-R_eff EVID) is met via `/api/score`; CL/type render as "—". Allow-list widening deliberately avoided. Proper fix is upstream (expose CL/type in `get`/`score --json`). 2. **Matrix / Sankey / Sunburst excluded from glow** — no per-node concept there; glow applies to the 4 box-views (Force/Tree/Radial/Lanes). SC-9 ("no glow on Sankey/Sunburst") holds unconditionally; toolbar toggle disables when every visible pane is sankey/sunburst. 3. **`filter: drop-shadow` not `box-shadow`** — box-shadow doesn't clip to shape inside SVG (RFC's rejected option C). 4. **Graph-level glow radius reflects R_eff only** (not decay) — `valid_until` isn't on the bulk list, only on `get`; the full composite (R_eff × decay) is shown in the ArtifactPanel risk-anatomy section. ## Safety Branch → revertible PR into **develop** (test integration). Nothing shipped to prod (main/npm untouched). Toggle defaults **off**, persisted per-user via settings. Refs: PRD-009, RFC-008, EVID-041 🤖 Generated with [Claude Code](https://claude.com/claude-code)
New widgets/stats-pulse: a 6th InsightsRail "Stats" tab with a health score (0..100, deterministic median-based formula), R_eff histogram, weekly velocity, status-transitions, and a decay signal — plus per-chart plain-language status badges + tooltips. All computed CLIENT-SIDE from already-polled allow-listed endpoints (/api/list, /api/score, /api/health, /api/log, /api/stale); charts are widget-local SVG on CSS tokens. Deliberately DROPPED two spec items that violate hard constraints (the implementation does NOT include them): - GET /api/pulse (RFC-009) — not an allow-listed read-only subcommand (rule 22). Stats are aggregated client-side instead. - server-written .forgeplan-web/health-history.json (RFC-009) — violates init host-isolation (rule 20). The 30-day trend (FR-011) is instead reconstructed client-side by replaying the /api/log event stream. - FR-003 decay calendar ships as a coarse at-risk/stale proxy from /api/health: valid_until is only on /api/get/[id], not any allow-listed aggregate; a true 12-month heat-map needs opt-in per-id fan-out (TODO). svelte-check 0/0 (1103 files); vitest 299/299 (+63 stats-pulse cases). PRD-010/RFC-009 bodies reconciled separately to match this as-built shape. Refs: PRD-010, RFC-009
… reconcile spec EVID-042 records the verified build (svelte-check 0/0, vitest 299/299, rule 22/24 PASS, all Must FRs). PRD-010 + RFC-009 gain an "As-Built Reconciliation" section marking the constraint-violating surfaces (GET /api/pulse, server-written health-history.json) as superseded — they are not in the code; stats compute client-side. R_eff=1.00. Refs: PRD-010, RFC-009, EVID-042
…#156) ## Summary Implements **PRD-010 / RFC-009 — workspace pulse**. A 6th InsightsRail "Stats" tab: deterministic health score (0–100, median-based), R_eff histogram, weekly velocity, status-transitions, decay signal — each with a plain-language status badge + tooltip. New FSD widget `widgets/stats-pulse`; charts are widget-local SVG on CSS tokens; pure compute in `lib/` with co-located tests. Built design→build→verify via workflow; verifier re-ran independently. ## Verification - `npm run check` → **0 / 0** (1103 files). - `npm test` → **299/299** (28 files; +63 stats-pulse cases). - **rule 22** ✓ — no `/api/pulse`; stats from allow-listed `/api/list`, `/api/score`, `/api/health`, `/api/log`, `/api/stale`. - **rule 24** ✓ — charts widget-local SVG (tokens only); 6th tab reuses Tabs/TabsList; no `:global()` into primitives. - Evidence **EVID-042** (CL3, supports), R_eff=1.00. ##⚠️ Spec reconciliation (important) PRD-010/RFC-009 originally **mandated two surfaces that violate hard constraints** — both deliberately **NOT** built, and now marked superseded via an "As-Built Reconciliation" section in each artifact: 1. **`GET /api/pulse` — dropped** (rule 22: not an allow-listed read-only subcommand). Stats compute **client-side**. 2. **server-written `.forgeplan-web/health-history.json` — dropped** (rule 20: init host-isolation). FR-011's 30-day trend is **reconstructed client-side** from the `/api/log` event stream. 3. **FR-003 decay calendar — degraded** to a coarse at-risk/stale proxy from `/api/health` (`valid_until` is only on `/api/get/[id]`, not any allow-listed aggregate). True 12-month heat-map = opt-in per-id fan-out (`TODO(fr-003-calendar)`). Re-introducing #1/#2 to satisfy the original spec would break the red lines — the reconciliation is the correct call. ## Safety Branch → revertible PR into **develop**. Nothing shipped to prod. New tab is additive; defaults unaffected. Refs: PRD-010, RFC-009, EVID-042 🤖 Generated with [Claude Code](https://claude.com/claude-code)
New widgets/hints: a rule-DSL + ranking dispatcher that surfaces proactive hints from workspace state (stale spikes, low-R_eff artifacts, imminent valid_until, new blind spots, orphans, velocity drops). Rules are pure, fixture-tested, with single-file tunable thresholds (FR-005). Hints render via existing shared/ui primitives (no new primitive, no :global override). All inputs come from already-polled allow-listed endpoints (/api/health, /api/stale, /api/blindspots, /api/blocked, /api/score, /api/list) — NO /api/anomalies, no allow-list widening (rule 22). PRD-011/RFC-010 did not mandate a forbidden surface, so no spec reconciliation was needed. svelte-check 0/0 (1116 files); vitest 330/330 (+31 hint-rule/compute cases). Refs: PRD-011, RFC-010
EVID-043 records the verified build (svelte-check 0/0, vitest 330/330, rule 22/24 PASS, rule-DSL is a real engine). Hints compute client-side from allow-listed endpoints — no /api/anomalies, no spec reconciliation needed. R_eff=1.00. (Workflow verify step failed on a structured-output schema retry-cap; orchestrator verified directly — recorded in EVID-043.) Refs: PRD-011, RFC-010, EVID-043
## Summary Implements **PRD-011 / RFC-010 — proactive hints engine**. A rule-DSL + ranking dispatcher (`widgets/hints`) that surfaces actionable hints from workspace state: stale spikes, low-R_eff artifacts, imminent `valid_until`, new blind spots, orphans, velocity drops. Rules are pure + fixture-tested with single-file tunable thresholds (FR-005); hints render via existing shared/ui primitives. Built via workflow (design→build); the workflow's verify step hit an infrastructure failure (structured-output schema retry-cap), so the **orchestrator verified directly** on the tree. ## Verification - `npm run check` → **0 / 0** (1116 files). - `npm test` → **330/330** (30 files; +31 hint-rule/compute cases). - **rule 22** ✓ — 0 `/api` files changed; no `/api/anomalies`; hints from allow-listed `/api/health`, `/api/stale`, `/api/blindspots`, `/api/blocked`, `/api/score`, `/api/list`. - **rule 24** ✓ — hints use existing primitives; no `:global()` into internals. - Evidence **EVID-043** (CL3, supports), R_eff=1.00. - No spec reconciliation needed (PRD-011/RFC-010 didn't mandate a forbidden surface). ## Safety Branch → revertible PR into **develop**. Nothing shipped to prod. Additive widget. Refs: PRD-011, RFC-010, EVID-043 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The conformance audit found rule-22's text lagged shipped, artifact-backed reality: /api/snapshot + /api/timeline-events spawn `git` (read-only history reconstruction; snapshot also runs `forgeplan reindex` inside an ephemeral throwaway worktree, never the host index), and /api/instance-status exports an OPTIONS preflight + CORS for the cross-origin instance switcher. All are read-only and were merged under PRD-008/RFC-007, PRD-016/RFC-015, and #134; this amendment documents them so the next reviewer doesn't read them as violations. No code change — rule text only. Refs: RFC-007, RFC-015
…RS (#158) ## Summary Reconciles **rule-22** with already-shipped, artifact-backed `/api/*` endpoints that its text didn't describe (flagged by the v0.2.x conformance audit). **No code change — rule text only.** Two new sections + a verification carve-out: 1. **git-reconstruction endpoints** (`/api/snapshot`, `/api/timeline-events`) — they spawn **`git`** (not `forgeplan`) read-only for history; `/api/snapshot` runs `forgeplan reindex` **inside an ephemeral throwaway worktree** (documented exception to "forbidden reindex" — never the host index). All argv-based, validated SHA/ISO inputs, scoped to `.forgeplan/`, timed out. 2. **OPTIONS/CORS carve-out** (`/api/instance-status`) — uses only allow-listed `health`+`claims`, but exports a side-effect-free `OPTIONS` preflight + CORS `*` for the cross-origin instance switcher. ## Why The audit confirmed these endpoints are read-only and safe, but rule-22 didn't mention the "spawn git read-only" category or the OPTIONS preflight — so the next reviewer would read them as violations. These endpoints landed under PRD-008/RFC-007 (time-travel), PRD-016/RFC-015 (snapshot identity), and #134 (instance switcher); this is documentation reconciliation, not a new decision. ## Safety Branch → revertible PR into **develop**. Docs-only, no code touched. Refs: RFC-007, RFC-015
…col) Closes the "висяки" gap surfaced when the conformance audit left 3 orphaned claims (read-only reviewers crashed before release). rule-12 now mandates, orchestrator-side: - step 0: `forgeplan_claims` BEFORE dispatch — the next agent sees what is already taken and by whom (no double-assignment). - a "Claim hygiene — no висяки" section: sweep orphaned claims after every sprint/workflow, force-release on crash/timeout (not wait for TTL), sweep read-only reviewers' self-claims too; /smith + /autorun consult claims before recommending the next step. ADR-002 (the governing decision, which already specified this protocol + the `release --force` mitigation) was still draft — now activated with EVID-044 (audit: rule-12 exists+indexed+hardened, protocol exercised + orphans swept this session). R_eff 0.80. Clears a stuck draft. Refs: ADR-002, EVID-044
…col) (#159) ## Summary Hardens the sub-agent **claim discipline** so orphaned claims ("висяки") stop happening, and activates **ADR-002** (the governing decision) which was stuck in `draft`. **rule-12 additions (orchestrator MUST):** - **Step 0 — `forgeplan_claims` before dispatch:** the next agent checks what is already claimed and by whom → no double-assignment ("следующий смотрит, что взято и кто над этим работает"). - **"Claim hygiene — no висяки" section:** sweep orphaned claims after every sprint/workflow; force-release on crash/timeout (don't wait for TTL); sweep read-only reviewers' self-claims too; `/smith` + `/autorun` consult `forgeplan_claims` before recommending next work. **ADR-002 activated** (`draft → active`, R_eff 0.80) via **EVID-044** (audit: rule-12 exists + indexed + hardened; protocol exercised this session — the conformance audit's reviewers claimed RFC-008/009/010 then crashed; orphans swept via `release --force`). ## Why The conformance audit left 3 orphaned claims on RFC-008/009/010 (read-only `architect-reviewer`s crashed on a schema retry-cap before releasing). ADR-002 already anticipated this ("claim висит до expiry → mitigation `release --force`") but was never activated, and rule-12 lacked an explicit pre-check + post-run sweep. This change makes the discipline enforceable and in-force. ## Safety Branch → revertible PR into **develop**. Rules/artifact docs only — no code touched. Refs: ADR-002, EVID-044
Consolidates the durable learnings from the 0.33 work into one doc: CLI-vs-MCP contract (identity triple is MCP/frontmatter-only), R_eff semantics (decision-property; evidence packs read r_eff 0), the "cheap + self-correcting" process model, a stats-dashboard reading guide, and an index of the upstream issues filed (forgeplan #397/#394/ #393/#348/#374; marketplace #165/#166/#167) + local follow-ups. Refs: forgeplan#397, marketplace#165, marketplace#166, marketplace#167
## Summary One durable doc (`docs/forgeplan-insights-and-upstream.md`) capturing the useful learnings from the forgeplan-0.33 work: - **Insights:** CLI-vs-MCP contract (identity triple is MCP/frontmatter-only, dormant in the viewer); R_eff semantics (decision-property; EVIDs read r_eff 0); the "make mistakes cheap + self-correcting" process model. - **Stats dashboard reading guide** (the 4 stats-pulse panels — what/how/why/when). - **Upstream issues index:** forgeplan #397 (identity in JSON), #394 (dup-id), #393 (r_eff staleness), #348, #374; marketplace #165 (reviewer StructuredOutput), #166 (read-only self-claim leak), #167 (smith claims+digest). - **Local follow-ups:** risk-anatomy=1.00-on-EVID quirk, FR-007 degraded, PRD-017. Docs-only. Refs: forgeplan#397, marketplace#165/#166/#167.
…m index Refs: marketplace#168
One-line addition: the AGENT-AUTHORING-GUIDE addendum issue (marketplace#168) now appears in the upstream-issues table of `docs/forgeplan-insights-and-upstream.md`. Docs-only.
…/health probe RFC-035 follow-up. The Info tab's "Other projects" row only appeared after the first message, because otherInstances rode only on the WebSocket `ready` frame (opened lazily on first send). Now the cheap `fetch /health` liveness probe — which already polls every 15s — carries the same data, so the row (and model) populate the moment the chat opens, with no WebSocket and no subprocess. - agent.mjs: GET /health JSON gains `capabilities` + `otherInstances` (readOtherLiveInstances(self), try/catch → [] on any registry error), mirroring the ready frame. CORS header + shape otherwise unchanged. - agent-client.ts: ProbeResult carries optional capabilities/otherInstances; probeDaemon parses them from the /health JSON (malformed → []). - chat-store.ts: checkDaemon sets otherInstances from the probe result on tier1 — same state the ready frame feeds, so the 15s probe keeps it live even with no open connection. Tokens deliberately stay "—" until a real WS usage frame (correct — no usage before a turn). Deliberately does NOT touch the WS connection lifecycle (ensureConnection/connectAgent/send) — that path carried the earlier "stuck offline" bugs; the low-risk probe extension avoids it. Live-verified with two daemons: Info shows "sees 1 other · Work:7432" on chat open with zero messages sent. smoke 0, vitest 83/83, svelte-check 0. Note: a simultaneous-startup registry write race can briefly drop a row (self-heals via the 30s heartbeat) — pre-existing registry contention (RFC-035 I5), not introduced here. Refs: RFC-035 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The chat launcher floated over the map (bottom-right), which was in the way, and looked like an ordinary secondary button. Two changes: - shared/ui Button gains a `magic` variant (rule 24 — the look lives in the primitive): an animated iridescent rainbow gradient (hue-sliding shimmer), a soft pulsing glow, and two twinkling ✦ sparkle accents (pure CSS pseudo- elements, no dep). White label + text-shadow carry contrast in both themes; `prefers-reduced-motion` freezes to a static gradient. Showcased on /playground + documented in shared/ui/README.md. (Also fixed a self-inflicted compile break: a CSS comment containing `*/` closed the block early.) - The launcher moves OUT of the map overlay into the /onboard header, next to "Exit to standard view →", as a `variant="magic"` "✨ Ask" / "Close chat" button. ComposedMapView gains `showChatLauncher` (default true) + a bindable `chatOpen`, so the onboard host drives the chat from its header while the dashboard host keeps its own (now also magic) launcher — neither breaks. - Removed the `.map-chat-pos` absolute wrapper: its stacking context was trapping the RFC-035 FloatingWindow's position:fixed root inside a local paint order instead of letting it escape to the viewport. Live-verified on /onboard: magic Ask sits in the header off the map, opens the chat, toggles to Close chat. Full suite 58 files / 771 tests, svelte-check 0. Refs: RFC-035 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…boost gradient) Refines the launcher per user direction (supersedes the filled "✨ Ask" header button from 60ae14a): - New shared/ui `MagicStar` primitive: the ✨ sparkles motif (one main four-pointed sparkle + two small accent sparkles) drawn as a gradient-stroked CONTOUR (fill:none, stroke=animated linear-gradient) in extraboost.ai's signature palette (#5B8DEF → #9D7BEA → #FB7185 → #FBBF24 → #34D399, looping). The colors visibly cycle — a 3s SMIL gradient rotation + a 4s CSS hue-rotate sweep — and freeze to a static gradient under prefers-reduced-motion. Unique gradient id per instance; showcased on /playground. - The launcher moves from the bottom-right over-the-map corner into the TOP chips toolbar, LEFT of the "All" chip: FlowChips gains a `leading` snippet (guarded so it still shows on zero-flow maps) and ComposedMapView passes the compact `<Button variant="ghost" size="icon"><MagicStar/></Button>` there. - Retired the just-added filled `magic` Button variant (superseded by MagicStar) and removed the onboard-header launcher + the now-unused showChatLauncher / bindable chatOpen plumbing — the launcher is common to both hosts again, mounted identically. Live-verified on /onboard: the ✨ sits left of "All" in the chips row with a visibly cycling gradient and opens the chat. vitest 211 pass, svelte-check 0. Refs: RFC-035 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "What's inside" zone-detail panel popped up and re-rendered on every pointer move across a zone (handleCanvasPointerMove set detailZoneId immediately), and sat top-right where it now collides with the chips toolbar + the ✨ launcher. - Dwell: detailZoneId is now set behind a 350ms timer (ZONE_DWELL_MS) that only fires if the cursor is still resting on the same zone — a quick pass no longer flashes the card. The hover ring (hoveredZoneId) stays immediate. The timer is cleared on zone change, on closeZoneDetail, on descend/level change, and on teardown. Sticky behavior kept: once shown it stays until a different zone is dwelt on or × dismisses it. - Moved ZoneDetailCard from top-right (top:52 right:16) to bottom-left (bottom:16 left:16), clear of the chips row and the bottom-center tour card; the "What's inside" list still scrolls. Live-verified: fast pass shows nothing; resting ~350ms on a zone shows the card in the bottom-left corner. vitest composed-map 101 pass, svelte-check 0. Refs: RFC-035 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
An adversarial 3-dimension web review (verified each with a concrete trigger) found 9 real bugs the green suite + a manual click-through missed. All fixed + regression-tested. HIGH: - Cross-turn frame race: cancel+immediate-resend on the one persistent WS could land a cancelled turn's token/usage/done on the next answer. Fix: per-turn `turnId` threaded client↔daemon on user_message + every server frame; the client drops frames whose turnId != current; cancel advances the turn. - Close-chat-mid-stream left `pending` stuck + an orphaned "thinking…" bubble (newChat became a no-op). Fix: stopAgentProbe now calls fallBackToTier0. - Escape closed the chat AND navigated the map (one press, two actions). Fix: FloatingWindow.handleKeydown stopPropagation on Escape. - FloatingWindow docked width seeded/left unclamped → panel off-screen on a narrow first-visit or live-shrink. Fix: clamp dockedWidth on resize + init. - handleError appended the error then fell to tier0 in the same tick → the error text never rendered (blank CTA). Fix: keep the transcript visible whenever messages exist; CTA only for the empty case. MEDIUM: - Error frame had no fatal/non-fatal discriminant → any per-turn error forced full tier0 fallback. Fix: `fatal:boolean` on the error frame; tier0 only when fatal. - maxWidth() floored at minWidth below a 352px viewport → window spilled off-screen. Fix: cap geometry against raw viewport dimensions. - hoveredZoneId not reset on descend/ascend/climbTo → stale hover-ring flash on re-entry (deterministic zone ids). Fix: clear it alongside detailZoneId. - checkDaemon probe writes unguarded → a fast close→reopen let an older probe overwrite a newer result. Fix: monotonic probe generation guard. Also fixed a type-cast bug in the error-frame parse surfaced by the fatal change (runtime type check, no unsafe cast). PROTOCOL_VERSION bumped; turnId/fatal are additive (missing → tolerated, backward-compatible). smoke exit 0, vitest 60 files / 782 tests, svelte-check 0 errors. Refs: RFC-035 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…amera chat) (#169) ## Summary **The live onboarding agent (PRD-038 Pillar C).** Talk to your project in the web chat and a **real local Claude Code session** answers — grounded in the actual repo — while the **map moves as it explains**. Two-tier + graceful: Tier 0 answers offline from `map.json`; Tier 1 upgrades to the live agent when the daemon is running. This PR consolidates the Pillar C **shape + build + evidence** (supersedes the shape-only #168). ## Proven end-to-end (EVID-096) Spawned the daemon, connected a WS client, asked *"what is this project and what is it for?"* — the local CC answered verbatim: *"@forgeplan/web is a tiny zero-install npm CLI that scaffolds a pre-built SvelteKit app into `.forgeplan-web/`, serves a read-only force-directed map of Forgeplan artifacts… `npx @forgeplan/web start`…"* — then **called `show_on_map` → `{zone: z.surfaces}`** and narrated the zone flow. Real model turn, grounded, camera-driven. ## What's in it - **RFC-034 + ADR-010** (active) — the daemon/protocol/camera/chat architecture + the packaging decision (separate optional package + spawn-only subcommand). - **Phase 1** — `camera-bus` seam (the one primitive a chat uses to move the RFC-033 tour camera) + Tier-0 chat (`map-chat`: client-grounded, model-free, offline). - **`agent/`** — NEW separate package `@forgeplan/web-agent` (ADR-010: own deps `@anthropic-ai/claude-agent-sdk` + `ws` + `zod`, never in core): a 127.0.0.1 WebSocket daemon booting a persistent Agent SDK `query()` session in a **read-only** profile (Read/Glob/Grep + `show_on_map`; deny Write/Edit/Bash), with an in-process `createSdkMcpServer` `show_on_map` tool that relays camera frames. - **`bin/commands/onboard-agent.mjs`** — spawn-only subcommand (rule 23: `spawn`s the package, never imports it). - **Tier-1 web wiring** — `agent-client.ts` (read-only WS client) + `chat-store` Tier-1 (stream → assistant bubble; `show_on_map` → camera-bus; degrades to Tier 0 when the daemon is down). ## Invariants - **Rule 22**: the live path is browser↔daemon over `ws://127.0.0.1`; `/api/*` is never involved. - **Rule 23 / ADR-010**: core `bin/` stays `node:*`+citty+siblings (spawn-only); the SDK lives only in the `agent/` package; root `package.json` untouched. - **Read-only**: the agent cannot mutate the workspace. ## Test plan - `npx vitest run src/widgets/map-chat src/widgets/composed-map` → **153/153**. - `npx svelte-check` → **0 errors**. - `node agent/scripts/smoke.mjs` → exit 0 (protocol + read-only profile + bind + `/health` + `{ready}`). - Rule-23 allow-list grep over `bin/` → OK. - **Live end-to-end turn** (above) — daemon + local CC + `show_on_map` (EVID-096, CL3). ## To try it `npx @forgeplan/web onboard-agent` in your project → the web chat detects it (`● live`) → ask away. Refs: PRD-038, RFC-034, ADR-010, EVID-096, RFC-033 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Throwaway /iso-spike route de-risking a true-3D IDEF0 exploded-pyramid map view. Threlte v8 + three; R1 non-centered nesting (child plane explodes under the parent zone-box, not centered), dashed MeshLine frustum connectors (attenuate=false), ICOM boundary arrows via real classifyIcom (ADR-007). Spike-scoped (// TODO(spike)); pre-RFC. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…stages Checkpoint of the workflow build: IsoScene monolith split into ui/ (12 components), lib/ (4), model/ (1). Matte material, dynamic re-layering + depthWindow accordion, node & layer hover-cards. 4 known svelte-check implicit-any errors to fix next. Spike-scoped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…epthWindow Thin translucent paper sheets (PLATE_THICKNESS/opacity down), hover highlights individual element not whole sheet, leader-line cards gated behind showInfoCards=false (minimap), windowPlanes root-anchored (first N levels expand downward), dashed-connector depthTest/renderOrder visibility fix, A11yProxy 3-kind union guard. svelte-check 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…reverse collapse Clicking a zone explodes its sub-layer chain downward (R1 nesting), dashed frustum connectors now render corner-to-corner (depthTest:false + renderOrder), breadcrumb + ascend, depthWindow caps depth. Fixed each_key_duplicate in IsoA11yProxy (same node id across two expanded planes). svelte-check 0, live-verified explode + connectors + 0 console. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s shows At depthWindow=2, descending into a deeper plane pushed the new level past the display window, hiding it as a sliver until you manually bumped the control to 3. Now focusZone grows depthWindow to min(3, chainLen+1) after each descend, so the layer you click into is always expanded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dim/desaturate by distance-from-deepest (drilled-into plane stays full, ancestors recede), wider PLANE_GAP, softer depth desaturation, ancestor node boxes darken with depth. Partial declutter — spatial overlap from R1 nesting remains (needs a layout/camera decision, not just dimming). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Only the drilled-into (deepest) plane renders node boxes; ancestor planes collapse to faint zone-frame outlines (context, not clutter). At rest (root) the root still shows full detail; drilling fades context to frames and details the focus. Clears the dense-node overlap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move IsoScene + ui/ + lib/ + model/ into a widgets/iso-map/ slice (internal structure preserved, relative imports intact). /iso-spike route now imports from the widget (route->widget, FSD-legal). Prep for mounting the 3D iso in the Map view's minimap corner. svelte-check 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
IsoMinimap (container-sized host reusing the shared mapPoller) + a lazy IsoMapCorner wrapper; DependencyGraph shows it in the bottom-right corner only on the Map view, keeping the 2D Minimap on the other 6 views. Main 2D ComposedMapView untouched. three/Threlte dynamic-imported (client code-split). svelte-check 0, dev live-verified (Map view: 2D map + 3D corner, 0 console errors). KNOWN SHIP-BLOCKER: dist build = 6.0M vs 3M cap (three in SSR bundle + unused draco/basis loaders from @threlte/extras). Bundle surgery next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Kill unused @threlte/extras draco/basis loaders (~1.5M) via a vite alias stub (vite/stubs/three-loaders.ts); ssr=false + browser-guarded dynamic import for /iso-spike and IsoMapCorner so three is fully OUT of the SSR server bundle (0 three markers in dist/index.js). Remaining over-cap is three+threlte itself (808K, lazy client chunk). Still 0.29M over the 3M cap — cap decision pending. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 3D Map-view corner (three.js + Threlte, ~808K lazy client chunk) pushes dist to ~3.4M. Cap raised to 3.5M per user decision; three is loaded only when the Map view opens (deferred download, no cold-start cost). TODO(iso-adr): amend PRD-030 NFR-005 via ADR before ship. npm run build now passes: images built stable + nightly, dist 3.4M. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… only surface The 3D iso view now lives entirely in widgets/iso-map, consumed by the Map-view corner (IsoMapCorner). The /iso-spike dev route was a public route that would have shipped in the app AND was the last SSR path pulling three into the server bundle. Removing it: no user-facing throwaway route, three fully client-lazy. Map corner live-verified, npm run build passes (dist 3.4M), svelte-check 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…control toggle New widgets/composed-map/model/shared-drill-bus.svelte.ts — a plain-data module singleton holding the shared focus chain (NO three/@threlte import, so the 2D/SSR path stays three-free). ComposedMapView (2D) and iso-view- state (3D) both read/write it: descend/ascend in EITHER view drives the other. 3D reflects + highlights the 2D's current focus and always shows the current depth expanded. IsoControls (1/2/3+ascend) gains a hide/show toggle. Live-verified both directions (3D zone-click -> 2D descends to Decision Trail; 2D 'All' -> 3D resets to root), 0 console errors, svelte-check 0, vite build green, three still lazy/code-split. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix the build.mjs cap comment: the amended cap is PRD-030 NFR-001 / SC-4 / rule 21 (not NFR-005 — that's the flag-lifecycle policy), and the deliberate 3->3.5 MiB bump is now recorded in ADR-011. Resolves the TODO(iso-adr) placeholder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ry, doc/RFC drift - HIGH: sync-drop race — 3D now records a pending focus-chain target when an update lands mid-animation and re-applies it on animation settle, so the 3D always converges to the 2D (RFC-036 NFR-004 / INV-E no-drift). - MED: IsoMapCorner wraps the 3D mount in <svelte:boundary> so a runtime WebGL/init failure shows an honest fallback (FR-007), not a broken corner. - docs: dropped the stale 'throwaway spike' comment, deduped the TODO(iso-promote) copies, removed the phantom TODO(iso-draco-basis), aligned shared-drill-bus public API names to the RFC-036 contract. svelte-check 0, vitest 782/782, npm run build passes (dist 3.4M both images). TODO: shared-drill-bus unit tests still owed (EVID-100 finding #2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…D-100 #2) 16 new tests: shared-drill-bus reducer idempotence + bidirectional 3D<->2D sync contract + mid-animation pending-retry convergence (the sync-drop-race fix under test). vitest 782 -> 798, svelte-check 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record + activate the Forgeplan artifact chain for the 3D isometric
layered-overview minimap shipped into the Map-view corner:
- PRD-039 requirement (child of PRD-036 composed-map)
- RFC-036 lazy iso-map widget, 2D-synced via three-free shared-drill-bus
- ADR-011 ship three.js+Threlte lazy chunk; raise dist cap 3->3.5 MiB
(amends PRD-030 NFR-001 / SC-4 / rule 21)
- EVID-099..107 dist-cap build, code review + re-review, security
rule-22 governance, render-proof, AC-3/AC-1 interaction proof,
and two guardian gates (final: PASS, both prior gaps closed).
Guardian re-gate (EVID-107) PASS: R_eff>0 on all three, both EVID-105
gaps closed and verified in source, blast radius viewer-only + reversible.
Refs: PRD-039
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rner (#170) ## Summary Replaces the 2D minimap in the **Map view's** bottom-right corner with a lazy-loaded **3D isometric layered-overview minimap** (exploded-pyramid IDEF0 stack). The other 8 graph views keep their unchanged 2D minimap; the main 2D composed-map is untouched. - **3D corner widget** (`widgets/iso-map/`, SOLID/FSD-decomposed): Threlte v8 + three, OrthographicCamera + OrbitControls, stacked isometric zone planes, node boxes, dashed frustum, depth control (1/2/3 + ascend) + show/hide toggle. - **Bidirectional 3D↔2D drill sync** via a new **three-free** `shared-drill-bus` singleton (plain-data focus chain): clicking a zone in 3D descends the 2D map and vice-versa; 3D always reflects the 2D focus. The 2D path never imports three. - **Lazy load**: three/@threlte load only on Map-view mount (dynamic import, browser-guarded, `<svelte:boundary>` fallback) — zero WebGL on the other views. - **Bundle surgery**: stubbed unused draco/basis loaders (−1.5 MB), pushed three out of SSR → dist 6.0 MB → **3.29 MiB** (< 3.5 MiB cap). - Dropped the throwaway `/iso-spike` dev route — the corner minimap is the only surface. ## Why The composed-map's flat 2D minimap couldn't convey the layered depth structure of the IDEF0 decomposition. The 3D exploded-pyramid overview shows the whole altitude stack at a glance and stays in lock-step with the 2D drill state. Driving Forgeplan chain (all **active**, guardian **PASS**): - **PRD-039** — requirement (child of PRD-036 composed-map) - **RFC-036** — lazy iso-map widget + shared-drill-bus design - **ADR-011** — ship three.js+Threlte lazy chunk; raise dist cap 3→3.5 MiB (amends PRD-030 NFR-001 / SC-4 / rule 21) - Evidence EVID-099..107 (dist-cap, code-review + re-review, rule-22 security governance, render-proof, AC-3/AC-1 interaction proof, 2 guardian gates). ## Test plan - `svelte-check` — **0 errors** (8 pre-existing a11y warnings). - `vitest` — **798/798** pass (incl. 16 new shared-drill-bus + iso-view-state sync tests: idempotence, bidirectional sync, mid-animation convergence). - `npm run build` — **PASS**, dist **3.29 MiB < 3.5 MiB** cap, both images; `three` isolated to a lazy client chunk, 0 markers in the SSR bundle. - **Live Playwright interaction proof** (EVID-106): depth 1/2/3 state change, ascend descend→climb→re-disable, show/hide toggle round-trip, and every non-Map view confirmed to keep its 2D minimap with `three` never mounted. - **rule-22 security audit** (EVID-104): 0 new server/network surface — the one new client GET consumes the already-allow-listed read-only `/api/map/layers/<zone>`. Refs: PRD-039 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Bring the .forgeplan markdown in sync with the index and clear the working-tree clutter left after the Pillar-B/C + iso arcs. - Fix markdown<->index desync (RED LINE #4): PRD-038 + RFC-035 were activated in the Lance index during the Pillar C (#169) close-out but their status never landed in the committed markdown, so a scan-import would silently revert them to draft. Restore status: active + the session's score/link updates on the Pillar-B/C evidence chain. - Commit EVID-098 (RFC-035 chat-panel-v2 verification) — it was never captured by any prior commit. - Add the three reference docs (CLAUDE-PLUGINS, MAP-PACK v0.2.0 findings, proactive hints rules). - gitignore transient forgeplan/local paths (anomalies-journal.jsonl, map/.work/, .local/). - Remove stray scratch (pnpm-lock.yaml — project is npm; plus dev-run yml/md droppings). No source/behaviour change; markdown is now the durable source of truth (ADR-003) that matches the derived index. Refs: PRD-038 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ee (#171) ## Summary Pre-release housekeeping on `develop` — no source or runtime behaviour change. - **Fix markdown↔index desync (RED LINE #4).** `PRD-038` + `RFC-035` were activated in the Lance index during the Pillar C (#169) close-out, but their `status: active` never landed in the committed markdown. A `forgeplan scan-import` on develop would have silently reverted them to `draft` and "unactivated" the Pillar C chain. Restored `status: active` (+ the session's score/link updates on the Pillar-B/C evidence chain). Verified: after `scan-import`, both stay `active`. - **Commit `EVID-098`** (RFC-035 chat-panel-v2 verification) — it existed only in the working tree, captured by no prior commit. - **Add three reference docs**: `docs/CLAUDE-PLUGINS.md`, `docs/MAP-PACK-v0.2.0-FINDINGS.md`, `docs/hints-rules.md`. - **gitignore** transient forgeplan/local paths: `.forgeplan/anomalies-journal.jsonl`, `.forgeplan/map/.work/`, `.local/`. - **Remove stray scratch**: `pnpm-lock.yaml` (project is npm — `package-lock.json` is the lockfile) + dev-run `*.yml` / `*.md` droppings. ## Why Bring `develop` to a clean, durable state before cutting the `v0.3.0` release branch. The markdown is the source of truth (ADR-003); it must match the derived index so a fresh clone + `scan-import` reproduces the activated Pillar C chain. ## Test plan - `forgeplan scan-import` → `PRD-038` + `RFC-035` remain **active** (desync cured). - No `template/` source touched → existing CI (svelte-check + vitest + build matrix) unaffected; this is a docs/metadata-only change. - `git diff --cached` verified: no scratch, no gitignored paths, no screenshots staged. Refs: PRD-038 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Release v0.3.0 (MINOR) — the IDEF0 composed-map program: composed-map T4 render + recursive drill-down, onboarding tour (Pillar B), live local-agent guide (Pillar C), and the 3D isometric Map-corner minimap. 152 commits since v0.2.4; no breaking changes.
Collaborator
|
Great!!!! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release v0.3.0 (MINOR) — cuts the entire IDEF0 composed-map program from
developtomain. 152 commits sincev0.2.4, no breaking changes.Headline features landed since v0.2.4:
with render-proof against the
forgeplan.map/v1contract (PRD-036 / SPEC-006 / RFC-030).map-pack-emitted per-zone layers with client-derived fallback (PRD-037 / RFC-031).
/onboardroute + deterministic zone-walkcamera tour (feat(idef0): onboarding tour (Pillar B) — /onboard + zone-walk camera #167).
(Tier-0 map-grounded, Tier-1 live), floatable/dockable chat panel v2 (feat(idef0): Pillar C — live onboarding agent (daemon + Agent SDK + camera chat) #169,
PRD-038 / RFC-034 / RFC-035 / ADR-010).
3D↔2D drill sync, dist cap raised 3→3.5 MiB (feat(idef0): 3D isometric layered-overview minimap in the Map-view corner #170, PRD-039 / RFC-036 / ADR-011).
Version bump
package.json+template/package.json:0.2.4→0.3.0.Release checklist
main(merge commit)v0.3.0onmain+ pushrelease.yml→ npm with provenance)release/v0.3.0→developTest plan
Full CI matrix on this PR must pass. No new code beyond the version bump; all
feature work was already CI-verified on
develop(each of #167/#169/#170/#171merged green).
🤖 Generated with Claude Code