Skip to content

fix(brief): render visual point-of-view paths inside the project worktree - #47

Merged
TastyTom13 merged 4 commits into
mainfrom
fm/fm-brief-visual-pov-paths
Sep 30, 2026
Merged

TastyTom13 merged 4 commits into
mainfrom
fm/fm-brief-visual-pov-paths

Conversation

@TastyTom13

@TastyTom13 TastyTom13 commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

Intent

Said 2026-09-30 about design work in general: "All of that should already be understood by any agent doing design work. Not just for this design, but any future design. So please make sure you are aware of that going forward."

Context: the merged visual-work contract makes bin/fm-brief.sh --visual --surface bind a point-of-view document. Its table points decks at $FM_HOME/docs/design/point-of-view.md, scout at $FM_HOME/docs/design-system/point-of-view.md and website at $FM_HOME/sites/tomasmeulenberg/design-concepts/POINT-OF-VIEW.md. None of those exist in the firstmate home: the point-of-view report places them inside the project checkouts: projects/doc-creator/docs/design/point-of-view.md, projects/scout/docs/design-system/point-of-view.md, and the Forge site design-concepts folder. The first scout brief built with the flag rendered a dead path.

What Changed

  • bin/fm-brief.sh --visual --surface now renders the decks, scout and website point-of-view documents as paths relative to the worker's own worktree (for example docs/design-system/point-of-view.md, followed by "in your worktree"). Before, it pointed at $FM_HOME/... paths that do not exist. The email document still lives under $FM_HOME/data/standards/.
  • The scaffold now checks $FM_HOME/projects/<repo-name>/<path> only to decide whether to warn. If the document is missing, it prints a warning that names the path it checked and does not refuse. For the project surfaces the brief says the check was advisory. The worker reads the document in its worktree if it exists, creates it from the ratified point-of-view report only if it is absent there, and never overwrites an existing one. For email, the brief tells the worker to create the missing document at that path.
  • .agents/skills/visual-work/SKILL.md updates the surface table and text to match. tests/fm-brief.test.sh now builds fixture projects, and asserts the worktree-relative wording, no primary-checkout path in the brief, and no warning when the document exists. It also asserts the warning and the advisory or create wording when the document is missing, for all four surfaces.

Risk Assessment

✅ Low: The change is small and confined to brief text and one advisory warning. It follows the recorded decisions: worktree-relative paths, the repo name checked under $FM_HOME/projects, and advisory wording. The tests run the real scaffold and assert the emitted brief and warning.

Testing

I ran the real brief script against a throwaway firstmate home. Scout, decks and website briefs name the document by a worktree-relative path ("in your worktree"), and never leak a primary-checkout path. A missing document prints a warning naming the exact primary-checkout path checked, and the brief is worded as advisory: read it if present, create only if absent, never overwrite. Email stays an absolute path under the firstmate home. Non-visual briefs are unchanged. Bad or missing surface is refused. The existing tests/fm-brief.test.sh passes. I did not run the full repo suite. The throwaway home was removed, and the worktree is clean.

  • Live validation: ✅ go - 7 of 7 scenarios driven live against the product
Scenario Result Live Evidence
Scout brief with a bare repo name and existing document renders a worktree-relative path and no warning ✅ pass live live-fm-brief.txt S1: brief says docs/design-system/point-of-view.md in your worktree; no warning; no $H/projects path in the brief
Decks brief with missing document warns with the primary-checkout path and words the brief as advisory ✅ pass live live-fm-brief.txt S2
Website brief for a project folder that does not exist still scaffolds, with warning ✅ pass live live-fm-brief.txt S3
Email surface keeps the absolute firstmate-home path ✅ pass live live-fm-brief.txt S4
Non-visual brief has no point-of-view text ✅ pass live live-fm-brief.txt S5: count 0
Invalid or missing --surface is refused ✅ pass live live-fm-brief.txt S6: rc=1 both
Existing fm-brief test file passes ✅ pass live fm-brief-test.txt, rc=0
Evidence: Live fm-brief.sh transcript (6 scenarios)

Source: Live fm-brief.sh transcript (6 scenarios)

\### S1 scout, doc exists in primary (bare name 'scout'), run from unrelated cwd
(eval):7: no such file or directory: bin/../2
scaffolded: /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/s1/brief.md (scout; replace {TASK} and {FIRSTMATE_SPEC})
rc=0
84:# Visual work contract
85-Before any design decision, read and follow `docs/design-system/point-of-view.md` in your worktree, the point of view and quality bar for the `scout` surface, and read `~/.no-mistakes/worktrees/a6ca20682364/01M3QP5RVATWZ0YPHX4RTCH82H/.agents/skills/visual-work/SKILL.md`.
0
\### S2 decks, doc missing (doc-creator)
warning: the decks point-of-view document does not exist yet (checked /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/projects/doc-creator/docs/design/point-of-view.md); the brief tells the worker to create it from the ratified point-of-view report before designing
scaffolded: /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/s2/brief.md (ship, mode=no-mistakes; replace {TASK} and {FIRSTMATE_SPEC})
rc=0
# Visual work contract
Before any design decision, read and follow `docs/design/point-of-view.md` in your worktree, the point of view and quality bar for the `decks` surface, and read `~/.no-mistakes/worktrees/a6ca20682364/01M3QP5RVATWZ0YPHX4RTCH82H/.agents/skills/visual-work/SKILL.md`.
At scaffold time this document was not found in the primary checkout. In your worktree, read `docs/design/point-of-view.md` if it exists, and only if it is absent there create it from the ratified point-of-view report (`/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/design-point-of-view-documents/report.md`) before designing; never overwrite an existing one.
\### S3 website, project dir missing entirely
warning: the website point-of-view document does not exist yet (checked /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/projects/forge/sites/tomasmeulenberg/design-concepts/POINT-OF-VIEW.md); the brief tells the worker to create it from the ratified point-of-view report before designing
scaffolded: /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/s3/brief.md (ship, mode=direct-PR; replace {TASK} and {FIRSTMATE_SPEC})
rc=0
# Visual work contract
Before any design decision, read and follow `sites/tomasmeulenberg/design-concepts/POINT-OF-VIEW.md` in your worktree, the point of view and quality bar for the `website` surface, and read `~/.no-mistakes/worktrees/a6ca20682364/01M3QP5RVATWZ0YPHX4RTCH82H/.agents/skills/visual-work/SKILL.md`.
At scaffold time this document was not found in the primary checkout. In your worktree, read `sites/tomasmeulenberg/design-concepts/POINT-OF-VIEW.md` if it exists, and only if it is absent there create it from the ratified point-of-view report (`/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/design-point-of-view-documents/report.md`) before designing; never overwrite an existing one.
\### S4 email stays absolute
warning: the email point-of-view document does not exist yet (checked /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/standards/mindshake-outbound-point-of-view.md); the brief tells the worker to create it from the ratified point-of-view report before designing
scaffolded: /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/s4/brief.md (ship, mode=local-only; replace {TASK} and {FIRSTMATE_SPEC})
rc=0
# Visual work contract
Before any design decision, read and follow `/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/standards/mindshake-outbound-point-of-view.md`, the point of view and quality bar for the `email` surface, and read `~/.no-mistakes/worktrees/a6ca20682364/01M3QP5RVATWZ0YPHX4RTCH82H/.agents/skills/visual-work/SKILL.md`.
This document does not exist yet. Before designing, create it at that path from the ratified point-of-view report (`/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/design-point-of-view-documents/report.md`), then follow it.
\### S5 non-visual brief has no POV
scaffolded: /var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/tmp.IoPsxBfy1W/home/data/s5/brief.md (ship, mode=local-only; replace {TASK} and {FIRSTMATE_SPEC})
0
\### S6 bad surface / missing --surface
error: --surface must be one of decks, scout, website, email (got 'nope')
rc=1
error: --visual requires --surface <decks|scout|website|email>
rc=1
Evidence: fm-brief.test.sh output

Source: fm-brief.test.sh output

ok - fm-brief: scaffolds leave the worker role scope to the launch boundary and keep the secondmate contract
ok - fm-brief.sh: bash -n succeeds
/private/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/fm-brief.zudvuA/heredoc-in-substitution.sh:2
ok - fm-brief.sh: no heredoc is nested inside a command substitution (Bash 3.2 parse-safe)
ok - fm-brief.sh: --help renders the complete header
ok - fm-brief.sh: no-mistakes/direct-PR/local-only briefs generate cleanly
ok - fm-brief.sh: ship --mode is required and closed-set validated
ok - fm-brief.sh: the explicit ship mode wins over the registered posture
ok - fm-brief.sh: --yolo and scout/secondmate --mode are refused, never silently dropped
ok - fm-brief.sh: the base branch line renders only for an explicit base
ok - fm-brief.sh: faster paths use configured authority without stacked review
ok - fm-brief.sh: no-mistakes DOD keeps its apostrophe prose and bans --yes outright
ok - fm-brief.sh: no-mistakes ask-user findings use one event plus a verbatim snapshot
ok - fm-brief.sh: ship project-memory wording carries the AGENTS.md authoring bar
ok - fm-brief.sh: --herdr-lab emits the complete hard safety contract
ok - fm-brief.sh: --herdr-lab uses its quoted Firstmate-owned helper path
ok - fm-brief.sh: ship and scout scaffolds make omitted Herdr intent fail-visible
ok - fm-brief.sh: the documented {TASK} and {FIRSTMATE_SPEC} fills cannot corrupt the Herdr safety gate
ok - fm-brief.sh: Herdr lab contract covers scouts and rejects secondmate misuse
ok - fm-brief.sh: --no-projects scaffolds a project-less charter and guards misuse
ok - fm-brief.sh: marked requests avoid generic acknowledgements and preserve material reporting
ok - fm-brief.sh: relative directory inputs ignore CDPATH, render stable absolute charter paths, or fail loudly
ok - fm-brief.sh: custom pause verb renders in every scaffold
ok - fm-brief.sh: ship and scout scaffolds teach validation-round pauses
ok - fm-brief.sh: investigation and visual-review completions load the shared decision policy
ok - fm-brief: scout and secondmate code paths still scaffold well-formed briefs
ok - fm-brief.sh: scout Lavish hosting follows the bootstrap lavish-axi floor and names a durable board path
ok - fm-brief.sh: ship and scout carry the CONTEXT pointer, Toolkit, and Reporting rules
ok - fm-brief.sh: --env-file is opt-in, absolute, self-explaining, and refused on charters
ok - fm-brief.sh: the merge wait is declared exactly where a PR is raised
ok - fm-brief.sh: the Built-by PR-body line reads this task's own recorded harness/model/effort
ok - fm-brief.sh: fable-prompting Task subsections, charter Intent slot, Working discipline lines, cd caution, and ship verification step render for every scaffold
ok - fm-brief.sh: acceptance-numbering and red-then-green rules render only for PR-raising ship briefs
ok - fm-brief.sh: the screenshot pre-flight renders only for --ui tasks
ok - fm-brief.sh: --help documents the --ui screenshot pre-flight
ok - fm-brief.sh: ship and scout briefs name the unwanted and wanted turn ends plus the time sentence
ok - fm-brief.sh: --pasted-file marks the captain's paste under Captain's intent and is otherwise byte-identical
ok - fm-brief.sh: --design adds only the front-end design block
warning: the decks point-of-view document does not exist yet (checked /private/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/fm-brief.zudvuA/visual-kind-scout/projects/some-proj/docs/design/point-of-view.md); the brief tells the worker to create it from the ratified point-of-view report before designing
warning: the decks point-of-view document does not exist yet (checked /private/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/fm-brief.zudvuA/visual-kind-direct-PR/projects/some-proj/docs/design/point-of-view.md); the brief tells the worker to create it from the ratified point-of-view report before designing
warning: the decks point-of-view document does not exist yet (checked /private/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/fm-brief.zudvuA/visual-kind-local-only/projects/some-proj/docs/design/point-of-view.md); the brief tells the worker to create it from the ratified point-of-view report before designing
warning: the decks point-of-view document does not exist yet (checked /private/var/folders/08/gk0k1cz96snd794rnghc_98r0000gn/T/fm-brief.zudvuA/visual-flagged/projects/some-proj/docs/design/point-of-view.md); the brief tells the worker to create it from the ratified point-of-view report before designing
ok - fm-brief.sh: --visual is surface-bound, shared by ship/scout, and byte-neutral when absent
ok - fm-brief.sh: --help documents the visual-work flag and surface selector
ok - fm-brief.sh: --help documents --pasted-file and --design

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed (2) ✅
  • 🚨 bin/fm-brief.sh:554 - The fix treats the second argument as a directory path, but that argument is a repo NAME. The usage line says &lt;repo-name&gt;. Every other test passes a bare name (firstmate, alpha, sample, some-proj). The script only uses it as text in the brief (worktree of $REPO). The firstmate-coding-guidelines skill calls it a caller-supplied string. Real projects live at $FM_HOME/projects/&lt;name&gt; (for example ~/firstmate/projects/forge). Trace: fm-brief.sh t scout --scout --visual --surface scout sets POS[1]=scout, so line 554 builds scout/docs/design-system/point-of-view.md. That path is relative to the caller's working directory, so it is still a dead path and no warning tells the worker why. This is the exact failure in the intent (the first scout brief built with the flag rendered a dead path). It is only fixed when the caller passes an absolute path, which nothing documents. Same defect at: bin/fm-brief.sh:554 (path build), bin/fm-brief.sh:17-18 and 90-97 (help still says repo-name while the new text says target project directory), .agents/skills/visual-work/SKILL.md:20-29 (&lt;project&gt; described as a directory passed as the second argument), tests/fm-brief.test.sh:1517-1526 (passes an absolute $proj, which hides the bug), tests/fm-brief.test.sh:1561-1570 (same in the missing-document loop). The intent points at projects/doc-creator/..., projects/scout/... and projects/forge/sites/tomasmeulenberg/design-concepts/.... The smallest fix is to resolve the name to $FM_HOME/projects/&lt;name&gt; (keep an absolute path as it is). Then run the tests with a bare repo name and a real $FM_HOME/projects/&lt;name&gt; tree. The report also puts the website document in projects/forge, so the surface-to-project mapping should be checked too.
  • ⚠️ bin/fm-brief.sh:557 - Once the path resolves into $FM_HOME/projects/&lt;name&gt;, it is the project's PRIMARY checkout. The worker runs in a disposable worktree. For a missing document, the brief says create it at that path. That writes into the primary checkout, outside the worktree that gets committed, pushed and torn down. The file would never reach the PR, and it would dirty the primary checkout. For an existing document, the primary checkout may be behind the worker's base branch. The right rule is a product decision: point the worker at the same relative path inside its own worktree, or keep the absolute primary-checkout path.

🔧 Fix applied.
3 issues (1 error, 2 warnings) still open:

  • 🚨 bin/fm-brief.sh:554 - The fix treats the second argument as a directory path, but that argument is a repo NAME. The usage line says &lt;repo-name&gt;. Every other test passes a bare name (firstmate, alpha, sample, some-proj). The script only uses it as text in the brief (worktree of $REPO). The firstmate-coding-guidelines skill calls it a caller-supplied string. Real projects live at $FM_HOME/projects/&lt;name&gt; (for example ~/firstmate/projects/forge). Trace: fm-brief.sh t scout --scout --visual --surface scout sets POS[1]=scout, so line 554 builds scout/docs/design-system/point-of-view.md. That path is relative to the caller's working directory, so it is still a dead path and no warning tells the worker why. This is the exact failure in the intent (the first scout brief built with the flag rendered a dead path). It is only fixed when the caller passes an absolute path, which nothing documents. Same defect at: bin/fm-brief.sh:554 (path build), bin/fm-brief.sh:17-18 and 90-97 (help still says repo-name while the new text says target project directory), .agents/skills/visual-work/SKILL.md:20-29 (&lt;project&gt; described as a directory passed as the second argument), tests/fm-brief.test.sh:1517-1526 (passes an absolute $proj, which hides the bug), tests/fm-brief.test.sh:1561-1570 (same in the missing-document loop). The intent points at projects/doc-creator/..., projects/scout/... and projects/forge/sites/tomasmeulenberg/design-concepts/.... The smallest fix is to resolve the name to $FM_HOME/projects/&lt;name&gt; (keep an absolute path as it is). Then run the tests with a bare repo name and a real $FM_HOME/projects/&lt;name&gt; tree. The report also puts the website document in projects/forge, so the surface-to-project mapping should be checked too.
  • ⚠️ bin/fm-brief.sh:557 - Once the path resolves into $FM_HOME/projects/&lt;name&gt;, it is the project's PRIMARY checkout. The worker runs in a disposable worktree. For a missing document, the brief says create it at that path. That writes into the primary checkout, outside the worktree that gets committed, pushed and torn down. The file would never reach the PR, and it would dirty the primary checkout. For an existing document, the primary checkout may be behind the worker's base branch. The right rule is a product decision: point the worker at the same relative path inside its own worktree, or keep the absolute primary-checkout path.
  • ⚠️ bin/fm-brief.sh:571 - The brief states as fact that the document 'does not exist yet' and orders the worker to 'create it', but the scaffold only checked the project's PRIMARY checkout at $FM_HOME/projects/<repo-name>. The worker reads from its own worktree, which may be on a different --base branch or newer than the primary checkout. Trace: primary checkout is stale or on another branch and lacks docs/design/point-of-view.md, while the worker's base branch already has it. The brief still says 'create it at that path in your worktree', so the worker can overwrite the ratified document. The fix from the prior round left the brief text unconditional even though the check runs in a different tree. Smallest fix: word the note as conditional, for example 'If it is not in your worktree, create it ...'. Also for scout briefs: the scout worktree is scratch with no commit or push, so 'a created file lands in its commit' (skills/visual-work/SKILL.md, bin/fm-brief.sh header) is false for --scout, and a document created there is discarded. Whether a scout should create it at all is a product decision.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Scout brief with bare repo name 'scout' and existing doc: no warning, path rendered relative in your worktree ✅ pass live cli-transcript.txt section A
Decks brief on doc-creator with doc missing: warning names the primary-checkout path; brief says read if present, create only if absent, never overwrite ✅ pass live cli-transcript.txt section B
Website brief on forge with doc missing: same advisory wording with sites/tomasmeulenberg/design-concepts/POINT-OF-VIEW.md ✅ pass live cli-transcript.txt section C
Email brief keeps its absolute path under the firstmate home ✅ pass live cli-transcript.txt section D
Adversarial: no absolute primary-checkout path leaks into any brief; non-visual brief has no visual section; --surface without --visual is refused ✅ pass live cli-transcript.txt sections E, F, G
Existing fm-brief test file passes end to end ✅ pass live fm-brief-test-tail.txt
  • Ran bin/fm-brief.sh for real in a throwaway FM_HOME with bare repo names (scout, doc-creator, forge)
  • Scout with the doc present: no warning, brief names docs/design-system/point-of-view.md in your worktree
  • Decks and website with the doc missing: warning names the primary-checkout path checked, brief uses the advisory wording
  • Email: absolute path under FM_HOME, still works
  • Checked no primary-checkout path leaks into any brief
  • Checked a non-visual brief is unchanged, and --surface without --visual is refused
  • bash tests/fm-brief.test.sh (the whole file for this script only)

✅ No issues found.

  • Live validation: ✅ go - 7 of 7 scenarios driven live against the product
Scenario Result Live Evidence
Scout brief with a bare repo name and existing document renders a worktree-relative path and no warning ✅ pass live live-fm-brief.txt S1: brief says docs/design-system/point-of-view.md in your worktree; no warning; no $H/projects path in the brief
Decks brief with missing document warns with the primary-checkout path and words the brief as advisory ✅ pass live live-fm-brief.txt S2
Website brief for a project folder that does not exist still scaffolds, with warning ✅ pass live live-fm-brief.txt S3
Email surface keeps the absolute firstmate-home path ✅ pass live live-fm-brief.txt S4
Non-visual brief has no point-of-view text ✅ pass live live-fm-brief.txt S5: count 0
Invalid or missing --surface is refused ✅ pass live live-fm-brief.txt S6: rc=1 both
Existing fm-brief test file passes ✅ pass live fm-brief-test.txt, rc=0
  • FM_HOME=&lt;tmp&gt; bin/fm-brief.sh s1 scout --scout --visual --surface scout with the document present in the primary checkout
  • fm-brief.sh s2 doc-creator --mode no-mistakes --visual --surface decks with the document missing
  • fm-brief.sh s3 forge --mode direct-PR --visual --surface website with the project folder absent
  • fm-brief.sh s4 forge --mode local-only --visual --surface email
  • fm-brief.sh s5 forge --mode local-only (no visual flag)
  • fm-brief.sh with --surface nope and with --visual but no --surface
  • bash tests/fm-brief.test.sh (whole brief test file, exit 0)
✅ **Document** - passed

✅ No issues found.

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

✅ No issues found.

Built by: claude/sonnet at medium

@TastyTom13
TastyTom13 force-pushed the fm/fm-brief-visual-pov-paths branch from 5d86dfe to 04ad0fc Compare September 30, 2026 08:28
…ons.test.sh, the "budget exhaustion (hang)" case. It has nothing to do with this PR's brief changes. The test gave the poll a 1 second budget on the real clock. When the wall clock ticked over a second at the wrong moment, the poll gave up before it called the forge, so the test failed at random. I could make it fail locally on the second run. Fix: the test now freezes the fake clock in both modes (hang and exhaust), as the exhaust mode already did (tests/fm-contributions.test.sh, in test_budget_exhaustion_keeps_prior_record). Did it work: yes. I ran the whole file 6 times after the fix and all 6 passed. Before the fix, it failed on the 2nd local run. What is left: the change is uncommitted and not pushed. The outer executor must push it and let CI re-run shard 6
@TastyTom13
TastyTom13 merged commit 02bff2d into main Sep 30, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant