From 2190e6cbb7ec26ce4797e06012883f3fae1d443c Mon Sep 17 00:00:00 2001 From: baokhang83 Date: Sat, 15 Aug 2026 11:14:54 +0200 Subject: [PATCH 1/3] fix(diagram): measure title and label clearance Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 2 ++ claude-skills/diagram-design/SKILL.md | 21 ++++++++++++------- .../references/type-architecture.md | 3 ++- .../skills/diagram-design/SKILL.md | 21 ++++++++++++------- .../references/type-architecture.md | 3 ++- tests/plugin.bats | 8 ++++++- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd5b738..6e42602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ All notable changes to FluencyLoop are documented here. level such as `jacoco-coverage-gates: familiar` is reused rather than asked again. - Embedded-diagram guidance now requires a visible SVG title and calculated, padded zone bounds; the reader preflight rejects a missing title or a node that touches a dashed boundary. +- Embedded-diagram guidance now measures the title-to-diagram gap in the reader and every label + line inside a node, rejecting cramped title spacing and overflowing detail text. ## 0.3.16 diff --git a/claude-skills/diagram-design/SKILL.md b/claude-skills/diagram-design/SKILL.md index b1b24df..958b759 100644 --- a/claude-skills/diagram-design/SKILL.md +++ b/claude-skills/diagram-design/SKILL.md @@ -79,7 +79,9 @@ The local reader already supplies the figure frame and caption. The embedded doc the diagram: no HTML page title, eyebrow, header, footer, outer `.frame` wrapper, or body padding. It **must** include a visible, concise title as an SVG `` element near the top. An HTML `` is metadata, not a visible title. Reserve a dedicated top band of at least 40 SVG units -for it; do not let a zone, connector, or node occupy that band. Set `html, body { margin: 0; +for it, then measure the title's rendered bounding box. The first zone, connector, or node must +start at least 32 CSS pixels below the title's rendered bottom in the reader iframe. Do not rely on +the nominal band alone and do not let a zone, connector, or node occupy that gap. Set `html, body { margin: 0; padding: 0; overflow: hidden; }` and render the SVG with `display: block; width: 100%; max-width: 100%; height: auto; min-width: 0`. Never add `overflow: auto`, `overflow-x: auto`, or a positive SVG `min-width` to an embedded diagram. @@ -95,11 +97,12 @@ its visual density, choose a wider/shorter layout, or split the explanation—ne Before delivering an embedded diagram, validate the rendered SVG in the local reader at its actual iframe width. This applies to native-renderer candidates and fallback HTML alike: -- Measure every visible text element with the chosen font and size (for example, with SVG - `getBBox()` or `getComputedTextLength()` in a browser); character count is not a fit check. Its - measured bounds must remain inside its intended node with at least 12 SVG units of horizontal - and 8 units of vertical clearance. Widen or heighten the node, use deliberate two-line text, or - choose a shorter faithful label — never let a label escape or clip. +- Measure every visible text element and each `tspan` line with the chosen font and size (for + example, with SVG `getBBox()` in a browser); character count is not a fit check. Its measured + bounds must remain inside the node's inner content rectangle with at least 16 SVG units of + horizontal and 12 SVG units of vertical clearance. Also confirm at the reader's actual scale + that the glyph bounds have at least 8 CSS pixels of side clearance. Widen or heighten the node, + then use deliberate line breaks; never compress text with `textLength`, let it escape, or clip. - A node inside a dashed or solid region must leave at least 16 SVG units between its outer stroke and every region edge. Derive each region *after* placing its nodes: use at least 24 SVG units at its left, right, and bottom, and reserve at least 40 SVG units above its first node for the zone @@ -113,8 +116,10 @@ iframe width. This applies to native-renderer candidates and fallback HTML alike Deliver it only after it passes every geometry check. If a clear fallback cannot pass, simplify the visual or keep the explanation in prose or a table; never ship a failed first pass. - Inspect the completed reader rendering, not only the source. Confirm that the SVG title is - visible and that every dashed boundary has clear space around its enclosed nodes. A missing title - or even one node visually touching a boundary fails the preflight and requires another revision. + visible, has at least 32 CSS pixels of space before the first diagram element, and that every + dashed boundary has clear space around its enclosed nodes. A missing title, a cramped title gap, + overflowing label, or even one node visually touching a boundary fails the preflight and + requires another revision. ## Non-embedded diagrams diff --git a/claude-skills/diagram-design/references/type-architecture.md b/claude-skills/diagram-design/references/type-architecture.md index 6c21603..992614f 100644 --- a/claude-skills/diagram-design/references/type-architecture.md +++ b/claude-skills/diagram-design/references/type-architecture.md @@ -67,7 +67,8 @@ Group 2+ nodes that serve the same tier or trust boundary with a zone rect — d ``` Rules: -- Leave 12–16px above the first enclosed node — the eyebrow label sits in this margin. +- Derive the zone bounds from placed node rectangles: use at least 24px at the sides and bottom, + and 40px above the first enclosed node. Do not use a generic 12–16px top gap. - Zone fill: `rgba(45,49,66,0.02)` (2% ink wash). Any stronger competes with node fills. - Max 3 zones per diagram. More and it reads like a swimlane (use that type instead). - Dark mode: swap `rgba(45,49,66,…)` → `rgba(245,245,245,…)` same opacities; label mask fill = `paper` (dark). diff --git a/plugins/fluencyloop/skills/diagram-design/SKILL.md b/plugins/fluencyloop/skills/diagram-design/SKILL.md index b1b24df..958b759 100644 --- a/plugins/fluencyloop/skills/diagram-design/SKILL.md +++ b/plugins/fluencyloop/skills/diagram-design/SKILL.md @@ -79,7 +79,9 @@ The local reader already supplies the figure frame and caption. The embedded doc the diagram: no HTML page title, eyebrow, header, footer, outer `.frame` wrapper, or body padding. It **must** include a visible, concise title as an SVG `<text>` element near the top. An HTML `<title>` is metadata, not a visible title. Reserve a dedicated top band of at least 40 SVG units -for it; do not let a zone, connector, or node occupy that band. Set `html, body { margin: 0; +for it, then measure the title's rendered bounding box. The first zone, connector, or node must +start at least 32 CSS pixels below the title's rendered bottom in the reader iframe. Do not rely on +the nominal band alone and do not let a zone, connector, or node occupy that gap. Set `html, body { margin: 0; padding: 0; overflow: hidden; }` and render the SVG with `display: block; width: 100%; max-width: 100%; height: auto; min-width: 0`. Never add `overflow: auto`, `overflow-x: auto`, or a positive SVG `min-width` to an embedded diagram. @@ -95,11 +97,12 @@ its visual density, choose a wider/shorter layout, or split the explanation—ne Before delivering an embedded diagram, validate the rendered SVG in the local reader at its actual iframe width. This applies to native-renderer candidates and fallback HTML alike: -- Measure every visible text element with the chosen font and size (for example, with SVG - `getBBox()` or `getComputedTextLength()` in a browser); character count is not a fit check. Its - measured bounds must remain inside its intended node with at least 12 SVG units of horizontal - and 8 units of vertical clearance. Widen or heighten the node, use deliberate two-line text, or - choose a shorter faithful label — never let a label escape or clip. +- Measure every visible text element and each `tspan` line with the chosen font and size (for + example, with SVG `getBBox()` in a browser); character count is not a fit check. Its measured + bounds must remain inside the node's inner content rectangle with at least 16 SVG units of + horizontal and 12 SVG units of vertical clearance. Also confirm at the reader's actual scale + that the glyph bounds have at least 8 CSS pixels of side clearance. Widen or heighten the node, + then use deliberate line breaks; never compress text with `textLength`, let it escape, or clip. - A node inside a dashed or solid region must leave at least 16 SVG units between its outer stroke and every region edge. Derive each region *after* placing its nodes: use at least 24 SVG units at its left, right, and bottom, and reserve at least 40 SVG units above its first node for the zone @@ -113,8 +116,10 @@ iframe width. This applies to native-renderer candidates and fallback HTML alike Deliver it only after it passes every geometry check. If a clear fallback cannot pass, simplify the visual or keep the explanation in prose or a table; never ship a failed first pass. - Inspect the completed reader rendering, not only the source. Confirm that the SVG title is - visible and that every dashed boundary has clear space around its enclosed nodes. A missing title - or even one node visually touching a boundary fails the preflight and requires another revision. + visible, has at least 32 CSS pixels of space before the first diagram element, and that every + dashed boundary has clear space around its enclosed nodes. A missing title, a cramped title gap, + overflowing label, or even one node visually touching a boundary fails the preflight and + requires another revision. ## Non-embedded diagrams diff --git a/plugins/fluencyloop/skills/diagram-design/references/type-architecture.md b/plugins/fluencyloop/skills/diagram-design/references/type-architecture.md index 6c21603..992614f 100644 --- a/plugins/fluencyloop/skills/diagram-design/references/type-architecture.md +++ b/plugins/fluencyloop/skills/diagram-design/references/type-architecture.md @@ -67,7 +67,8 @@ Group 2+ nodes that serve the same tier or trust boundary with a zone rect — d ``` Rules: -- Leave 12–16px above the first enclosed node — the eyebrow label sits in this margin. +- Derive the zone bounds from placed node rectangles: use at least 24px at the sides and bottom, + and 40px above the first enclosed node. Do not use a generic 12–16px top gap. - Zone fill: `rgba(45,49,66,0.02)` (2% ink wash). Any stronger competes with node fills. - Max 3 zones per diagram. More and it reads like a swimlane (use that type instead). - Dark mode: swap `rgba(45,49,66,…)` → `rgba(245,245,245,…)` same opacities; label mask fill = `paper` (dark). diff --git a/tests/plugin.bats b/tests/plugin.bats index 63dca6a..bdfa90a 100644 --- a/tests/plugin.bats +++ b/tests/plugin.bats @@ -247,17 +247,22 @@ for diagram_skill_text in [ assert "visible, concise title as an SVG `<text>` element" in diagram_skill_text assert "An HTML\n`<title>` is metadata, not a visible title." in diagram_skill_text assert "dedicated top band of at least 40 SVG units" in diagram_skill_text + assert "at least 32 CSS pixels below the title's rendered bottom" in diagram_skill_text assert "Never add `overflow: auto`,\n`overflow-x: auto`, or a positive SVG `min-width`" in diagram_skill_text assert "`scrollWidth <= clientWidth` and `scrollHeight <= clientHeight`" in diagram_skill_text assert "within the reader's fixed 33rem height" in diagram_skill_text assert "### Geometry preflight — no cramped or escaping content" in diagram_skill_text assert "character count is not a fit check" in diagram_skill_text + assert "each `tspan` line" in diagram_skill_text + assert "at least 16 SVG units of\n horizontal and 12 SVG units of vertical clearance" in diagram_skill_text + assert "at least 8 CSS pixels of side clearance" in diagram_skill_text + assert "never compress text with `textLength`" in diagram_skill_text assert "at least 16 SVG units between its outer stroke" in diagram_skill_text assert "use the general fallback rather than editing generated HTML" in diagram_skill_text assert "This is a design loop, not a one-shot fallback" in diagram_skill_text assert "then measure again after every revision" in diagram_skill_text assert "never ship a failed first pass" in diagram_skill_text - assert "A missing title\n or even one node visually touching a boundary fails the preflight" in diagram_skill_text + assert "A missing title, a cramped title gap,\n overflowing label" in diagram_skill_text for full_guide_text in [ read_text(root / "claude-skills" / "diagram-design" / "references" / "full-guide.md"), read_text(dist / "skills" / "diagram-design" / "references" / "full-guide.md"), @@ -275,6 +280,7 @@ for architecture_reference in [ assert "at least 24px outside the extreme node strokes" in architecture_reference assert "top at least 40px above the first node" in architecture_reference assert "including the bottom and sides" in architecture_reference + assert "Do not use a generic 12–16px top gap." in architecture_reference claude_plan_text = read_text(root / "claude-skills" / "plan" / "SKILL.md") codex_plan_text = read_text(dist / "skills" / "plan" / "SKILL.md") assert "**Migrate imported history before planning.**" in claude_plan_text From b37f4ab2df477f985854175228b4eeac7a65bcbe Mon Sep 17 00:00:00 2001 From: baokhang83 <alex.bretet.at@gmail.com> Date: Sat, 15 Aug 2026 11:17:25 +0200 Subject: [PATCH 2/3] release: prepare 0.3.18 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- CHANGELOG.md | 9 +++++++-- plugins/fluencyloop/.codex-plugin/plugin.json | 2 +- plugins/fluencyloop/VERSION | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 626f48a..c32ec08 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "fluencyloop", "source": ".", "displayName": "FluencyLoop", - "version": "0.3.17", + "version": "0.3.18", "description": "A per-feature loop that designs, teaches, journals decisions, and assembles PR reviews.", "author": { "name": "baokhang83" diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 0d60366..ad41465 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "fluencyloop", "displayName": "FluencyLoop", - "version": "0.3.17", + "version": "0.3.18", "description": "Stay fluent in the code your AI agent writes with a per-feature design, build, teaching, and review loop.", "author": { "name": "baokhang83", diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e42602..7e84696 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to FluencyLoop are documented here. +## 0.3.18 + +### Fixed + +- Embedded-diagram guidance now measures the title-to-diagram gap in the reader and every label + line inside a node, rejecting cramped title spacing and overflowing detail text. + ## 0.3.17 ### Fixed @@ -10,8 +17,6 @@ All notable changes to FluencyLoop are documented here. level such as `jacoco-coverage-gates: familiar` is reused rather than asked again. - Embedded-diagram guidance now requires a visible SVG title and calculated, padded zone bounds; the reader preflight rejects a missing title or a node that touches a dashed boundary. -- Embedded-diagram guidance now measures the title-to-diagram gap in the reader and every label - line inside a node, rejecting cramped title spacing and overflowing detail text. ## 0.3.16 diff --git a/plugins/fluencyloop/.codex-plugin/plugin.json b/plugins/fluencyloop/.codex-plugin/plugin.json index c1531b1..5d45b25 100644 --- a/plugins/fluencyloop/.codex-plugin/plugin.json +++ b/plugins/fluencyloop/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fluencyloop", - "version": "0.3.17", + "version": "0.3.18", "description": "Stay fluent in the code your AI agent writes with a per-feature design, build, teaching, and review loop.", "author": { "name": "baokhang83", diff --git a/plugins/fluencyloop/VERSION b/plugins/fluencyloop/VERSION index 6e46293..f43e370 100644 --- a/plugins/fluencyloop/VERSION +++ b/plugins/fluencyloop/VERSION @@ -1 +1 @@ -0.3.17 \ No newline at end of file +0.3.18 \ No newline at end of file From 44265f5cff59542a66f50e112513ebb263093663 Mon Sep 17 00:00:00 2001 From: baokhang83 <alex.bretet.at@gmail.com> Date: Sat, 15 Aug 2026 11:21:09 +0200 Subject: [PATCH 3/3] fix(evidence): replace plan-era realization links Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --- CHANGELOG.md | 2 ++ claude-skills/feature/SKILL.md | 7 +++++++ claude-skills/plan/SKILL.md | 6 ++++++ plugins/fluencyloop/skills/feature/SKILL.md | 7 +++++++ plugins/fluencyloop/skills/plan/SKILL.md | 6 ++++++ tests/plugin.bats | 8 ++++++++ 6 files changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e84696..f64632c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to FluencyLoop are documented here. - Embedded-diagram guidance now measures the title-to-diagram gap in the reader and every label line inside a node, rejecting cramped title spacing and overflowing detail text. +- Planning no longer records plan documents as implementation evidence. Implementing features now + replace plan-era concept records with the concrete source paths that realize them. ## 0.3.17 diff --git a/claude-skills/feature/SKILL.md b/claude-skills/feature/SKILL.md index 57ddd26..3b842b4 100644 --- a/claude-skills/feature/SKILL.md +++ b/claude-skills/feature/SKILL.md @@ -418,6 +418,13 @@ Build the feature one **meaningful slice** at a time (a logical, commit-worthy c Re-stating a name records the refined concept; use relations to connect concepts to each other, their realizing components, or the feature that changed them. + **Replace plan-era evidence when code arrives.** Before feature handoff, inspect every + relevant existing concept. If its `realized_by` points to `plan.md`, another planning document, + or no source path, and this feature implements the concept, append a newer record with the + same name and every real project-relative source path that realizes it. Keep the old record: + the store is append-only and the reader resolves the newer evidence. Never carry a planning + document forward as implementation evidence or replace several components with one vague area. + **Tags are mandatory for every new architectural record.** Choose one to three `--tag` values *before* you call the writer; never append an untagged record with an intention to repair it later. Tags name the widely-known ideas the record is an instance of — at most three words diff --git a/claude-skills/plan/SKILL.md b/claude-skills/plan/SKILL.md index 9055620..744adc4 100644 --- a/claude-skills/plan/SKILL.md +++ b/claude-skills/plan/SKILL.md @@ -202,6 +202,12 @@ a stable, small evidence range. Do not use absolute paths, URLs, invented source symbol name in place of a path. The reader can then link the record to source without making the plan guess at a future implementation. Cite Constitution principles by their recorded `§N`. +**A plan is never implementation evidence.** Never use `plan.md`, a roadmap, a design document, +or any other planning Markdown file as `--realized-by`. If a concept has no existing source path, +explain it in the plan but wait for the feature that implements it to append or replace the concept +record with real source paths. Do not create a placeholder realization merely to make the concept +appear in the reader. + `plan.md` is planning prose, not a local-reader page. Do not add raw Markdown file links to it. When later distillation prose needs inspectable support, use `[[record-slug]]`, `[[src/path/to/file.ts]]`, `[[ed8821a]]`, or `[[§8]]` only after the target exists. diff --git a/plugins/fluencyloop/skills/feature/SKILL.md b/plugins/fluencyloop/skills/feature/SKILL.md index d78fe7d..c398394 100644 --- a/plugins/fluencyloop/skills/feature/SKILL.md +++ b/plugins/fluencyloop/skills/feature/SKILL.md @@ -474,6 +474,13 @@ visible; the journal is its durable byproduct. Re-stating a name records the refined concept; use relations to connect concepts to each other, their realizing components, or the feature that changed them. + **Replace plan-era evidence when code arrives.** Before feature handoff, inspect every + relevant existing concept. If its `realized_by` points to `plan.md`, another planning document, + or no source path, and this feature implements the concept, append a newer record with the + same name and every real project-relative source path that realizes it. Keep the old record: + the store is append-only and the reader resolves the newer evidence. Never carry a planning + document forward as implementation evidence or replace several components with one vague area. + **Tags are mandatory for every new architectural record.** Choose one to three `--tag` values *before* you call the writer; never append an untagged record with an intention to repair it later. Tags name the widely-known ideas the record is an instance of — diff --git a/plugins/fluencyloop/skills/plan/SKILL.md b/plugins/fluencyloop/skills/plan/SKILL.md index 76cdd68..1235e9b 100644 --- a/plugins/fluencyloop/skills/plan/SKILL.md +++ b/plugins/fluencyloop/skills/plan/SKILL.md @@ -238,6 +238,12 @@ a stable, small evidence range. Do not use absolute paths, URLs, invented source symbol name in place of a path. The reader can then link the record to source without making the plan guess at a future implementation. Cite Constitution principles by their recorded `§N`. +**A plan is never implementation evidence.** Never use `plan.md`, a roadmap, a design document, +or any other planning Markdown file as `--realized-by`. If a concept has no existing source path, +explain it in the plan but wait for the feature that implements it to append or replace the concept +record with real source paths. Do not create a placeholder realization merely to make the concept +appear in the reader. + `plan.md` is planning prose, not a local-reader page. Do not add raw Markdown file links to it. When later distillation prose needs inspectable support, use `[[record-slug]]`, `[[src/path/to/file.ts]]`, `[[ed8821a]]`, or `[[§8]]` only after the target exists. diff --git a/tests/plugin.bats b/tests/plugin.bats index bdfa90a..245c9ca 100644 --- a/tests/plugin.bats +++ b/tests/plugin.bats @@ -182,6 +182,10 @@ for feature_skill_text in [feature_text, codex_feature_text]: assert "[[src/path/to/file.ts]]" in feature_skill_text assert "[[ed8821a]]" in feature_skill_text assert "Make record evidence linkable." in feature_skill_text + assert "**Replace plan-era evidence when code arrives.**" in feature_skill_text + assert "If its `realized_by` points to `plan.md`, another planning document," in feature_skill_text + assert "every real project-relative source path that realizes it" in feature_skill_text + assert "the store is append-only and the reader resolves the newer evidence" in feature_skill_text assert "**only after the feature is complete**" in feature_skill_text assert "Never distill during a slice, after a decision, or as a turn-by-turn summary" in feature_skill_text assert "fluencyloop calibration show --json" in feature_skill_text @@ -346,6 +350,10 @@ for plan_skill_text in [claude_plan_text, codex_plan_text]: assert "Source of truth:" in plan_skill_text assert "SpecKit" in plan_skill_text assert "Never author cold" not in plan_skill_text + assert "**A plan is never implementation evidence.**" in plan_skill_text + assert "Never use `plan.md`, a roadmap, a design document," in plan_skill_text + assert "wait for the feature that implements it to append or replace the concept" in plan_skill_text + assert "Do not create a placeholder realization merely to make the concept" in plan_skill_text plan_template = read_text(dist / "templates" / "plan.md") assert "## Open questions" in plan_template assert "rather than silently assuming an answer" in plan_template