Migrate HomesFlow to SpecAssay + display-name normalizer (FR-HOME-04 / AC-HOME-15) - #9
Migrate HomesFlow to SpecAssay + display-name normalizer (FR-HOME-04 / AC-HOME-15)#9rdryfoos wants to merge 2 commits into
Conversation
Renames the installed traceability bundle from the retired "clewseau"
naming to SpecAssay, and re-runs the cold-agent trial under the new
naming as end-to-end evidence.
Migration:
- .specify bundle clewseau-gate -> specassay-check (extension, preset,
config, hook, install registries, agent-command skill)
- task markers **Traces**: -> **Carries**: (accepted both during
transition); brand prose in PRD/glossary -> SpecAssay / trace-manifest
- tombstoned the temporary CLEW probe IDs (US/FR/AC-CLEW-01): removed
from registry + backlog, retirement recorded neutrally; no "clew"
string remains anywhere in the tree
Cold-agent slice (generated by a zero-context agent from the PRD intent,
gate as the only witness):
- minted FR-HOME-04 + AC-HOME-15 (next-free HOME domain)
- specs/002-home-name-normalize/{spec.md,tasks.md} (Carries)
- ios/HomesFlow/Core/Home/HomeDisplayName.swift (@Covers)
- ios/HomesFlowTests/HomeDisplayNameTests.swift (test_AC_HOME_15_...)
SpecAssay Check (Gate 2): OK — 81 rows, gate.ok true, 0 GAP
(67 verified / 10 tracked-debt / 4 backlog). trace-manifest.json emitted
as evidence.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM5e4tKiqCUNANBCkTtH2r
|
Warning Review limit reached
Next review available in: 46 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe pull request replaces Clewseau traceability tooling with SpecAssay Check and changes task references from ChangesSpecAssay traceability migration
Home display-name normalization
Estimated code review effort: 3 (Moderate) | ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A minted-ahead user story carried only by an open Carries TODO (specs/backlog/tasks.md T901) — rides as backlog, not GAP or drift. Gives the trace-manifest a live anointed-backlog row. Gate 2: OK — 82 rows, gate.ok true, 0 GAP (67 verified / 10 debt / 5 backlog). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TM5e4tKiqCUNANBCkTtH2r
|
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.specify/extensions/specassay-check/config-template.yml:
- Around line 30-32: Replace the double-quoted carries_regex YAML scalar with a
single-quoted scalar in .specify/extensions/specassay-check/config-template.yml
lines 30-32 and .specify/extensions/specassay-check/specassay-check-config.yml
line 13, preserving the existing Carries/Traces regex.
In @.specify/extensions/specassay-check/scripts/check-traceability.sh:
- Line 14: Update the configuration initialization in the traceability check
script to fall back to the legacy CLEW settings when the SPECASSAY variables are
unset, including project root, config, and manifest/output settings. Preserve
explicitly provided SPECASSAY values and ensure upstream callers pass equivalent
values so CI never silently uses defaults.
In @.specify/presets/specassay/README.md:
- Line 13: Update the PROMOTION-CONTRACT.md link in the specassay README to
traverse three parent directories so it resolves to the repository-root document
instead of the .specify directory.
In @.specify/presets/specassay/templates/constitution-template.md:
- Line 26: Update the GAP row in the constitution template to replace the
undefined “frays” status wording with “is broken,” matching the established
Golden Thread vocabulary in GLOSSARY.md while preserving the rest of the
description.
In @.specify/templates/tasks-template.md:
- Line 18: Replace the retired Traces marker with Carries in all three affected
locations: update the example in .specify/templates/tasks-template.md at line
18, rename the displayed field label in .github/pull_request_template.md at line
8, and update the T088 description in specs/001-mvp/tasks.md at line 305.
In `@HomesFlow.prd.md`:
- Around line 338-340: Update the “Retired IDs” section to explicitly list
FR-CLEW-01 and every associated retired story and acceptance identifier from the
removed validation-probe requirement family. Preserve the identifiers as retired
and state that none may be reused.
In `@ios/HomesFlow/Core/Home/HomeDisplayName.swift`:
- Around line 8-15: Wire HomeDisplayName.normalized(_:) into the production home
display-name path so user-facing names consistently use the normalization
helper; locate the existing production code that renders or exposes home names
and route that value through HomeDisplayName.normalized(_:).
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 442d04ad-5722-4fc1-aa22-6d6c606023dd
📒 Files selected for processing (33)
.github/pull_request_template.md.specify/extensions.yml.specify/extensions/.registry.specify/extensions/clewseau-gate/.specify-dev/agent-commands/claude/speckit-clewseau-gate-check/SKILL.md.specify/extensions/clewseau-gate/README.md.specify/extensions/clewseau-gate/commands/speckit.clewseau-gate.check.md.specify/extensions/clewseau-gate/extension.yml.specify/extensions/specassay-check/.specify-dev/agent-commands/claude/speckit-specassay-check/SKILL.md.specify/extensions/specassay-check/README.md.specify/extensions/specassay-check/commands/speckit.specassay.check.md.specify/extensions/specassay-check/config-template.yml.specify/extensions/specassay-check/extension.yml.specify/extensions/specassay-check/scripts/check-traceability.sh.specify/extensions/specassay-check/specassay-check-config.yml.specify/presets/.registry.specify/presets/clewseau/README.md.specify/presets/clewseau/templates/constitution-template.md.specify/presets/specassay/GLOSSARY.md.specify/presets/specassay/README.md.specify/presets/specassay/preset.yml.specify/presets/specassay/templates/constitution-template.md.specify/presets/specassay/templates/spec-template.md.specify/presets/specassay/templates/tasks-template.md.specify/templates/tasks-template.mdHomesFlow.prd.mdglossary.mdios/HomesFlow/Core/Home/HomeDisplayName.swiftios/HomesFlowTests/HomeDisplayNameTests.swiftspecs/001-mvp/tasks.mdspecs/002-home-name-normalize/spec.mdspecs/002-home-name-normalize/tasks.mdspecs/backlog/tasks.mdtrace-manifest.json
💤 Files with no reviewable changes (6)
- .specify/presets/clewseau/README.md
- .specify/extensions/clewseau-gate/README.md
- .specify/extensions/clewseau-gate/commands/speckit.clewseau-gate.check.md
- .specify/extensions/clewseau-gate/.specify-dev/agent-commands/claude/speckit-clewseau-gate-check/SKILL.md
- .specify/presets/clewseau/templates/constitution-template.md
- .specify/extensions/clewseau-gate/extension.yml
| # The task-side mark. Accepts both **Carries**: (new) and **Traces**: (pre-rename) during transition. | ||
| carries_regex: "\*\*(Carries|Traces)\*\*:" | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
python - <<'PY'
from pathlib import Path
import sys
try:
import yaml
except ModuleNotFoundError:
sys.exit("PyYAML is required for this verification")
for name in (
".specify/extensions/specassay-check/config-template.yml",
".specify/extensions/specassay-check/specassay-check-config.yml",
):
yaml.safe_load(Path(name).read_text())
print(f"valid: {name}")
PYRepository: rdryfoos/HomesFlow
Length of output: 3410
Use valid YAML quoting for carries_regex.
\* is not a valid double-quoted YAML escape, so these files fail to parse; use a single-quoted scalar instead.
.specify/extensions/specassay-check/config-template.yml#L30-L32.specify/extensions/specassay-check/specassay-check-config.yml#L13
Proposed fix
-carries_regex: "\*\*(Carries|Traces)\*\*:"
+carries_regex: '\*\*(Carries|Traces)\*\*:'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # The task-side mark. Accepts both **Carries**: (new) and **Traces**: (pre-rename) during transition. | |
| carries_regex: "\*\*(Carries|Traces)\*\*:" | |
| # The task-side mark. Accepts both **Carries**: (new) and **Traces**: (pre-rename) during transition. | |
| carries_regex: '\*\*(Carries|Traces)\*\*:' |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 31-31: syntax error: found unknown escape character '*'
(syntax)
📍 Affects 2 files
.specify/extensions/specassay-check/config-template.yml#L30-L32(this comment).specify/extensions/specassay-check/specassay-check-config.yml#L13-L13
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.specify/extensions/specassay-check/config-template.yml around lines 30 -
32, Replace the double-quoted carries_regex YAML scalar with a single-quoted
scalar in .specify/extensions/specassay-check/config-template.yml lines 30-32
and .specify/extensions/specassay-check/specassay-check-config.yml line 13,
preserving the existing Carries/Traces regex.
Source: Linters/SAST tools
|
|
||
| EXT_DIR="$(cd "$(dirname "$0")/.." && pwd)" | ||
| PROJECT_ROOT="${CLEWSEAU_PROJECT_ROOT:-}" | ||
| PROJECT_ROOT="${SPECASSAY_PROJECT_ROOT:-}" |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
# Inspect active callers of retired and current settings.
rg -n -i -C 4 \
'clew|specassay_(project_root|config)|manifest_out|manifest_path|clew_path' \
. \
--glob '!trace-manifest.json' || trueRepository: rdryfoos/HomesFlow
Length of output: 926
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '--- candidate file ---\n'
wc -l .specify/extensions/specassay-check/scripts/check-traceability.sh 2>/dev/null || true
sed -n '1,130p' .specify/extensions/specassay-check/scripts/check-traceability.sh 2>/dev/null || true
printf '\n--- broader repository text references, excluding trace-manifest.json ---\n'
rg -n -i -C 3 \
'specassay_project_root|specassay_config|manifest_out|manifest_path|clew_path|CLEW|ProjectRoot|config' \
. \
--glob '!trace-manifest.json' || true
printf '\n--- environment variable writes in scripts/config/docs ---\n'
rg -n -E 'export[[:space:]]+[A-Za-z_][A-Za-z0-9_]*=|^\s*[A-Za-z_][A-Za-z0-9_]*=' \
. \
--glob '!trace-manifest.json' \
--glob '!*.lock' \
| rg -i 'clew|specassay|project_root|config|manifest_out|manifest_path' || trueRepository: rdryfoos/HomesFlow
Length of output: 247
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
echo '--- candidate file ---'
wc -l .specify/extensions/specassay-check/scripts/check-traceability.sh 2>/dev/null || true
sed -n '1,140p' .specify/extensions/specassay-check/scripts/check-traceability.sh 2>/dev/null || true
echo
echo '--- references excluding trace-manifest.json ---'
rg -n -i -C 3 \
'specassay_project_root|specassay_config|manifest_out|manifest_path|clew_path|CLEW|ProjectRoot|config' \
. \
--glob '!trace-manifest.json' || true
echo
echo '--- environment variable writes mentioning relevant names ---'
rg -n -E 'export[[:space:]]+[A-Za-z_][A-Za-z0-9_]*=|^\s*[A-Za-z_][A-Za-z0-9_]*='\
. \
--glob '!trace-manifest.json' \
--glob '!*.lock' | rg -i 'clew|specassay|project_root|config|manifest_out|manifest_path' || trueRepository: rdryfoos/HomesFlow
Length of output: 40686
Add compatibility fallbacks for renamed settings.
This script now drops Clewseau names without reading defaults. Add explicit fallbacks for CLEW_PROJECT_ROOT, CLEW_CONFIG, and output settings, or update upstream callers so CI won’t silently use a default project root/config/manifest output instead of the intended values.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.specify/extensions/specassay-check/scripts/check-traceability.sh at line
14, Update the configuration initialization in the traceability check script to
fall back to the legacy CLEW settings when the SPECASSAY variables are unset,
including project root, config, and manifest/output settings. Preserve
explicitly provided SPECASSAY values and ensure upstream callers pass equivalent
values so CI never silently uses defaults.
|
|
||
| Vocabulary (trace-manifest, statuses, Gate 2) lands in the constitution template. For projects that keep a separate glossary, also merge [`GLOSSARY.md`](./GLOSSARY.md). | ||
|
|
||
| See the repo root [`PROMOTION-CONTRACT.md`](../../PROMOTION-CONTRACT.md). |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the relative link to the repository-root contract.
This README is at .specify/presets/specassay/README.md. The current link resolves to .specify/PROMOTION-CONTRACT.md. If PROMOTION-CONTRACT.md is at the repository root as stated, use three parent-directory traversals.
Proposed fix
-See the repo root [`PROMOTION-CONTRACT.md`](../../PROMOTION-CONTRACT.md).
+See the repo root [`PROMOTION-CONTRACT.md`](../../../PROMOTION-CONTRACT.md).📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| See the repo root [`PROMOTION-CONTRACT.md`](../../PROMOTION-CONTRACT.md). | |
| See the repo root [`PROMOTION-CONTRACT.md`](../../../PROMOTION-CONTRACT.md). |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.specify/presets/specassay/README.md at line 13, Update the
PROMOTION-CONTRACT.md link in the specassay README to traverse three parent
directories so it resolves to the repository-root document instead of the
.specify directory.
| | **Loupe** | Viewer that reads a trace-manifest only — no target re-scan. Reads any emitter's manifest. | | ||
| | **verified** | Named carrier exists (AC proof and/or `@covers` / proof for US/FR/NFR). | | ||
| | **tracked-debt** | Incomplete, but declared on an open task with `Carries:`. | | ||
| | **GAP** | Silent AC gap — neither proof nor open debt; Gate refuses; the Golden Thread frays. | |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use the defined broken status term.
The vocabulary in .specify/presets/specassay/GLOSSARY.md Lines 13-15 defines the Golden Thread as broken or intact. This template uses frays, which introduces a second status term. Replace it with is broken.
Proposed fix
-| **GAP** | Silent AC gap — neither proof nor open debt; Gate refuses; the Golden Thread frays. |
+| **GAP** | Silent AC gap — neither proof nor open debt; Gate refuses; the Golden Thread is broken. |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | **GAP** | Silent AC gap — neither proof nor open debt; Gate refuses; the Golden Thread frays. | | |
| | **GAP** | Silent AC gap — neither proof nor open debt; Gate refuses; the Golden Thread is broken. | |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.specify/presets/specassay/templates/constitution-template.md at line 26,
Update the GAP row in the constitution template to replace the undefined “frays”
status wording with “is broken,” matching the established Golden Thread
vocabulary in GLOSSARY.md while preserving the rest of the description.
| ## Format: `[ID] [P?] [Story] Description` | ||
|
|
||
| - **Traces**: Required — AC/FR ID(s) this task implements (e.g. `Traces: AC-HOME-01`) | ||
| - **Carries**: Required — AC/FR ID(s) this task implements (e.g. `Traces: AC-HOME-01`) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Replace the remaining Traces references with Carries.
The migration changes the task field to **Carries**:, but three changed documents still display the retired marker.
.specify/templates/tasks-template.md#L18-L18: change the example marker to**Carries**:..github/pull_request_template.md#L8-L8: rename the displayed field label to**Carries**:.specs/001-mvp/tasks.md#L305-L305: update the T088 description to reference**Carries**:.
📍 Affects 3 files
.specify/templates/tasks-template.md#L18-L18(this comment).github/pull_request_template.md#L8-L8specs/001-mvp/tasks.md#L305-L305
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.specify/templates/tasks-template.md at line 18, Replace the retired Traces
marker with Carries in all three affected locations: update the example in
.specify/templates/tasks-template.md at line 18, rename the displayed field
label in .github/pull_request_template.md at line 8, and update the T088
description in specs/001-mvp/tasks.md at line 305.
| ### Retired IDs | ||
|
|
||
| A temporary validation-probe requirement family (a pure display-name normalizer) was withdrawn during the SpecAssay migration. Its capability is being delivered as a first-class HomesFlow requirement. Retired ID slots are not reused. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
List the exact retired IDs.
The Retired IDs section describes a withdrawn family but does not name any identifier. The removed content includes FR-CLEW-01. Preserve that ID and every associated retired story or acceptance ID explicitly so future allocations and traceability reviews can enforce non-reuse.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@HomesFlow.prd.md` around lines 338 - 340, Update the “Retired IDs” section to
explicitly list FR-CLEW-01 and every associated retired story and acceptance
identifier from the removed validation-probe requirement family. Preserve the
identifiers as retired and state that none may be reused.
| enum HomeDisplayName { | ||
| static func normalized(_ raw: String) -> String { | ||
| let separators = CharacterSet.whitespacesAndNewlines | ||
| return raw | ||
| .components(separatedBy: separators) | ||
| .filter { !$0.isEmpty } | ||
| .joined(separator: " ") | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Expect at least one production call site outside the test target.
rg -n --glob '*.swift' --glob '!ios/HomesFlowTests/**' \
'HomeDisplayName\.normalized\s*\(' iosRepository: rdryfoos/HomesFlow
Length of output: 156
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Files matching HomeDisplayName or FR-HOME-04:\n'
rg -n --glob '*.swift' --glob '!ios/HomesFlowTests/**' 'HomeDisplayName|FR-HOME-04' ios || true
printf '\nHomeDisplayName.swift:\n'
cat -n ios/HomesFlow/Core/Home/HomeDisplayName.swift
printf '\nAll HomeDisplayName references:\n'
rg -n --glob '*.swift' 'HomeDisplayName' iosRepository: rdryfoos/HomesFlow
Length of output: 2460
Wire normalization into production display paths.
HomeDisplayName.normalized(_:) only has a test caller in ios/HomesFlowTests/HomeDisplayNameTests.swift; no outside Swift source calls the helper. Add a production display caller or remove the @covers FR-HOME-04 annotation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@ios/HomesFlow/Core/Home/HomeDisplayName.swift` around lines 8 - 15, Wire
HomeDisplayName.normalized(_:) into the production home display-name path so
user-facing names consistently use the normalization helper; locate the existing
production code that renders or exposes home names and route that value through
HomeDisplayName.normalized(_:).


Summary
Renames the installed traceability bundle from the retired
clewseaunaming to SpecAssay (specassay-checkextension +specassaypreset), migrates task markers**Traces**:→**Carries**:, and tombstones the temporary CLEW probe IDs. As end-to-end evidence under the new naming, a zero-context cold agent then carried the next unminted PRD intent — a home display-name normalizer — all the way to a passing gate, with the deterministic check as its only witness. Gate 2: 81 rows, gate.ok true, 0 GAP (67 verified / 10 tracked-debt / 4 backlog).Traceability
T001(impl),T002(proof) —specs/002-home-name-normalize/tasks.mdFR-HOME-04,AC-HOME-15FR-HOME-04/AC-HOME-15minted intoHomesFlow.prd.md. The temporaryUS/FR/AC-CLEW-01probe IDs were tombstoned (retirement recorded neutrally; noclewstring remains anywhere in the tree).Proof
bash .specify/extensions/specassay-check/scripts/check-traceability.sh→ OK, exit 0, 0 GAPtest_AC_HOME_15_normalizes_whitespace(all edge cases: leading/trailing, internal runs, tabs, newlines, mixed, already-clean, empty, whitespace-only)@covers FR-HOME-04, AC-HOME-15onios/HomesFlow/Core/Home/HomeDisplayName.swiftDelivery checklist
claude/specassay-migration, not direct tomain)HomesFlow.prd.mdonly — no invented product behaviorNotes for review
trace-manifest.jsonis committed as the gate's emitted evidence for this run.🤖 Generated with Claude Code
https://claude.ai/code/session_01TM5e4tKiqCUNANBCkTtH2r
Generated by Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores