@techierathore/techieflow 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/TechieFlow/agents/analyst.md +0 -5
- package/.claude/commands/TechieFlow/agents/architect.md +0 -6
- package/.claude/commands/TechieFlow/agents/flow-master.md +41 -215
- package/.claude/commands/TechieFlow/agents/verifier.md +23 -64
- package/.claude/commands/TechieFlow/tasks/_metrics-emit-gate.md +24 -117
- package/.claude/commands/TechieFlow/tasks/_smoke-test-policy.md +20 -84
- package/.claude/commands/TechieFlow/tasks/_status-update-gate.md +10 -74
- package/.claude/commands/TechieFlow/tasks/_yolo-mode.md +20 -58
- package/.claude/commands/TechieFlow/tasks/amend-docs.md +20 -143
- package/.claude/commands/TechieFlow/tasks/build-phase.md +14 -224
- package/.claude/commands/TechieFlow/tasks/day1-brownfield.md +31 -505
- package/.claude/commands/TechieFlow/tasks/day1-greenfield.md +28 -213
- package/.claude/commands/TechieFlow/tasks/deploy-checklist.md +19 -0
- package/.claude/commands/TechieFlow/tasks/devguide.md +10 -219
- package/.claude/commands/TechieFlow/tasks/fix-issues.md +10 -129
- package/.claude/commands/TechieFlow/tasks/log-miss.md +19 -158
- package/.claude/commands/TechieFlow/tasks/metrics-report.md +1 -1
- package/.claude/commands/TechieFlow/tasks/mockups.md +12 -117
- package/.claude/commands/TechieFlow/tasks/refresh-status.md +9 -130
- package/.claude/commands/TechieFlow/tasks/split-brd.md +10 -126
- package/.claude/commands/TechieFlow/tasks/triage-and-fix.md +14 -0
- package/.claude/commands/TechieFlow/tasks/triage-issues.md +11 -152
- package/.claude/commands/TechieFlow/tasks/verify-phase.md +36 -572
- package/.opencode/plugin/techieflow.js +39 -12
- package/.tfcore/agents/analyst.md +0 -5
- package/.tfcore/agents/architect.md +0 -6
- package/.tfcore/agents/flow-master.md +41 -215
- package/.tfcore/agents/verifier.md +23 -64
- package/.tfcore/core-config.yaml +10 -0
- package/.tfcore/hooks/block-git.sh +4 -4
- package/.tfcore/hooks/guard-artifacts.sh +2 -2
- package/.tfcore/hooks/guard-build.sh +76 -0
- package/.tfcore/hooks/guard-db.sh +90 -0
- package/.tfcore/hooks/guard-metrics.sh +56 -0
- package/.tfcore/hooks/guard-status-html.sh +116 -71
- package/.tfcore/hooks/guard-status.sh +43 -16
- package/.tfcore/hooks/guard-verify.sh +70 -48
- package/.tfcore/hooks/sweep-artifacts.sh +2 -2
- package/.tfcore/install-manifest.yaml +0 -18
- package/.tfcore/routing.yaml +25 -14
- package/.tfcore/standards/coding-standards-core.md +61 -0
- package/.tfcore/standards/coding-standards-dotnet.md +93 -0
- package/.tfcore/tasks/_metrics-emit-gate.md +24 -117
- package/.tfcore/tasks/_smoke-test-policy.md +20 -84
- package/.tfcore/tasks/_status-update-gate.md +10 -74
- package/.tfcore/tasks/_yolo-mode.md +20 -58
- package/.tfcore/tasks/amend-docs.md +20 -143
- package/.tfcore/tasks/build-phase.md +14 -224
- package/.tfcore/tasks/day1-brownfield.md +31 -505
- package/.tfcore/tasks/day1-greenfield.md +28 -213
- package/.tfcore/tasks/deploy-checklist.md +19 -0
- package/.tfcore/tasks/devguide.md +10 -219
- package/.tfcore/tasks/fix-issues.md +10 -129
- package/.tfcore/tasks/log-miss.md +19 -158
- package/.tfcore/tasks/metrics-report.md +1 -1
- package/.tfcore/tasks/mockups.md +12 -117
- package/.tfcore/tasks/refresh-status.md +9 -130
- package/.tfcore/tasks/split-brd.md +10 -126
- package/.tfcore/tasks/triage-and-fix.md +14 -0
- package/.tfcore/tasks/triage-issues.md +11 -152
- package/.tfcore/tasks/verify-phase.md +36 -572
- package/.tfcore/telemetry/SCHEMA.md +43 -7
- package/.tfcore/telemetry/tf-metrics.sh +152 -17
- package/.tfcore/templates/project-brief-tmpl.yaml +1 -1
- package/.tfcore/templates/stack-defaults/dotnet.md +35 -0
- package/.tfcore/templates/stack-questions.md +77 -0
- package/.tfcore/templates/v4custom/app-agents-md-tmpl.md +3 -4
- package/.tfcore/templates/v4custom/app-architecture-tmpl.md +107 -115
- package/.tfcore/templates/v4custom/app-brd-tmpl.md +108 -184
- package/.tfcore/templates/v4custom/app-checklist-tmpl.md +48 -73
- package/.tfcore/templates/v4custom/app-claude-md-tmpl.md +1 -1
- package/.tfcore/templates/v4custom/app-coding-standards-tmpl.md +52 -0
- package/.tfcore/templates/v4custom/app-deployment-checklist-tmpl.md +86 -0
- package/.tfcore/templates/v4custom/app-devguide-tmpl.md +69 -146
- package/.tfcore/templates/v4custom/app-phases-tmpl.md +35 -0
- package/.tfcore/templates/v4custom/app-productguide-tmpl.md +38 -35
- package/.tfcore/templates/v4custom/app-project-status-tmpl.md +63 -73
- package/.tfcore/templates/v4custom/app-uidesign-tmpl.md +62 -37
- package/.tfcore/templates/v4custom/app-usageguide-tmpl.md +69 -54
- package/.tfcore/templates/v4custom/build-invocation-ladder.md +17 -180
- package/.tfcore/templates/v4custom/build-subagent-prompt.md +17 -0
- package/.tfcore/templates/v4custom/metrics-report-template.md +2 -2
- package/.tfcore/user-guide.md +0 -23
- package/.tfcore/utils/__pycache__/tf-brd-status.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-checklist-edit.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-codex-bind.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-codex-telemetry.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-day1-files.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-devguide-list.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-doc-check.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-log-miss.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-misses-md.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-mockups-locate.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-opencode-audit.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-perf-grade.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-render-html.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-split-brd.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-status-facts.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-triage.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-verify-list.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-verify-verdict.cpython-312.pyc +0 -0
- package/.tfcore/utils/tf-brd-status.py +176 -0
- package/.tfcore/utils/tf-brd-status.sh +19 -0
- package/.tfcore/utils/tf-build-list.py +191 -0
- package/.tfcore/utils/tf-build-list.sh +20 -0
- package/.tfcore/utils/tf-build.sh +143 -0
- package/.tfcore/utils/tf-cdp-relay.ps1 +64 -0
- package/.tfcore/utils/tf-checklist-edit.py +133 -0
- package/.tfcore/utils/tf-day1-files.py +208 -0
- package/.tfcore/utils/tf-day1-files.sh +20 -0
- package/.tfcore/utils/tf-devguide-list.py +249 -0
- package/.tfcore/utils/tf-devguide-list.sh +18 -0
- package/.tfcore/utils/tf-doc-check.py +1267 -0
- package/.tfcore/utils/tf-doc-check.sh +29 -0
- package/.tfcore/utils/tf-emit.sh +203 -13
- package/.tfcore/utils/tf-fix-close.sh +83 -0
- package/.tfcore/utils/tf-goal.sh +193 -62
- package/.tfcore/utils/tf-harness.sh +4 -9
- package/.tfcore/utils/tf-log-miss.py +197 -0
- package/.tfcore/utils/tf-log-miss.sh +14 -0
- package/.tfcore/utils/tf-misses-md.py +211 -0
- package/.tfcore/utils/tf-misses-md.sh +13 -0
- package/.tfcore/utils/tf-mockups-locate.py +66 -0
- package/.tfcore/utils/tf-mockups-locate.sh +18 -0
- package/.tfcore/utils/tf-opencode-audit.py +23 -7
- package/.tfcore/utils/tf-perf-grade.py +97 -0
- package/.tfcore/utils/tf-perf-grade.sh +12 -0
- package/.tfcore/utils/tf-phase.sh +74 -0
- package/.tfcore/utils/tf-routing-bind.sh +10 -5
- package/.tfcore/utils/tf-routing.sh +6 -7
- package/.tfcore/utils/tf-split-brd.py +304 -0
- package/.tfcore/utils/tf-split-brd.sh +22 -0
- package/.tfcore/utils/tf-status-evidence.sh +68 -0
- package/.tfcore/utils/tf-status-facts.py +309 -0
- package/.tfcore/utils/tf-status-facts.sh +20 -0
- package/.tfcore/utils/tf-triage.py +243 -0
- package/.tfcore/utils/tf-triage.sh +16 -0
- package/.tfcore/utils/tf-verify-boot.sh +250 -0
- package/.tfcore/utils/tf-verify-emit.sh +110 -0
- package/.tfcore/utils/tf-verify-env.sh +88 -0
- package/.tfcore/utils/tf-verify-list.py +270 -0
- package/.tfcore/utils/tf-verify-list.sh +13 -0
- package/.tfcore/utils/tf-verify-screens.mjs +283 -0
- package/.tfcore/utils/tf-verify-screens.sh +22 -0
- package/.tfcore/utils/tf-verify-tests.sh +123 -0
- package/.tfcore/utils/tf-verify-verdict.py +283 -0
- package/.tfcore/utils/tf-verify-verdict.sh +15 -0
- package/.tfcore/utils/tf-yolo.sh +59 -0
- package/README.md +114 -1149
- package/docs/TechieFlow-Installation.md +27 -7
- package/opencode.jsonc +13 -33
- package/package.json +4 -7
- package/scripts/install.mjs +73 -46
- package/scripts/npm-cleanup.mjs +137 -0
- package/scripts/npm-postinstall.mjs +49 -0
- package/.claude/commands/TechieFlow/tasks/advanced-elicitation.md +0 -117
- package/.claude/commands/TechieFlow/tasks/author-brd.md +0 -79
- package/.claude/commands/TechieFlow/tasks/document-project.md +0 -343
- package/.claude/commands/TechieFlow/tasks/execute-checklist.md +0 -86
- package/.claude/commands/TechieFlow/tasks/index-docs.md +0 -173
- package/.claude/commands/TechieFlow/tasks/kb-mode-interaction.md +0 -75
- package/.claude/commands/TechieFlow/tasks/shard-doc.md +0 -185
- package/.codex/config.toml +0 -46
- package/.codex/hooks.json +0 -63
- package/.codex/rules/techieflow.rules +0 -8
- package/.tfcore/hooks/codex-adapter.py +0 -248
- package/.tfcore/tasks/advanced-elicitation.md +0 -117
- package/.tfcore/tasks/author-brd.md +0 -79
- package/.tfcore/tasks/document-project.md +0 -343
- package/.tfcore/tasks/execute-checklist.md +0 -86
- package/.tfcore/tasks/index-docs.md +0 -173
- package/.tfcore/tasks/kb-mode-interaction.md +0 -75
- package/.tfcore/tasks/shard-doc.md +0 -185
- package/.tfcore/utils/tf-codex-bind.py +0 -196
- package/.tfcore/utils/tf-codex-telemetry.py +0 -60
- package/WORKFLOW.html +0 -1986
- package/scripts/test-install.mjs +0 -505
- package/scripts/validate.mjs +0 -163
package/WORKFLOW.html
DELETED
|
@@ -1,1986 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
-
<title>TechieFlow: Solo-Dev Delivery Workflow — Claude Code + OpenCode + Codex</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root{
|
|
9
|
-
--bg:#0f1115; --panel:#161a22; --panel2:#1c2230; --line:#2a3142;
|
|
10
|
-
--ink:#e6e8ee; --muted:#9aa3b2; --accent:#7cc4ff; --accent2:#a6e3a1;
|
|
11
|
-
--warn:#f9c74f; --danger:#f38ba8; --ok:#a6e3a1;
|
|
12
|
-
--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
|
|
13
|
-
--sans:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
|
|
14
|
-
}
|
|
15
|
-
*{box-sizing:border-box}
|
|
16
|
-
html,body{margin:0;padding:0;background:var(--bg);color:var(--ink);font-family:var(--sans);line-height:1.5;font-size:15px}
|
|
17
|
-
a{color:var(--accent);text-decoration:none}
|
|
18
|
-
a:hover{text-decoration:underline}
|
|
19
|
-
code{font-family:var(--mono);font-size:13px;background:#0a0d13;color:#e6e8ee;padding:1px 5px;border-radius:4px;border:1px solid var(--line)}
|
|
20
|
-
pre{font-family:var(--mono);font-size:12.5px;background:#0a0d13;border:1px solid var(--line);border-radius:8px;padding:12px 14px;overflow:auto;color:#d8dde8;position:relative}
|
|
21
|
-
pre code{background:none;border:none;padding:0}
|
|
22
|
-
.copy{position:absolute;top:8px;right:8px;background:#1c2230;color:#9aa3b2;border:1px solid var(--line);border-radius:6px;padding:3px 8px;font-size:11px;font-family:var(--sans);cursor:pointer}
|
|
23
|
-
.copy:hover{color:var(--accent);border-color:var(--accent)}
|
|
24
|
-
pre.mermaid{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:16px 14px;text-align:center;color:var(--ink);overflow:auto;line-height:1.3}
|
|
25
|
-
.dcap{font-size:14px;color:var(--accent);font-weight:700;margin:18px 0 4px}
|
|
26
|
-
.dnote{font-size:12.5px;color:var(--muted);margin:0 0 6px}
|
|
27
|
-
.layout{display:grid;grid-template-columns:260px 1fr;min-height:100vh}
|
|
28
|
-
nav.side{position:sticky;top:0;height:100vh;overflow-y:auto;border-right:1px solid var(--line);background:var(--panel);padding:18px 14px}
|
|
29
|
-
nav.side h1{font-size:14px;margin:0 0 4px;letter-spacing:.5px;color:var(--ink)}
|
|
30
|
-
nav.side .sub{font-size:11.5px;color:var(--muted);margin-bottom:14px}
|
|
31
|
-
nav.side ol{list-style:none;padding:0;margin:0;counter-reset:n}
|
|
32
|
-
nav.side ol li{counter-increment:n;font-size:13px;margin:2px 0}
|
|
33
|
-
nav.side ol li a{display:block;padding:5px 8px;color:var(--ink);border-radius:6px}
|
|
34
|
-
nav.side ol li a::before{content:counter(n,decimal-leading-zero);color:var(--muted);font-family:var(--mono);font-size:11px;margin-right:8px}
|
|
35
|
-
nav.side ol li a:hover{background:var(--panel2);text-decoration:none}
|
|
36
|
-
nav.side .group{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.7px;margin:14px 8px 4px}
|
|
37
|
-
main{padding:32px 40px 80px;max-width:1100px}
|
|
38
|
-
h2{font-size:22px;margin:32px 0 10px;padding-bottom:6px;border-bottom:1px solid var(--line);scroll-margin-top:16px}
|
|
39
|
-
h3{font-size:17px;margin:22px 0 6px;color:#cfd5e3;scroll-margin-top:16px}
|
|
40
|
-
h4{font-size:14px;margin:14px 0 4px;color:var(--accent)}
|
|
41
|
-
p{margin:6px 0 10px}
|
|
42
|
-
.lede{color:var(--muted);font-size:14px;margin-top:-4px}
|
|
43
|
-
.panel{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:14px 18px;margin:10px 0}
|
|
44
|
-
.panel.warn{border-color:#5a4a1a;background:#241d10}
|
|
45
|
-
.panel.ok{border-color:#2f5a2f;background:#13211a}
|
|
46
|
-
.panel.danger{border-color:#5a2a3a;background:#241016}
|
|
47
|
-
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
|
|
48
|
-
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
|
|
49
|
-
table{border-collapse:collapse;width:100%;font-size:13.5px;margin:8px 0}
|
|
50
|
-
table.quickref-legacy{display:none}
|
|
51
|
-
th,td{border:1px solid var(--line);padding:8px 10px;text-align:left;vertical-align:top}
|
|
52
|
-
th{background:var(--panel2);color:#cfd5e3;font-weight:600}
|
|
53
|
-
tr:nth-child(even) td{background:#13171f}
|
|
54
|
-
.badge{display:inline-block;font-size:11px;padding:2px 7px;border-radius:999px;background:#1c2230;border:1px solid var(--line);color:var(--muted);font-family:var(--mono)}
|
|
55
|
-
.badge.cmd{color:var(--accent);border-color:#274d6e}
|
|
56
|
-
.badge.agent{color:#c4b5fd;border-color:#3a335a}
|
|
57
|
-
.badge.task{color:#fcd34d;border-color:#564218}
|
|
58
|
-
.badge.file{color:#86efac;border-color:#1f4a2a}
|
|
59
|
-
.tabs{display:flex;gap:0;border-bottom:1px solid var(--line);margin:14px 0 0}
|
|
60
|
-
.tabs button{background:none;color:var(--muted);border:none;border-bottom:2px solid transparent;padding:10px 16px;font:inherit;cursor:pointer}
|
|
61
|
-
.tabs button.active{color:var(--accent);border-color:var(--accent)}
|
|
62
|
-
.tabpanel{display:none;padding:16px 0}
|
|
63
|
-
.tabpanel.active{display:block}
|
|
64
|
-
.flow{display:flex;flex-direction:column;gap:6px;margin:14px 0}
|
|
65
|
-
.step{display:grid;grid-template-columns:38px 1fr;gap:12px;align-items:start;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:10px 12px}
|
|
66
|
-
.step .num{font-family:var(--mono);font-size:16px;font-weight:700;color:var(--accent);background:#0d2030;border:1px solid #274d6e;border-radius:8px;width:38px;height:38px;display:flex;align-items:center;justify-content:center}
|
|
67
|
-
.step .body h4{margin:0 0 4px;color:var(--ink);font-size:14.5px}
|
|
68
|
-
.step .body p{margin:2px 0;font-size:13.5px;color:#cfd5e3}
|
|
69
|
-
.step .body .cmds{margin-top:6px}
|
|
70
|
-
.arrow{display:flex;justify-content:center;color:var(--muted);font-size:18px;font-family:var(--mono)}
|
|
71
|
-
.kbd{font-family:var(--mono);background:#0a0d13;border:1px solid var(--line);padding:1px 5px;border-radius:4px;font-size:12px;color:#cfd5e3}
|
|
72
|
-
hr{border:none;border-top:1px solid var(--line);margin:24px 0}
|
|
73
|
-
.toc-mini{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:8px 14px;font-size:13px;color:var(--muted);margin:8px 0 16px}
|
|
74
|
-
.toc-mini a{color:#cfd5e3}
|
|
75
|
-
details{border:1px solid var(--line);border-radius:8px;background:var(--panel);padding:8px 14px;margin:8px 0}
|
|
76
|
-
details > summary{cursor:pointer;color:var(--ink);font-weight:600;font-size:14px}
|
|
77
|
-
details[open] > summary{margin-bottom:8px}
|
|
78
|
-
.pain{display:grid;grid-template-columns:1fr 1fr;gap:10px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:10px 14px;margin:8px 0}
|
|
79
|
-
.pain .p{color:#f0b4be}
|
|
80
|
-
.pain .s{color:#bce6c4}
|
|
81
|
-
.pain h4{margin:0 0 4px}
|
|
82
|
-
.small{font-size:12.5px;color:var(--muted)}
|
|
83
|
-
ul.tight,ol.tight{margin:6px 0;padding-left:22px}
|
|
84
|
-
ul.tight li,ol.tight li{margin:2px 0}
|
|
85
|
-
.anchor-link{color:var(--muted);font-weight:400;font-size:0.85em;margin-left:8px;opacity:0;transition:opacity .15s}
|
|
86
|
-
h2:hover .anchor-link,h3:hover .anchor-link{opacity:1}
|
|
87
|
-
.pill{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:#0d2030;color:var(--accent);font-family:var(--mono);border:1px solid #274d6e;margin-right:6px}
|
|
88
|
-
.pill.ok{background:#13211a;color:var(--ok);border-color:#2f5a2f}
|
|
89
|
-
.pill.warn{background:#241d10;color:var(--warn);border-color:#5a4a1a}
|
|
90
|
-
.pill.once{background:#241016;color:#f38ba8;border-color:#5a2a3a}
|
|
91
|
-
.audience{display:inline-block;font-size:10.5px;padding:1px 6px;border-radius:4px;font-family:var(--mono);margin-left:6px;vertical-align:middle}
|
|
92
|
-
.audience.h{background:#162a18;color:#86efac;border:1px solid #1f4a2a}
|
|
93
|
-
.audience.a{background:#1c1731;color:#c4b5fd;border:1px solid #3a335a}
|
|
94
|
-
.placeholder{color:#f9c74f;font-family:var(--mono);font-size:13px;background:#241d10;padding:0 5px;border-radius:3px;border:1px solid #5a4a1a}
|
|
95
|
-
@media(max-width:900px){.layout{grid-template-columns:1fr}nav.side{position:static;height:auto}}
|
|
96
|
-
</style>
|
|
97
|
-
</head>
|
|
98
|
-
<body>
|
|
99
|
-
<div class="layout">
|
|
100
|
-
<nav class="side">
|
|
101
|
-
<h1>TechieFlow: Solo-Dev Delivery Framework</h1>
|
|
102
|
-
<div class="sub">Custom workflow for Claude Max + WSL / macOS</div>
|
|
103
|
-
<div class="group">Quick reference</div>
|
|
104
|
-
<ol>
|
|
105
|
-
<li><a href="#ataglance">Process at a glance (flowcharts)</a></li>
|
|
106
|
-
</ol>
|
|
107
|
-
<div class="group">One-time</div>
|
|
108
|
-
<ol>
|
|
109
|
-
<li><a href="#wsl-bootstrap">WSL bootstrap (once, ever)</a></li>
|
|
110
|
-
<li><a href="#mac-bootstrap">macOS bootstrap (once, ever)</a></li>
|
|
111
|
-
<li><a href="#device-bootstrap">Device-host bootstrap (MAUI Android/iOS/Mac)</a></li>
|
|
112
|
-
</ol>
|
|
113
|
-
<div class="group">Start here</div>
|
|
114
|
-
<ol>
|
|
115
|
-
<li><a href="#overview">Overview & principles</a></li>
|
|
116
|
-
<li><a href="#painpoints">Pain points → solutions</a></li>
|
|
117
|
-
<li><a href="#scaffolding">Scaffolding a project</a></li>
|
|
118
|
-
<li><a href="#naming">File-naming convention</a></li>
|
|
119
|
-
<li><a href="#structure">Project structure</a></li>
|
|
120
|
-
<li><a href="#docs">Doc artifacts & audiences</a></li>
|
|
121
|
-
</ol>
|
|
122
|
-
<div class="group">Workflows</div>
|
|
123
|
-
<ol>
|
|
124
|
-
<li><a href="#flows">Brownfield / Greenfield</a></li>
|
|
125
|
-
<li><a href="#resume">Resuming a cold project</a></li>
|
|
126
|
-
</ol>
|
|
127
|
-
<div class="group">Operate</div>
|
|
128
|
-
<ol>
|
|
129
|
-
<li><a href="#libraries">Custom library agents</a></li>
|
|
130
|
-
<li><a href="#standards-enforcement">Coding standards enforcement</a></li>
|
|
131
|
-
<li><a href="#wsl-runtime">MAUI from WSL / macOS</a></li>
|
|
132
|
-
<li><a href="#permissions">Permissions (yolo-except-git-writes)</a></li>
|
|
133
|
-
</ol>
|
|
134
|
-
<div class="group">Reference</div>
|
|
135
|
-
<ol>
|
|
136
|
-
<li><a href="#agents">Agent cheat sheet</a></li>
|
|
137
|
-
<li><a href="#quickref">Command reference</a></li>
|
|
138
|
-
<li><a href="#faq">FAQ & gotchas</a></li>
|
|
139
|
-
<li><a href="#platforms">Running on macOS / Windows / Linux</a></li>
|
|
140
|
-
<li><a href="#telemetry">Development telemetry</a> · <a href="#misses">misses & rework cost</a> · <a href="#telemetry-gotchas">gotchas</a></li>
|
|
141
|
-
<li><a href="#model-routing">Model routing (per-phase tiers)</a></li>
|
|
142
|
-
<li><a href="#team-edition">Team edition — the AI-First Playbook</a></li>
|
|
143
|
-
</ol>
|
|
144
|
-
</nav>
|
|
145
|
-
|
|
146
|
-
<main>
|
|
147
|
-
|
|
148
|
-
<h1 style="margin:0 0 4px;font-size:28px">TechieFlow: Solo-Dev Delivery Workflow</h1>
|
|
149
|
-
<div class="lede">Compressed TechieFlow process for one-person teams. Two flows (brownfield + greenfield), human-readable BRD + Architecture with Mermaid, project-specific coding standards every agent follows, automated verification via <code>verifier</code>, your own library agents (<code>trblazeui</code>, <code>techierag</code>) baked in, zero-friction permissions.</div>
|
|
150
|
-
|
|
151
|
-
<div class="toc-mini">
|
|
152
|
-
<span class="pill">Root</span> <code>/Volumes/MacD/MyCode/TechieFlow</code> (macOS) · <code>/mnt/c/3AIGenCode/TechieFlow</code> (WSL) ·
|
|
153
|
-
<span class="pill">Harness</span> Claude Code + OpenCode + Codex ·
|
|
154
|
-
<span class="pill">Stack</span> .NET / Blazor / MAUI / TrBlazeUI / TechieRag
|
|
155
|
-
</div>
|
|
156
|
-
|
|
157
|
-
<!-- ============================================================ -->
|
|
158
|
-
<!-- PROCESS AT A GLANCE — quick-reference flowcharts -->
|
|
159
|
-
<!-- ============================================================ -->
|
|
160
|
-
<h2 id="ataglance">Process at a glance — flowcharts <span class="pill">quick reference</span><span class="anchor-link"><a href="#ataglance">#</a></span></h2>
|
|
161
|
-
<p class="lede" style="font-size:15px">The whole process on one screen. Each box is the exact command to run (agent + <code>*task</code>); the deep sections (<a href="#flows">§7</a>, <a href="#resume">§8</a>) explain each step. Loops mean "repeat until the gate passes".</p>
|
|
162
|
-
|
|
163
|
-
<div class="dcap">A · Greenfield — new app from scratch</div>
|
|
164
|
-
<pre class="mermaid">
|
|
165
|
-
flowchart TD
|
|
166
|
-
A["scaffold-greenfield.sh ."] --> B["/analyst *day1-greenfield"]
|
|
167
|
-
B --> M["/analyst *mockups (auto-run at day-1)"]
|
|
168
|
-
M --> C{"Approve BRD + Architecture + mockups"}
|
|
169
|
-
C -->|"approved"| D["/analyst *split-brd (creates the one Checklist)"]
|
|
170
|
-
D --> E["/flow-master *build-phase (calls trblazeui + techierag)"]
|
|
171
|
-
E --> F["/verifier *verify all (data + visual gates)"]
|
|
172
|
-
F --> G{"All REQ Verified?"}
|
|
173
|
-
G -->|"bugs found"| X["/flow-master *fix-issues {App} {screenshots-folder}"]
|
|
174
|
-
X --> F
|
|
175
|
-
G -->|"UAT/prod bugs — log, don't fix yet"| T["/flow-master *triage-issues {App} {evidence}"]
|
|
176
|
-
T --> X
|
|
177
|
-
G -->|"yes"| H["/flow-master *handoff-phase"]
|
|
178
|
-
</pre>
|
|
179
|
-
|
|
180
|
-
<div class="dcap">B · Brownfield — existing app</div>
|
|
181
|
-
<pre class="mermaid">
|
|
182
|
-
flowchart TD
|
|
183
|
-
A["scaffold-brownfield.sh ."] --> B["/analyst *day1-brownfield (reverse-doc + DevGuide)"]
|
|
184
|
-
B --> C{"Was a dev plan migrated into the Checklist?"}
|
|
185
|
-
C -->|"no"| D["/analyst *split-brd (creates the Checklist)"]
|
|
186
|
-
C -->|"yes"| E["/flow-master *build-phase"]
|
|
187
|
-
D --> E
|
|
188
|
-
E --> F["/verifier *verify all"]
|
|
189
|
-
F --> G{"All REQ Verified?"}
|
|
190
|
-
G -->|"bugs found"| X["/flow-master *fix-issues {App} {screenshots-folder}"]
|
|
191
|
-
X --> F
|
|
192
|
-
G -->|"UAT/prod bugs — log, don't fix yet"| T["/flow-master *triage-issues {App} {evidence}"]
|
|
193
|
-
T --> X
|
|
194
|
-
G -->|"yes"| H["/flow-master *handoff-phase"]
|
|
195
|
-
</pre>
|
|
196
|
-
|
|
197
|
-
<div class="dcap">C · Which command next? — the Build to Verify to Handoff ladder</div>
|
|
198
|
-
<p class="dnote">Pick the next command from the <em>weakest</em> open REQ in the Checklist. When in doubt, build.</p>
|
|
199
|
-
<pre class="mermaid">
|
|
200
|
-
flowchart TD
|
|
201
|
-
S{"Weakest open REQ in the Checklist?"}
|
|
202
|
-
S -->|"any REQ unbuilt (Planned / In Progress / PARTIAL), or built but not testable yet"| B["/flow-master *build-phase {App}"]
|
|
203
|
-
S -->|"all built and testable, some not yet Verified"| V["/verifier *verify all {App}"]
|
|
204
|
-
S -->|"all REQ Verified"| H["/flow-master *handoff-phase {App}"]
|
|
205
|
-
</pre>
|
|
206
|
-
|
|
207
|
-
<div class="dcap">D · Recovering a cold / interrupted project</div>
|
|
208
|
-
<pre class="mermaid">
|
|
209
|
-
flowchart LR
|
|
210
|
-
A["Session died mid-phase — PROJECT-STATUS is stale"] --> B["/flow-master *refresh-status {App}"]
|
|
211
|
-
B --> C["Rebuilds status from Checklist + files on disk + a fresh build"]
|
|
212
|
-
C --> D["Prints the exact next command to resume"]
|
|
213
|
-
</pre>
|
|
214
|
-
|
|
215
|
-
<div class="dcap">E · Library project (TrBlazeUI / TechieRag) — docs and DevGuide</div>
|
|
216
|
-
<p class="dnote">A NuGet library is a first-class project: same doc set as an app, DevGuide driven by its demo/sample app.</p>
|
|
217
|
-
<pre class="mermaid">
|
|
218
|
-
flowchart TD
|
|
219
|
-
A["Library repo (TrBlazeUI / TechieRag)"] --> B["/analyst *day1-brownfield (docs + PROJECT-STATUS)"]
|
|
220
|
-
B --> C["/analyst *split-brd (the Checklist)"]
|
|
221
|
-
C --> D["/flow-master *devguide --update"]
|
|
222
|
-
D --> E["UI-component library: component-by-component"]
|
|
223
|
-
D --> G["Service / SDK library: service-by-service"]
|
|
224
|
-
</pre>
|
|
225
|
-
|
|
226
|
-
<!-- ============================================================ -->
|
|
227
|
-
<h2 id="wsl-bootstrap">0. WSL bootstrap — <span class="pill once">DO ONCE, EVER</span><span class="anchor-link"><a href="#wsl-bootstrap">#</a></span></h2>
|
|
228
|
-
|
|
229
|
-
<p><strong>Run this once per WSL distro.</strong> Installs headless-Chromium system libs + the MAUI bridge.</p>
|
|
230
|
-
|
|
231
|
-
<div class="panel ok"><strong>On macOS: skip this section — your one-time setup is <a href="#mac-bootstrap">§0a</a> instead.</strong> There is no <code>winrun</code> bridge on a Mac (<code>dotnet</code> and MAUI run natively) and Playwright's Chromium needs no apt libraries.</div>
|
|
232
|
-
|
|
233
|
-
<pre><code class="lang-bash">sudo apt-get update && sudo apt-get install -y \
|
|
234
|
-
libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 \
|
|
235
|
-
libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libpango-1.0-0 \
|
|
236
|
-
libcairo2 libasound2 libgtk-3-0 libx11-xcb1
|
|
237
|
-
|
|
238
|
-
mkdir -p ~/bin && cat > ~/bin/winrun << 'SH'
|
|
239
|
-
#!/usr/bin/env bash
|
|
240
|
-
WINPATH=$(wslpath -w "$PWD")
|
|
241
|
-
powershell.exe -NoProfile -Command "cd '$WINPATH'; $*"
|
|
242
|
-
SH
|
|
243
|
-
chmod +x ~/bin/winrun
|
|
244
|
-
grep -q 'HOME/bin' ~/.bashrc || echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc</code></pre>
|
|
245
|
-
|
|
246
|
-
<div class="panel ok"><strong>Verify:</strong> open a new WSL terminal and run <code>which winrun</code> → <code>/home/<you>/bin/winrun</code>.</div>
|
|
247
|
-
|
|
248
|
-
<h3 id="opencode-wsl">OpenCode in WSL — the primary path (since 2026-08-20)</h3>
|
|
249
|
-
<p>OpenCode runs <strong>natively inside the same WSL distro as Claude Code</strong> — OpenCode's own docs recommend WSL over native Windows, and inside WSL it gets the entire runtime harness above (<code>winrun</code>, headless Chromium, Appium) for free. Full rationale, probe evidence, and the crash playbook: <code>docs/OpenCode-Deployment-Guide.md</code>.</p>
|
|
250
|
-
<pre><code class="lang-bash">curl -fsSL https://opencode.ai/install | bash
|
|
251
|
-
grep -q '.opencode/bin' ~/.bashrc || echo 'export PATH="$HOME/.opencode/bin:$PATH"' >> ~/.bashrc
|
|
252
|
-
opencode auth login</code></pre>
|
|
253
|
-
<div class="panel warn"><strong>The PATH line matters:</strong> WSL's Windows-interop otherwise resolves <code>opencode</code> to the Windows npm shim (<code>AppData\Roaming\npm\opencode</code>) — the native-Windows Bun build that breaks on large repos. Verify with <code>type -a opencode</code> (the <code>~/.opencode/bin</code> entry must come first).</div>
|
|
254
|
-
<p>The framework side is automatic: the scaffold/update scripts deploy <code>.opencode/plugin/techieflow.js</code> — the guard bridge that runs the same <code>.tfcore/hooks/</code> guards Claude Code runs (git ban, PROJECT-STATUS shape, Verified ledger) plus session telemetry with real dollar cost — and a framework-owned <code>.opencode/opencode.jsonc</code> into every app. Check with <code>opencode agent list</code> (the six TechieFlow agents must appear).</p>
|
|
255
|
-
<div class="panel ok"><strong>Large repos:</strong> the failure historically blamed on Bun is a <code>/mnt/c</code> (9p filesystem) pathology — OpenCode's snapshot walk can take minutes there, while the identical repo on WSL-native ext4 boots in seconds. Typical apps on <code>/mnt/c</code> are fine; genuinely large repos belong on ext4 (or see the watcher tuning in the deployment guide).</div>
|
|
256
|
-
|
|
257
|
-
<div class="panel warn"><strong>Everything below is the FALLBACK path (Docker), kept in case WSL ever reproduces the native-Windows crash — skip it on the WSL path.</strong> OpenCode in Docker on Windows is different from WSL: a Linux container cannot execute Windows <code>cmd.exe</code> or see the Windows .NET workloads. Do not install a fake <code>cmd.exe</code>. The supplied <code>docs/Dockerfile</code> uses the .NET 10 SDK and deliberately installs no MAUI workloads. Build standard .NET apps in the container; build Windows MAUI Blazor Desktop heads through its SSH-backed <code>winrun</code> bridge to the Windows host. Build and test mobile, iOS, and Mac Catalyst heads natively on a Mac.</div>
|
|
258
|
-
|
|
259
|
-
<h3 id="opencode-docker">Containerized OpenCode — one-time Windows host bridge (fallback only)</h3>
|
|
260
|
-
<p>This bridge is only required when the container must build or run a Windows-host project (for example, a Windows MAUI head). Blazor/Linux-compatible projects do not need it. The first command uses Windows Update and can take several minutes, but it should not remain at <code>Operation [Running]</code> indefinitely.</p>
|
|
261
|
-
<p>Run each command separately in an <strong>elevated PowerShell</strong> window. Do not paste the whole block while the first command is still running:</p>
|
|
262
|
-
<pre><code class="lang-powershell">$cap = Get-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
|
263
|
-
$cap.State
|
|
264
|
-
|
|
265
|
-
if ($cap.State -ne 'Installed') {
|
|
266
|
-
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
Get-Service sshd -ErrorAction SilentlyContinue
|
|
270
|
-
Start-Service sshd
|
|
271
|
-
Set-Service -Name sshd -StartupType Automatic
|
|
272
|
-
|
|
273
|
-
if (-not (Get-NetFirewallRule -Name OpenSSH-Server-In-TCP -ErrorAction SilentlyContinue)) {
|
|
274
|
-
New-NetFirewallRule -Name OpenSSH-Server-In-TCP -DisplayName "OpenSSH Server (sshd)" -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
|
|
275
|
-
}</code></pre>
|
|
276
|
-
<p>If <code>Add-WindowsCapability</code> is still running after about 10 minutes, press <kbd>Ctrl+C</kbd>. It has not reached the SSH commands. Check the servicing state and Windows Update source, then retry:</p>
|
|
277
|
-
<pre><code class="lang-powershell">Get-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
|
278
|
-
Get-WinEvent -LogName 'Microsoft-Windows-DISM/Operational' -MaxEvents 20 | Format-Table TimeCreated,Id,LevelDisplayName,Message -Wrap
|
|
279
|
-
Get-Service wuauserv,bits,TrustedInstaller | Format-Table Name,Status,StartType
|
|
280
|
-
# Optional: use Settings > System > Optional features > View features and install
|
|
281
|
-
# "OpenSSH Server" if the capability command cannot obtain its payload.</code></pre>
|
|
282
|
-
<p>When the capability reports <code>Installed</code>, open a <strong>normal</strong> PowerShell window as the same non-administrator Windows user that will run the launcher. Copy and paste this as <strong>one complete line</strong>. It is safe to run again:</p>
|
|
283
|
-
<pre><code class="lang-powershell">$ssh="$env:USERPROFILE\.ssh"; New-Item -ItemType Directory -Force $ssh | Out-Null; if (-not (Test-Path "$ssh\opencode-docker")) { ssh-keygen -t ed25519 -f "$ssh\opencode-docker" -N "" }; $publicKey=(Get-Content "$ssh\opencode-docker.pub" -Raw).Trim(); $auth="$ssh\authorized_keys"; if (-not (Test-Path $auth)) { Set-Content -Path $auth -Value $publicKey } elseif ((Get-Content $auth) -notcontains $publicKey) { Add-Content -Path $auth -Value $publicKey }</code></pre>
|
|
284
|
-
<p>Verify the bridge before starting Docker. This test deliberately disables password fallback. A successful test prints the Windows host's <code>dotnet --info</code> output and never asks for a password:</p>
|
|
285
|
-
<pre><code class="lang-powershell">ssh -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -i "$env:USERPROFILE\.ssh\opencode-docker" "$env:USERNAME@localhost" powershell.exe -NoProfile -NonInteractive -Command "dotnet --info"</code></pre>
|
|
286
|
-
<p>If the test reports <code>Permission denied (publickey)</code>, do not enter your VPS password or Windows password. Public-key authentication was not accepted. Check whether the account is an Administrator:</p>
|
|
287
|
-
<pre><code class="lang-powershell">whoami /groups | Select-String 'S-1-5-32-544'</code></pre>
|
|
288
|
-
<p>If that prints a result, Windows OpenSSH reads administrator keys from <code>C:\ProgramData\ssh\administrators_authorized_keys</code> instead of the profile file. In an elevated PowerShell window, install the same public key there and apply the required permissions:</p>
|
|
289
|
-
<pre><code class="lang-powershell">$auth="$env:ProgramData\ssh\administrators_authorized_keys"; $publicKey=(Get-Content "$env:USERPROFILE\.ssh\opencode-docker.pub" -Raw).Trim(); New-Item -ItemType Directory -Force (Split-Path $auth) | Out-Null; if (-not (Test-Path $auth)) { Set-Content -Path $auth -Value $publicKey } elseif ((Get-Content $auth) -notcontains $publicKey) { Add-Content -Path $auth -Value $publicKey }; icacls $auth /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"</code></pre>
|
|
290
|
-
<p>Retry the SSH command after that. If the account is not an Administrator, keep using the profile <code>authorized_keys</code> file and inspect the SSH log instead of entering a password:</p>
|
|
291
|
-
<pre><code class="lang-powershell">Get-WinEvent -LogName 'OpenSSH/Operational' -MaxEvents 20 | Format-Table TimeCreated,Id,Message -Wrap</code></pre>
|
|
292
|
-
<p>Keep <code>Dockerfile</code> and <code>opencode-docker.cmd</code> in <code>%USERPROFILE%\\.opencode-docker-config</code>. Build the image once from that folder, then put that folder on <code>PATH</code> so the command is available in every application PowerShell:</p>
|
|
293
|
-
<pre><code class="lang-powershell">Set-Location "$env:USERPROFILE\.opencode-docker-config"
|
|
294
|
-
docker build --pull --no-cache -t my-opencode-dotnet .
|
|
295
|
-
# Only if an app actually targets Tizen:
|
|
296
|
-
# docker build --pull --no-cache --build-arg INSTALL_TIZEN=true -t my-opencode-dotnet .</code></pre>
|
|
297
|
-
<p>From the application folder, run <code>opencode-docker.cmd</code>. It uses the existing <code>my-opencode-dotnet</code> image, gives each app its own OpenCode data directory, mounts NuGet and SSH credentials read-only, and passes the Windows app path to the bridge:</p>
|
|
298
|
-
<pre><code class="lang-powershell">opencode-docker.cmd</code></pre>
|
|
299
|
-
<p>The equivalent expanded container command is:</p>
|
|
300
|
-
<pre><code class="lang-powershell">docker run --rm -it `
|
|
301
|
-
-v "${USERPROFILE}\.opencode-docker\nuget:/root/.nuget/NuGet:ro" `
|
|
302
|
-
-v "${USERPROFILE}\.ssh:/root/.ssh:ro" `
|
|
303
|
-
-v "${PWD}:/workspace" -w /workspace `
|
|
304
|
-
-e TF_WINDOWS_SSH_HOST=host.docker.internal `
|
|
305
|
-
-e TF_WINDOWS_SSH_USER="$env:USERNAME" `
|
|
306
|
-
-e TF_WINDOWS_SSH_KEY=/root/.ssh/opencode-docker `
|
|
307
|
-
-e TF_WINDOWS_APP_PATH="C:\\path\\to\\app" `
|
|
308
|
-
-e TF_OPENCODE_DOCKER=1 `
|
|
309
|
-
my-opencode-dotnet opencode</code></pre>
|
|
310
|
-
<p>Inside the container use <code>dotnet build</code> and <code>dotnet test</code> for standard .NET projects. Use <code>winrun "dotnet --info"</code> as the bridge probe, then <code>winrun "dotnet build -c Release"</code> for the Windows MAUI Blazor Desktop head. <code>TF_WINDOWS_APP_PATH</code> is the Windows path to the same app mounted as <code>/workspace</code>. Mobile, iOS, and Mac Catalyst builds and runtime UI tests are outside this Windows container setup and should run on a Mac.</p>
|
|
311
|
-
<p>The SSH directory is intentionally mounted read-only. Docker Desktop may expose the mounted key with Linux mode <code>0777</code>, which OpenSSH rejects, and the mounted directory cannot accept a new <code>known_hosts</code> file. The image's <code>winrun</code> wrapper copies the key to writable <code>/tmp/opencode-docker/</code> with mode <code>0600</code> and creates its writable host-trust file there. Do not try to <code>chmod</code> the mounted key from inside the container.</p>
|
|
312
|
-
|
|
313
|
-
<!-- ============================================================ -->
|
|
314
|
-
<h2 id="mac-bootstrap">0a. macOS bootstrap — <span class="pill once">DO ONCE, EVER</span><span class="anchor-link"><a href="#mac-bootstrap">#</a></span></h2>
|
|
315
|
-
|
|
316
|
-
<p><strong>Run this once per Mac.</strong> The native equivalent of §0: everything the agents need to build, run, and <em>see</em> your apps on macOS. There is no <code>winrun</code> bridge to install — <code>dotnet</code>, Playwright, and Appium all run natively — but the machine still needs its toolchain once.</p>
|
|
317
|
-
|
|
318
|
-
<pre><code class="lang-bash"># 1. Xcode Command Line Tools — provides git AND python3 (the framework's
|
|
319
|
-
# guard-status/guard-verify hooks silently fail open without python3)
|
|
320
|
-
xcode-select --install
|
|
321
|
-
|
|
322
|
-
# If full Xcode is installed (required for MAUI iOS / Mac Catalyst builds),
|
|
323
|
-
# accept its license once or python3/git error out with a license prompt:
|
|
324
|
-
sudo xcodebuild -license accept
|
|
325
|
-
|
|
326
|
-
# 2. Homebrew (skip if `brew --version` already works)
|
|
327
|
-
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
328
|
-
|
|
329
|
-
# 3. The toolchain: .NET SDK + Node.js (Node powers Playwright and Appium)
|
|
330
|
-
brew install dotnet-sdk node
|
|
331
|
-
|
|
332
|
-
# 4. MAUI workload — only if any of your apps ships a MAUI head.
|
|
333
|
-
# sudo is REQUIRED on macOS: the SDK lives in root-owned /usr/local/share/dotnet,
|
|
334
|
-
# so without it this (and any `dotnet workload update` / SDK update) fails with
|
|
335
|
-
# "Inadequate permissions. Run the command with elevated privileges."
|
|
336
|
-
sudo dotnet workload install maui</code></pre>
|
|
337
|
-
|
|
338
|
-
<div class="panel ok"><strong>Playwright — nothing for you to do.</strong> The verifier <strong>self-provisions</strong> it per project the first time it runs (<code>verify-phase.md §1</code>, also used by every self-smoke): it creates <code>package.json</code> if missing, runs <code>npm install -D @playwright/test</code> + <code>npx playwright install chromium</code>, and writes a minimal <code>playwright.config.ts</code>. The only machine-level prerequisite is <strong>Node</strong> (step 3 above). The Chromium download is cached once under <code>~/Library/Caches/ms-playwright</code> and shared by every project, so only the first project ever pays it — and unlike WSL there are no system libraries to install.</div>
|
|
339
|
-
|
|
340
|
-
<div class="panel ok"><strong>Verify:</strong> <code>dotnet --info</code> prints an SDK, <code>node --version</code> answers, and <code>python3 --version</code> answers <em>without</em> an Xcode-license error. The agents handle everything else per project.</div>
|
|
341
|
-
|
|
342
|
-
<div class="panel"><strong>MAUI native-UI testing</strong> (Android emulator / iOS Simulator / Mac Catalyst): continue with <a href="#device-bootstrap">§0b</a> — on a Mac-native setup every piece of it (Android Studio + emulator, Appium + drivers, the Simulator) runs on this same machine, and all endpoints are <code>http://localhost:4723</code>.</div>
|
|
343
|
-
|
|
344
|
-
<!-- ============================================================ -->
|
|
345
|
-
<h2 id="device-bootstrap">0b. Device-host bootstrap (MAUI Android / iOS / Mac Catalyst) — <span class="pill once">DO ONCE PER HOST</span><span class="anchor-link"><a href="#device-bootstrap">#</a></span></h2>
|
|
346
|
-
|
|
347
|
-
<h3>What this is, in plain words</h3>
|
|
348
|
-
|
|
349
|
-
<p>The AI does its own testing of every app it builds. For a <strong>website</strong> app it can already "see" the screens — it opens the site in an invisible browser, looks at each page, and checks that everything shows up and looks right. But when an app runs on a <strong>phone, tablet, or as a Mac desktop program</strong>, the AI has no window into it: it can confirm the app <em>compiles</em>, but it can't <em>see</em> what the running app looks like. That is the gap this setup closes — without it, the AI might report "all good" while the real phone screen has buttons on top of each other, text cut off, or empty lists.</p>
|
|
350
|
-
|
|
351
|
-
<div class="panel"><strong>The analogy:</strong> think of the AI as a quality inspector. For websites it already has a screen to watch. This one-time setup gives it a <strong>video feed and a remote control for a phone (and a Mac)</strong> so it can tap around the real app, take screenshots, and catch a broken-looking screen — the same way it already does for websites. You set up the camera and remote <em>once</em>; after that the AI uses them by itself every time it tests.</div>
|
|
352
|
-
|
|
353
|
-
<div class="panel warn"><strong>Do you even need this?</strong> Only if the app runs on <strong>phones/tablets (Android or iPhone/iPad)</strong> or as a <strong>Mac desktop program</strong>. If your app is a normal <strong>website</strong> (Blazor), you can skip this whole section — website testing already works out of the box. You can also set up just the parts you need: only Android, or only Apple, or both.</div>
|
|
354
|
-
|
|
355
|
-
<h3>A few words you'll see</h3>
|
|
356
|
-
<table>
|
|
357
|
-
<tr><th>Word</th><th>What it means here</th></tr>
|
|
358
|
-
<tr><td><strong>Appium</strong></td><td>The free tool that acts as the "remote control" — it lets the AI tap buttons and read the screen of a phone or Mac app.</td></tr>
|
|
359
|
-
<tr><td><strong>Emulator</strong> / <strong>Simulator</strong></td><td>A pretend phone that runs <em>on your computer</em> in a window, so you don't need a physical phone plugged in. "Emulator" = Android; "Simulator" = iPhone/iPad.</td></tr>
|
|
360
|
-
<tr><td><strong>AVD</strong></td><td>"Android Virtual Device" — one specific pretend Android phone you've created (e.g. a Pixel running Android 14).</td></tr>
|
|
361
|
-
<tr><td><strong>SDK</strong></td><td>The official toolkit from Google (Android) or Apple (iPhone) for building and running their apps.</td></tr>
|
|
362
|
-
<tr><td><strong>WSL</strong></td><td>The Linux environment inside your Windows PC where the AI (Claude Code) actually runs.</td></tr>
|
|
363
|
-
<tr><td><strong>Endpoint / URL</strong></td><td>An address like <code>http://localhost:4723</code> that the AI uses to reach the remote control. <code>localhost</code> means "this same computer".</td></tr>
|
|
364
|
-
<tr><td><strong>Terminal</strong> / <strong>PowerShell</strong></td><td>A text window where you type commands. On Windows it's "PowerShell" or "Terminal"; on Mac it's the "Terminal" app; inside WSL it's your Ubuntu window.</td></tr>
|
|
365
|
-
</table>
|
|
366
|
-
|
|
367
|
-
<h3>What you'll need first</h3>
|
|
368
|
-
<ul>
|
|
369
|
-
<li><strong>For Android testing:</strong> a Windows PC, plus <strong>Android Studio</strong> (the free Google app — the easiest way to get the Android toolkit, a pretend phone, and the emulator all at once) and <strong>Node.js</strong> (free, from <code>nodejs.org</code> — it provides the <code>npm</code> command used to install Appium).</li>
|
|
370
|
-
<li><strong>For iPhone / iPad / Mac-desktop testing:</strong> a <strong>Mac computer on the same Wi-Fi/network</strong> as your PC, with <strong>Xcode</strong> (free from the Mac App Store) and <strong>Node.js</strong>. This is the same Mac used to build Apple apps.</li>
|
|
371
|
-
<li>Permission to install software (you may be asked for your password), and an internet connection for the downloads.</li>
|
|
372
|
-
</ul>
|
|
373
|
-
|
|
374
|
-
<div class="panel"><strong>How the pieces fit:</strong> the pretend phone and its remote control run <em>where that platform lives</em> — Android on your <strong>Windows PC</strong>, iPhone/iPad and Mac-desktop on the <strong>Mac</strong>. The AI just needs the <em>address</em> to reach each one; it never needs the phone tools installed in its own Linux environment. Builds are unaffected — this only adds the AI's ability to <em>watch</em> the running app.</div>
|
|
375
|
-
|
|
376
|
-
<div class="panel"><strong>Running Claude Code natively on a Mac?</strong> Then everything in this section collapses onto the one machine: Android Studio + the emulator + Appium run locally, and the "paired Mac" for iPhone/iPad and Mac-desktop testing <em>is this same machine</em>. Do Step 3 (and Step 2's Android pieces if the app has an Android head) in the Mac's own Terminal, skip the WSL mirrored-networking step entirely, and use <code>http://localhost:4723</code> for every head in <code>core-config.yaml</code> — no fixed LAN address needed.</div>
|
|
377
|
-
|
|
378
|
-
<h3>Step 1 — let the AI reach the Android remote control (Windows only, once)</h3>
|
|
379
|
-
<p>By default the AI's Linux environment and the rest of Windows don't share the same network address. Turning on "mirrored networking" makes them share <code>localhost</code>, so the AI can reach the Android remote control with a simple address. Create or edit the file <code>.wslconfig</code> in your user folder (its full path is <code>%UserProfile%\.wslconfig</code> — paste that into the File Explorer address bar) and put these two lines in it:</p>
|
|
380
|
-
<pre><code class="lang-ini">[wsl2]
|
|
381
|
-
networkingMode=mirrored</code></pre>
|
|
382
|
-
<p>Save it, then open <strong>PowerShell</strong> (click Start, type "PowerShell", press Enter) and run <code>wsl --shutdown</code>. Close and reopen your WSL window. <span class="small">(Skip this step if you're only setting up Apple testing.)</span></p>
|
|
383
|
-
|
|
384
|
-
<h3>Step 2 — set up the Android pretend-phone + remote control (on the Windows PC)</h3>
|
|
385
|
-
<p><strong>Easiest way (clicking):</strong> install <strong>Android Studio</strong>, open its <em>Device Manager</em>, and click "Create device" to make a pretend phone (e.g. a Pixel with Android 14). Android Studio installs the Android toolkit for you. Then install the remote control by opening <strong>PowerShell</strong> and running the two <code>appium</code> lines below.</p>
|
|
386
|
-
<p><strong>Command way (does the same thing):</strong> in <strong>PowerShell</strong>:</p>
|
|
387
|
-
<pre><code class="lang-powershell"># create a pretend Android phone (an "AVD")
|
|
388
|
-
sdkmanager "system-images;android-34;google_apis;x86_64"
|
|
389
|
-
avdmanager create avd -n Pixel_API_34 -k "system-images;android-34;google_apis;x86_64"
|
|
390
|
-
|
|
391
|
-
# install the remote control (Appium) and its Android adapter
|
|
392
|
-
npm install -g appium
|
|
393
|
-
appium driver install uiautomator2</code></pre>
|
|
394
|
-
<p>Finally, save a tiny helper file named <code>start-android-verify.ps1</code> (the AI runs this itself to switch the phone + remote control on when it tests). It contains:</p>
|
|
395
|
-
<pre><code class="lang-powershell">Start-Process emulator -ArgumentList "-avd Pixel_API_34 -no-snapshot -no-boot-anim"
|
|
396
|
-
Start-Process appium -ArgumentList "--address 0.0.0.0 --port 4723"</code></pre>
|
|
397
|
-
<p class="small">If you used a different phone name in Android Studio, use that name instead of <code>Pixel_API_34</code> here and in the settings file in Step 4.</p>
|
|
398
|
-
|
|
399
|
-
<h3>Step 3 — set up Apple (iPhone/iPad + Mac desktop) testing (on the Mac)</h3>
|
|
400
|
-
<p>On the <strong>Mac</strong> (which must be on the same network as your PC), open the <strong>Terminal</strong> app and install the remote control plus the Apple adapters:</p>
|
|
401
|
-
<pre><code class="lang-bash">npm install -g appium
|
|
402
|
-
appium driver install xcuitest # for the iPhone/iPad simulator
|
|
403
|
-
appium driver install mac2 # for the Mac desktop app
|
|
404
|
-
appium --address 0.0.0.0 --port 4723 # start the remote control (leave this running while testing)</code></pre>
|
|
405
|
-
<p>Give the Mac a <strong>fixed network address</strong> so the AI always finds it (in your Wi-Fi router, reserve an IP for the Mac — search "DHCP reservation" for your router model). Note that address down; you'll put it in Step 4. <span class="small">(Skip this step if you're only setting up Android.)</span></p>
|
|
406
|
-
|
|
407
|
-
<h3>Step 4 — tell the app where the remote controls are</h3>
|
|
408
|
-
<p>Each app keeps its settings in a file called <code>core-config.yaml</code>. Add a <code>runtimeVerification.appium</code> section listing only the platforms <em>this</em> app runs on. The AI reads this automatically; if a platform isn't listed (or can't be reached), the AI simply marks that platform's screens "not visually checked" rather than pretending they passed.</p>
|
|
409
|
-
<p class="small"><strong>WSL-on-Windows setup (Android on this PC, Apple on the LAN Mac):</strong></p>
|
|
410
|
-
<pre><code class="lang-yaml">runtimeVerification:
|
|
411
|
-
appium:
|
|
412
|
-
android: { url: http://localhost:4723, avd: Pixel_API_34, launch: 'winrun "powershell -File start-android-verify.ps1"' }
|
|
413
|
-
ios: { url: http://192.168.1.50:4723, simulator: "iPhone 15" }
|
|
414
|
-
maccatalyst: { url: http://192.168.1.50:4723 }</code></pre>
|
|
415
|
-
<p class="small"><strong>macOS-native setup (everything on this Mac — no winrun, no LAN address):</strong></p>
|
|
416
|
-
<pre><code class="lang-yaml">runtimeVerification:
|
|
417
|
-
appium:
|
|
418
|
-
android: { url: http://localhost:4723, avd: Pixel_API_34 }
|
|
419
|
-
ios: { url: http://localhost:4723, simulator: "iPhone 15" }
|
|
420
|
-
maccatalyst: { url: http://localhost:4723 }</code></pre>
|
|
421
|
-
<p class="small">Use the block for the machine the AI runs on. On WSL: replace <code>192.168.1.50</code> with your Mac's actual address from Step 3 and keep <code>localhost</code> for Android (that's "this PC"). Remove any platform the app doesn't have.</p>
|
|
422
|
-
|
|
423
|
-
<div class="panel ok"><strong>Check it works:</strong> in your WSL window, type <code>curl http://localhost:4723/status</code> (Android) and <code>curl http://<your-mac-address>:4723/status</code> (Apple); on a Mac-native setup it's <code>curl http://localhost:4723/status</code> for everything. If you see something containing <code>"ready":true</code>, the remote control is reachable — you're done. From now on the AI turns the pretend phone on, takes screenshots, and checks each screen by itself; you don't run anything.</div>
|
|
424
|
-
|
|
425
|
-
<div class="panel warn"><strong>If something doesn't work:</strong>
|
|
426
|
-
<ul class="small">
|
|
427
|
-
<li><strong>"command not found" for <code>sdkmanager</code>/<code>avdmanager</code>/<code>emulator</code>:</strong> these come with Android Studio but may not be on your command path — easiest fix is to create the pretend phone by clicking inside Android Studio's Device Manager instead.</li>
|
|
428
|
-
<li><strong>"command not found" for <code>npm</code> or <code>appium</code>:</strong> install <strong>Node.js</strong> first (from <code>nodejs.org</code>), then re-run the <code>npm install -g appium</code> line.</li>
|
|
429
|
-
<li><strong>The <code>curl</code> check fails for Android:</strong> make sure Step 1 (mirrored networking) was done and you reopened WSL, and that the emulator + Appium are actually running (run <code>start-android-verify.ps1</code> once to start them).</li>
|
|
430
|
-
<li><strong>The <code>curl</code> check fails for Apple:</strong> confirm the Mac is on and on the same Wi-Fi, that <code>appium</code> is still running in its Terminal window, and that you used the Mac's correct address.</li>
|
|
431
|
-
<li><strong>The AI says a screen is "STATIC-ONLY":</strong> that just means it couldn't reach that platform's remote control this time (e.g. the Mac was off) — it's being honest, not failing. Bring the device host up and ask it to verify again.</li>
|
|
432
|
-
</ul></div>
|
|
433
|
-
|
|
434
|
-
<p class="small"><strong>One more thing for whoever writes the app's screens:</strong> each important button, list, and value should be given a stable name (an <code>AutomationId</code>) so the AI can find it reliably — this is part of the coding standards (see §10). The AI handles this when it builds; you don't need to.</p>
|
|
435
|
-
|
|
436
|
-
<!-- ============================================================ -->
|
|
437
|
-
<h2 id="overview">1. Overview & principles<span class="anchor-link"><a href="#overview">#</a></span></h2>
|
|
438
|
-
|
|
439
|
-
<div class="grid3">
|
|
440
|
-
<div class="panel">
|
|
441
|
-
<h4>Compress, don't expand</h4>
|
|
442
|
-
<p class="small">No story-by-story TechieFlow. One BRD + one Architecture + one Coding-Standards doc (all human-readable) feed the unified <code>build-phase</code> — which reads ONE AI-only doc (the app Checklist) and calls the library agents (<code>/trblazeui</code>, <code>/techierag</code>) as sub-agents.</p>
|
|
443
|
-
</div>
|
|
444
|
-
<div class="panel">
|
|
445
|
-
<h4>Verify, don't trust</h4>
|
|
446
|
-
<p class="small">The <code>build-phase</code> self-smokes (data + visual) and then chains <code>verifier</code>. Headless Playwright + <code>dotnet test</code>, with a data-render gate AND a visual-truth gate. Verdicts written into the checklist's Requirements Status table.</p>
|
|
447
|
-
</div>
|
|
448
|
-
<div class="panel">
|
|
449
|
-
<h4>Standards enforced from day 1</h4>
|
|
450
|
-
<p class="small">Every project has <code>docs/<APP>-Coding-Standards.md</code>. Every implementation agent prompt references it. <code>CLAUDE.md</code> at project root pins it for auto-load.</p>
|
|
451
|
-
</div>
|
|
452
|
-
</div>
|
|
453
|
-
|
|
454
|
-
<div class="panel ok">
|
|
455
|
-
<strong>Core idea:</strong> Requirements get IDs (<code>REQ-UI-*</code>, <code>REQ-FN-*</code>, <code>REQ-RAG-*</code>, <code>REQ-NFR-*</code>) in ONE checklist. Implementing agents reference IDs in commits and follow <code><APP>-Coding-Standards.md</code>. <code>verifier</code> maps IDs → test evidence (data + visual gates), written into the checklist's single Requirements Status table. Nothing is "done" until every row in that table is green.
|
|
456
|
-
</div>
|
|
457
|
-
|
|
458
|
-
<!-- ============================================================ -->
|
|
459
|
-
<h2 id="painpoints">2. Pain points → solutions<span class="anchor-link"><a href="#painpoints">#</a></span></h2>
|
|
460
|
-
|
|
461
|
-
<div class="pain">
|
|
462
|
-
<div class="p"><h4>1. Agents miss requirements; verify-fix loop is exhausting</h4></div>
|
|
463
|
-
<div class="s"><h4>→ <code>verifier</code> mandatory + ID-driven; chain in same prompt</h4></div>
|
|
464
|
-
</div>
|
|
465
|
-
<div class="pain">
|
|
466
|
-
<div class="p"><h4>2. WSL has no GUI browser; Playwright MCP eats context</h4></div>
|
|
467
|
-
<div class="s"><h4>→ Headless Playwright CLI from §0 bootstrap</h4></div>
|
|
468
|
-
</div>
|
|
469
|
-
<div class="pain">
|
|
470
|
-
<div class="p"><h4>3. Can't build/run MAUI from WSL</h4></div>
|
|
471
|
-
<div class="s"><h4>→ <code>winrun</code> WSL→Windows bridge (§9)</h4></div>
|
|
472
|
-
</div>
|
|
473
|
-
<div class="pain">
|
|
474
|
-
<div class="p"><h4>4. Hard to scan markdown on cold re-entry</h4></div>
|
|
475
|
-
<div class="s"><h4>→ <code><APP>-BRD.html</code> + <code><APP>-Architecture.html</code> + <code>PROJECT-STATUS.html</code> with Mermaid (§6 + §11)</h4></div>
|
|
476
|
-
</div>
|
|
477
|
-
<div class="pain">
|
|
478
|
-
<div class="p"><h4>5. <code>npx techieflow install</code> grabs v6, breaks customizations</h4></div>
|
|
479
|
-
<div class="s"><h4>→ <code>scaffold-brownfield.sh</code> / <code>scaffold-greenfield.sh</code> copy your v4 setup (§3)</h4></div>
|
|
480
|
-
</div>
|
|
481
|
-
<div class="pain">
|
|
482
|
-
<div class="p"><h4>6. Claude Code prompts every Bash; <code>*yolo</code> doesn't help; a VM goal run waits days on delete prompts, git-read blocks and usage limits</h4></div>
|
|
483
|
-
<div class="s"><h4>→ Pre-built <code>.claude/settings.json</code> (§12)</h4></div>
|
|
484
|
-
</div>
|
|
485
|
-
<div class="pain">
|
|
486
|
-
<div class="p"><h4>7. Generated code uses inconsistent style across projects</h4></div>
|
|
487
|
-
<div class="s"><h4>→ <code><APP>-Coding-Standards.md</code> per project, referenced in every impl prompt; <code>CLAUDE.md</code> pin</h4></div>
|
|
488
|
-
</div>
|
|
489
|
-
<div class="pain">
|
|
490
|
-
<div class="p"><h4>8. Agents excuse themselves from smoke-testing ("can't run on Linux / it targets Windows / it's MAUI / Playwright needs a GUI")</h4></div>
|
|
491
|
-
<div class="s"><h4>→ <code>_smoke-test-policy.md</code>: those are <strong>banned excuses</strong> — headless Playwright + the Windows/MAUI bridge are already set up (§0). Every change is self-smoked by the agent before the verifier; the user is asked to boot only after the build ladder genuinely fails. "It runs" means controls <strong>render their data</strong>, not just HTTP 200.</h4></div>
|
|
492
|
-
</div>
|
|
493
|
-
<div class="pain">
|
|
494
|
-
<div class="p"><h4>9. Smoke/verify runs pollute the DB with random throwaway test users</h4></div>
|
|
495
|
-
<div class="s"><h4>→ <code>_smoke-test-policy.md</code>: use the canonical test accounts in <code><APP>-UsageGuide.md</code> (or look them up in the DB via the connection string); never auto-create — ask the owner to confirm, then record the account in the UsageGuide.</h4></div>
|
|
496
|
-
</div>
|
|
497
|
-
<div class="pain">
|
|
498
|
-
<div class="p"><h4>10. The data + visual gates only reached Blazor + the MAUI Windows head — Android/iOS/Mac-desktop screens were build-only (never run/observed)</h4></div>
|
|
499
|
-
<div class="s"><h4>→ <strong>Appium runtime bridge (§0b)</strong>: the verifier drives MAUI <strong>Android</strong> (emulator on the Windows host), <strong>iOS</strong> (Simulator on a LAN Mac), and <strong>Mac Catalyst</strong> (same Mac) over an HTTP WebDriver endpoint that returns the same screenshot + element tree, so the §4a/§4b gates run unchanged. Endpoints live in <code>core-config.yaml → runtimeVerification.appium</code>; an unreachable host degrades that head to <code>⚠ STATIC-ONLY</code>, never a faked pass.</h4></div>
|
|
500
|
-
</div>
|
|
501
|
-
|
|
502
|
-
<!-- ============================================================ -->
|
|
503
|
-
<h2 id="scaffolding">3. Scaffolding a new project — copy, don't npm-install<span class="anchor-link"><a href="#scaffolding">#</a></span></h2>
|
|
504
|
-
<div class="callout info"><strong>Codex adapter.</strong> Both scaffolders and the updater deploy <code>.codex/</code> (config, custom agents, hooks and rules) and <code>.agents/skills/</code> (TechieFlow workflows). Trust the repository and review <code>/hooks</code> after installation. Invoke <code>$techieflow-build</code>, <code>$techieflow-verify</code>, or another generated skill. Use <code>tf-goal.sh --harness codex</code> for unattended local work; full winrun/Appium verification requires a local Codex environment.</div>
|
|
505
|
-
|
|
506
|
-
<p>You have a customized v4 setup. <code>npx techieflow install</code> would fetch v6 and lose your customizations. Use the scaffold script:</p>
|
|
507
|
-
|
|
508
|
-
<p>Three scripts: two scaffolders (one per flow) plus an updater for projects scaffolded earlier. All are idempotent (scaffolders use rsync <code>--ignore-existing</code> — existing files preserved on re-run; the updater force-refreshes framework files including <code>.claude/settings.json</code>, see <a href="#update-framework">below</a>).</p>
|
|
509
|
-
|
|
510
|
-
<h3>Brownfield (existing app) — <code>scaffold-brownfield.sh</code></h3>
|
|
511
|
-
<p class="small"><strong>WSL (Windows):</strong></p>
|
|
512
|
-
<pre><code class="lang-bash">cd /path/to/existing-app
|
|
513
|
-
/mnt/c/3AIGenCode/TechieFlow/scaffold-brownfield.sh .</code></pre>
|
|
514
|
-
<p class="small"><strong>macOS:</strong></p>
|
|
515
|
-
<pre><code class="lang-bash">cd /path/to/existing-app
|
|
516
|
-
/Volumes/MacD/MyCode/TechieFlow/scaffold-brownfield.sh .</code></pre>
|
|
517
|
-
|
|
518
|
-
<p>Adds <code>.tfcore/</code>, <code>.claude/commands/</code>, <code>.opencode/</code>, <code>.codex/</code>, <code>.agents/skills/</code>, <code>WORKFLOW.html</code>, <code>opencode.jsonc</code>, and <code>.claude/settings.json</code>. <strong>Does NOT touch</strong> existing <code>src/</code>, <code>tests/</code>, or other <code>docs/</code> contents. Warns (non-blocking) if no <code>.csproj</code>/<code>.sln</code> found within 4 levels. Refuses if the target directory doesn't exist (use greenfield script for that). (No <code>.opencode/command/TechieFlow/</code> mirror is deployed — OpenCode loads agents/tasks from <code>opencode.jsonc</code> <code>{file:./.tfcore/...}</code> references instead.)</p>
|
|
519
|
-
|
|
520
|
-
<h3>Greenfield (new app) — <code>scaffold-greenfield.sh</code></h3>
|
|
521
|
-
<p class="small"><strong>WSL (Windows):</strong></p>
|
|
522
|
-
<pre><code class="lang-bash">mkdir /path/to/my-new-app && cd /path/to/my-new-app
|
|
523
|
-
git init
|
|
524
|
-
/mnt/c/3AIGenCode/TechieFlow/scaffold-greenfield.sh .</code></pre>
|
|
525
|
-
<p class="small"><strong>macOS:</strong></p>
|
|
526
|
-
<pre><code class="lang-bash">mkdir /path/to/my-new-app && cd /path/to/my-new-app
|
|
527
|
-
git init
|
|
528
|
-
/Volumes/MacD/MyCode/TechieFlow/scaffold-greenfield.sh .</code></pre>
|
|
529
|
-
<p class="small"><strong>Then, on either machine:</strong></p>
|
|
530
|
-
<pre><code class="lang-bash">dotnet new sln -n MyNewApp
|
|
531
|
-
dotnet new blazor -n MyNewApp.Web -o src/MyNewApp.Web
|
|
532
|
-
dotnet sln add src/MyNewApp.Web
|
|
533
|
-
dotnet add src/MyNewApp.Web package TrBlazeUI # if UI involved
|
|
534
|
-
dotnet add src/MyNewApp.Web package TechieRag # if AI/RAG involved
|
|
535
|
-
dotnet build # deploys library agent files</code></pre>
|
|
536
|
-
|
|
537
|
-
<p>Same framework drop as brownfield, plus creates empty <code>src/</code>, <code>tests/playwright/</code>, <code>tests/unit/</code> folders ready for use.</p>
|
|
538
|
-
|
|
539
|
-
<div class="panel">
|
|
540
|
-
<strong>What neither script creates:</strong> per-project doc files (BRD, Architecture, Coding Standards, the Checklist, etc.). Those are produced by <code>/analyst</code> on day 1 of the workflow (§7 step 1). Both scripts also exclude the library-deployed agent files (<code>trblazeui.md</code>, <code>techierag.md</code>) — those land via <code>dotnet build</code> after you add the NuGet packages.
|
|
541
|
-
</div>
|
|
542
|
-
|
|
543
|
-
<h3 id="update-framework">Updating an already-scaffolded project — <code>update-framework.sh</code></h3>
|
|
544
|
-
|
|
545
|
-
<p>When the reference framework repo (WSL: <code>/mnt/c/3AIGenCode/TechieFlow</code> · macOS: <code>/Volumes/MacD/MyCode/TechieFlow</code>) evolves (new tasks, updated templates, agent fixes), pull those changes into an existing project with the updater. Unlike the scaffolders (<code>--ignore-existing</code>: never touch a file that's already there), the updater <strong>force-overwrites framework files</strong> and preserves everything that contains your work product. The scripts self-locate — invoke whichever machine's copy you're on and it uses itself as the source.</p>
|
|
546
|
-
|
|
547
|
-
<p class="small"><strong>WSL (Windows):</strong></p>
|
|
548
|
-
<pre><code class="lang-bash"># Preview what would change (recommended first):
|
|
549
|
-
/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/your-app --dry-run
|
|
550
|
-
|
|
551
|
-
# Apply:
|
|
552
|
-
/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/your-app
|
|
553
|
-
|
|
554
|
-
# Or run from inside the project (defaults to $PWD):
|
|
555
|
-
cd /path/to/your-app
|
|
556
|
-
/mnt/c/3AIGenCode/TechieFlow/update-framework.sh</code></pre>
|
|
557
|
-
<p class="small"><strong>macOS:</strong></p>
|
|
558
|
-
<pre><code class="lang-bash"># Preview what would change (recommended first):
|
|
559
|
-
/Volumes/MacD/MyCode/TechieFlow/update-framework.sh /path/to/your-app --dry-run
|
|
560
|
-
|
|
561
|
-
# Apply:
|
|
562
|
-
/Volumes/MacD/MyCode/TechieFlow/update-framework.sh /path/to/your-app
|
|
563
|
-
|
|
564
|
-
# Or run from inside the project (defaults to $PWD):
|
|
565
|
-
cd /path/to/your-app
|
|
566
|
-
/Volumes/MacD/MyCode/TechieFlow/update-framework.sh</code></pre>
|
|
567
|
-
|
|
568
|
-
<p>Note: the script is NOT on your PATH — always invoke it with the full path shown above (a bare <code>update-framework.sh</code> gives <em>"command not found"</em>). Optional alias — WSL: <code>echo "alias update-framework.sh='/mnt/c/3AIGenCode/TechieFlow/update-framework.sh'" >> ~/.bashrc</code> · macOS (zsh): <code>echo "alias update-framework.sh='/Volumes/MacD/MyCode/TechieFlow/update-framework.sh'" >> ~/.zshrc</code>.</p>
|
|
569
|
-
|
|
570
|
-
<table>
|
|
571
|
-
<tr><th>Force-overwritten (framework — reference repo wins)</th><th>Preserved (your work product — never touched)</th></tr>
|
|
572
|
-
<tr>
|
|
573
|
-
<td><code>.tfcore/{tasks,templates,agents,checklists,data,utils,workflows,agent-teams}/</code><br>
|
|
574
|
-
<code>.claude/commands/TechieFlow/</code> subtree<br>
|
|
575
|
-
<code>.claude/commands/*.md</code> top-level commands (generate-html etc.)<br>
|
|
576
|
-
<code>.opencode/command/*.md</code> top-level commands (generate-html etc.)<br>
|
|
577
|
-
<code>WORKFLOW.html</code><br>
|
|
578
|
-
<code>.claude/settings.json</code> (refreshed to canonical config by default; old file → <code>settings.json.bak</code>; <code>--keep-permissions</code> to skip; <code>settings.local.json</code> never touched)</td>
|
|
579
|
-
<td><code>docs/</code>, <code>src/</code>, <code>tests/</code><br>
|
|
580
|
-
<code>PROJECT-STATUS.md</code>, <code>CLAUDE.md</code>, <code>.editorconfig</code><br>
|
|
581
|
-
<code>.tfcore/core-config.yaml</code><br>
|
|
582
|
-
<code>opencode.jsonc</code><br>
|
|
583
|
-
<code>.claude/{trblazeui,techierag}.md</code> + <code>.opencode/command/{trblazeui,techierag}.md</code> (NuGet-deployed)</td>
|
|
584
|
-
</tr>
|
|
585
|
-
</table>
|
|
586
|
-
|
|
587
|
-
<p>The scaffolders and the updater also <strong>ensure the project's <code>.gitignore</code> ignores the deployed framework copies</strong> (<code>.tfcore/</code>, <code>.claude/</code>, <code>.opencode/</code>, <code>.codex/</code>, <code>.agents/skills/</code>, <code>/CLAUDE.md</code>, <code>/WORKFLOW.html</code>, <code>/opencode.jsonc</code>, <code>/.tf-scaffold-note.txt</code>) — everything the framework drops into an app is a <em>copy</em> (source of truth: the reference repo, or the NuGet package for the library personas) and must never be committed in the app repo. The step is append-only and idempotent: your own <code>.gitignore</code> entries are respected, nothing is removed. Note git never <em>un</em>tracks a file just because it became ignored — if a framework file was committed before the entry existed, run <code>git rm -r --cached <path></code> once yourself (git is manual in TechieFlow; agents never run it).</p>
|
|
588
|
-
|
|
589
|
-
<p>They also manage a second block — <strong>agent test-harness & log artifacts</strong> (<code>node_modules/</code>, <code>/package.json</code>, <code>/package-lock.json</code>, <code>tests/.artifacts/</code>, <code>test-results/</code>, <code>test-results-*/</code>, <code>/scripts-*/</code>, <code>playwright-report/</code>, <code>.verify/</code>, <code>logs/</code>, <code>/docs/.last-verify.json</code>, <code>.DS_Store</code>). These are machine-generated by the verifier's npm/Playwright self-provisioning (verify-phase §1) and the standing Serilog default, and are fully regenerable — <strong>you should never have to triage them at commit time</strong>. verify-phase §1 also self-heals the block whenever it provisions, so even a project scaffolded before this block existed gets it on its next verify. <code>playwright.config.ts</code> deliberately stays <em>tracked</em> — committed test suites depend on it. Same caveat as above: already-tracked artifacts need a one-time <code>git rm -r --cached <path></code> from you.</p>
|
|
590
|
-
|
|
591
|
-
<p><strong>Where test artifacts live — <code>tests/.artifacts/</code>, never the repo root</strong> (rule added 2026-08-10). Screenshots, traces, videos and Playwright/Appium output are <em>failure evidence with a session lifetime</em>, not work product: they exist so a verify run can cite a path in a checklist Remark, and Playwright wipes the directory at the start of the next run. verify-phase §1 now pins <code>outputDir: './tests/.artifacts/test-results'</code> in <code>playwright.config.ts</code> — creating the config if absent and <strong>editing it if it lacks the setting</strong> — and bans the two habits that used to litter app repos: a repo-root <code>test-results/</code>, and per-cluster siblings like <code>test-results-cluster-a/</code> from a fan-out passing <code>--output test-results-<slug></code>. Those siblings were the real damage: <code>test-results/</code> does not match <code>test-results-cluster-a/</code>, so they were never ignored, they surfaced untracked at every commit, and they accumulated one directory per run (TechieBlog reached fourteen). If a parallel run genuinely needs isolation, the only permitted form is a subfolder — <code>--output tests/.artifacts/<slug></code>. The bare <code>test-results/</code> and the <code>test-results-*/</code> glob stay in the ignore block purely to cover legacy trees; a compliant run writes neither, and verify-phase §1 deletes any it finds at the repo root on its next pass. Deliberately tracked screenshots — the DevGuide's reviewed set under <code>docs/screenshots/<APP>/</code> — are untouched by all of this.</p>
|
|
592
|
-
|
|
593
|
-
<p><strong>The rule covers the harness too, not just its output</strong> (extended 2026-08-10). The first version of this rule pinned where the <em>tools write</em> and said nothing about where the agent <em>puts the scripts it writes</em> — so the next fan-out stopped creating <code>test-results-cluster-a/</code> and created <code>scripts-cluster-b/</code> instead: same defect, different noun, same four untracked folders in your commit view. A throwaway smoke/verify/load/cleanup script an agent authors for a run is scratch, and it now lands in <strong><code>tests/.artifacts/harness/</code></strong>, named per cluster <em>inside</em> that folder. Two things follow. Your project's own <strong><code>scripts/</code></strong> — release, publish, dev-setup scripts you track and own — is off limits to agents in both directions: nothing writes a run harness into it, and no sweep ever deletes it (the ignore entry is <code>/scripts-*/</code>, which requires the hyphen and the root anchor, so plain <code>scripts/</code> can never match). And a harness that does <code>import { chromium } from 'playwright'</code> drives the <strong>library</strong>, not the test runner — it never loads <code>playwright.config.ts</code>, so <code>outputDir</code> does not apply and nothing wipes what it writes; such a script must place its own captures under <code>tests/.artifacts/</code> and must never hardcode an absolute path. The general lesson, worth stating because the first fix missed it: a location rule has to name the <em>class of thing</em> (everything this run generates that is not a deliverable), not the specific filenames a tool happened to default to.</p>
|
|
594
|
-
|
|
595
|
-
<div class="panel warn">
|
|
596
|
-
<strong>After every update: restart Claude Code</strong> in that project. New/changed tasks and agents under <code>.claude/commands/TechieFlow/</code> are only registered as skills at session start — without a restart, a freshly-synced command like <code>/TechieFlow:tasks:generate-html</code> won't resolve.
|
|
597
|
-
</div>
|
|
598
|
-
|
|
599
|
-
<!-- ============================================================ -->
|
|
600
|
-
<h2 id="naming">4. File-naming convention — <span class="placeholder"><APP></span> prefix<span class="anchor-link"><a href="#naming">#</a></span></h2>
|
|
601
|
-
|
|
602
|
-
<p>Every per-project document filename starts with the application name. Examples from the user's existing projects: <code>AppManager-Coding-Standards.md</code>, <code>AstroLyfe-Coding-Standards.md</code>. Same convention applies to every doc:</p>
|
|
603
|
-
|
|
604
|
-
<table>
|
|
605
|
-
<tr><th>Pattern</th><th>Example for app "AppManager"</th><th>Example for app "AstroLyfe"</th></tr>
|
|
606
|
-
<tr><td><code><APP>-BRD.md</code> / <code>.html</code></td><td><code>AppManager-BRD.md</code></td><td><code>AstroLyfe-BRD.md</code></td></tr>
|
|
607
|
-
<tr><td><code><APP>-Architecture.md</code> / <code>.html</code></td><td><code>AppManager-Architecture.md</code></td><td><code>AstroLyfe-Architecture.md</code></td></tr>
|
|
608
|
-
<tr><td><code><APP>-Coding-Standards.md</code></td><td><code>AppManager-Coding-Standards.md</code></td><td><code>AstroLyfe-Coding-Standards.md</code></td></tr>
|
|
609
|
-
<tr><td><code><APP>-Checklist.md</code> (ONE per app — all REQ-UI/FN/RAG/NFR-*)</td><td><code>AppManager-Checklist.md</code></td><td><code>AstroLyfe-Checklist.md</code></td></tr>
|
|
610
|
-
<tr><td><code><APP>-UIDesign.md</code> (greenfield mockups spec)</td><td><code>AppManager-UIDesign.md</code></td><td><code>AstroLyfe-UIDesign.md</code></td></tr>
|
|
611
|
-
<tr><td><code><APP>-<Library>-Feedback.md</code> (one per library)</td><td><code>AppManager-TrBlazeUI-Feedback.md</code></td><td><code>AstroLyfe-TechieRag-Feedback.md</code></td></tr>
|
|
612
|
-
<tr><td><code><APP>-UsageGuide.md</code></td><td><code>AppManager-UsageGuide.md</code></td><td><code>AstroLyfe-UsageGuide.md</code></td></tr>
|
|
613
|
-
<tr><td><code><APP>-DevGuide.md</code> (developer code-map)</td><td><code>AppManager-DevGuide.md</code></td><td><code>AstroLyfe-DevGuide.md</code></td></tr>
|
|
614
|
-
<tr><td><code><APP>-ProductGuide.md</code> (end-user how-to manual)</td><td><code>AppManager-ProductGuide.md</code></td><td><code>AstroLyfe-ProductGuide.md</code></td></tr>
|
|
615
|
-
</table>
|
|
616
|
-
|
|
617
|
-
<p>Throughout this document, <span class="placeholder"><APP></span> is a placeholder. When you paste a prompt to an agent, substitute it with your actual application name (no spaces; use PascalCase to match the user's two existing samples).</p>
|
|
618
|
-
|
|
619
|
-
<p>Files that stay generic (not <code><APP></code>-prefixed):</p>
|
|
620
|
-
<ul class="tight">
|
|
621
|
-
<li><code>PROJECT-STATUS.md</code> / <code>.html</code> — one per repo, project-name is in its content</li>
|
|
622
|
-
<li><code>CLAUDE.md</code> — Claude Code's auto-loaded session memory; one per repo</li>
|
|
623
|
-
<li><code>WORKFLOW.html</code> — this file; identical across projects</li>
|
|
624
|
-
</ul>
|
|
625
|
-
|
|
626
|
-
<!-- ============================================================ -->
|
|
627
|
-
<h2 id="structure">5. Project structure<span class="anchor-link"><a href="#structure">#</a></span></h2>
|
|
628
|
-
|
|
629
|
-
<pre><code>your-app/ ← e.g. AppManager/
|
|
630
|
-
├── PROJECT-STATUS.md ← /analyst (day 1)
|
|
631
|
-
├── PROJECT-STATUS.html ← /flow-master after each phase
|
|
632
|
-
├── CLAUDE.md ← /analyst (day 1) — pins coding standards
|
|
633
|
-
├── WORKFLOW.html ← from scaffold
|
|
634
|
-
│
|
|
635
|
-
├── .tfcore/ ← from scaffold (your customized v4)
|
|
636
|
-
├── .claude/
|
|
637
|
-
│ ├── commands/TechieFlow/... ← from scaffold
|
|
638
|
-
│ ├── settings.json ← from scaffold (yolo-except-git-writes)
|
|
639
|
-
│ ├── trblazeui.md ← from `dotnet build` (TrBlazeUI NuGet)
|
|
640
|
-
│ └── techierag.md ← from `dotnet build` (TechieRag NuGet)
|
|
641
|
-
├── .opencode/command/
|
|
642
|
-
│ ├── generate-html.md ← from scaffold
|
|
643
|
-
│ ├── trblazeui.md ← from dotnet build
|
|
644
|
-
│ └── techierag.md ← from dotnet build
|
|
645
|
-
├── .trblazeui/TrBlazeUI-AI-Reference.md ← from dotnet build
|
|
646
|
-
├── .techierag/TechieRag-AI-Reference.md ← from dotnet build
|
|
647
|
-
│
|
|
648
|
-
├── .editorconfig ← /analyst (day 1) — machine-checkable subset of coding standards
|
|
649
|
-
│
|
|
650
|
-
├── docs/
|
|
651
|
-
│ ├── <APP>-BRD.md ← /analyst — humans + AI
|
|
652
|
-
│ ├── <APP>-BRD.html ← /flow-master renders BRD.md → humans
|
|
653
|
-
│ ├── <APP>-Architecture.md ← /analyst — humans + AI (both flows!)
|
|
654
|
-
│ ├── <APP>-Architecture.html ← /flow-master renders Architecture.md → humans
|
|
655
|
-
│ ├── <APP>-Coding-Standards.md ← /analyst (day 1) — ALL agents follow this
|
|
656
|
-
│ ├── <APP>-Checklist.md ← /analyst (*split-brd) — ONE checklist, all REQ-UI/FN/RAG/NFR-* — AI
|
|
657
|
-
│ ├── <APP>-UIDesign.md ← /analyst (*mockups, greenfield) — per-screen spec + component map — humans
|
|
658
|
-
│ ├── <APP>-UIDesign.html ← rendered for humans
|
|
659
|
-
│ ├── mockups/ ← /analyst (*mockups, greenfield) — rendered *.html screens (TrBlazeUI-styled)
|
|
660
|
-
│ ├── screenshots/<APP>/ ← /flow-master (*devguide OBSERVE — any built app) — per-screen *.png (DevGuide + Product Guide source)
|
|
661
|
-
│ ├── <APP>-TrBlazeUI-Feedback.md ← agents log TrBlazeUI issues — one file PER library
|
|
662
|
-
│ ├── <APP>-TechieRag-Feedback.md ← agents log TechieRag issues — each goes to its team
|
|
663
|
-
│ ├── <APP>-UsageGuide.md ← /flow-master — humans
|
|
664
|
-
│ ├── <APP>-UsageGuide.html ← /flow-master — rendered for humans
|
|
665
|
-
│ ├── <APP>-DevGuide.md ← /flow-master (*devguide) — humans (small app: single doc)
|
|
666
|
-
│ ├── <APP>-DevGuide.html ← /flow-master — rendered for humans
|
|
667
|
-
│ ├── devguides/ ← large app: split per-role DevGuide (index + <APP>-DevGuide-<Role>.md/.html)
|
|
668
|
-
│ ├── <APP>-ProductGuide.md ← /flow-master (*productguide) — END USERS / external (small app: single doc)
|
|
669
|
-
│ ├── <APP>-ProductGuide.html ← /flow-master — rendered for end users
|
|
670
|
-
│ └── productguides/ ← large app: split per-role Product Guide (index + <APP>-ProductGuide-<Role>.md/.html)
|
|
671
|
-
│
|
|
672
|
-
├── tests/{playwright,unit}/ …
|
|
673
|
-
└── src/ …</code></pre>
|
|
674
|
-
|
|
675
|
-
<!-- ============================================================ -->
|
|
676
|
-
<h2 id="docs">6. Doc artifacts & audiences<span class="anchor-link"><a href="#docs">#</a></span></h2>
|
|
677
|
-
|
|
678
|
-
<p class="small"><strong>Agent-facing authoring notes never render.</strong> The doc templates carry drafting-agent instructions (the "Depth mandate" / "Mermaid mandate" notes) as HTML comments, so they are invisible in both the generated <code>.md</code> and the rendered HTML — the human reader must never see them. Docs generated from pre-2026-07 templates may still show them as visible blockquotes; the next HTML render strips them automatically (<code>html-render-shell.md §6b</code>).</p>
|
|
679
|
-
|
|
680
|
-
<table>
|
|
681
|
-
<tr><th>File</th><th>Audience</th><th>Format</th><th>Created by</th><th>Purpose</th></tr>
|
|
682
|
-
<tr>
|
|
683
|
-
<td><code>docs/<APP>-BRD.md</code></td>
|
|
684
|
-
<td><span class="audience h">H</span> <span class="audience a">AI</span></td>
|
|
685
|
-
<td>MD + Mermaid</td>
|
|
686
|
-
<td><code>/analyst</code></td>
|
|
687
|
-
<td>Business Requirements — the WHY.</td>
|
|
688
|
-
</tr>
|
|
689
|
-
<tr>
|
|
690
|
-
<td><code>docs/<APP>-BRD.html</code></td>
|
|
691
|
-
<td><span class="audience h">H</span></td>
|
|
692
|
-
<td>Self-contained HTML</td>
|
|
693
|
-
<td><code>/flow-master</code></td>
|
|
694
|
-
<td>Browseable BRD for stakeholders / future-you.</td>
|
|
695
|
-
</tr>
|
|
696
|
-
<tr>
|
|
697
|
-
<td><code>docs/<APP>-Architecture.md</code></td>
|
|
698
|
-
<td><span class="audience h">H</span> <span class="audience a">AI</span></td>
|
|
699
|
-
<td>MD + Mermaid</td>
|
|
700
|
-
<td><code>/analyst</code> (both flows)</td>
|
|
701
|
-
<td>Brownfield: current architecture + planned deltas. Greenfield: target architecture.</td>
|
|
702
|
-
</tr>
|
|
703
|
-
<tr>
|
|
704
|
-
<td><code>docs/<APP>-Architecture.html</code></td>
|
|
705
|
-
<td><span class="audience h">H</span></td>
|
|
706
|
-
<td>Self-contained HTML</td>
|
|
707
|
-
<td><code>/flow-master</code></td>
|
|
708
|
-
<td>Browseable architecture diagrams.</td>
|
|
709
|
-
</tr>
|
|
710
|
-
<tr>
|
|
711
|
-
<td><code>docs/<APP>-Coding-Standards.md</code></td>
|
|
712
|
-
<td><span class="audience h">H</span> <span class="audience a">AI</span></td>
|
|
713
|
-
<td>Markdown</td>
|
|
714
|
-
<td><code>/analyst</code> (day 1)</td>
|
|
715
|
-
<td>Every implementation agent follows this. Pinned by CLAUDE.md.</td>
|
|
716
|
-
</tr>
|
|
717
|
-
<tr>
|
|
718
|
-
<td><code>docs/<APP>-Checklist.md</code></td>
|
|
719
|
-
<td><span class="audience a">AI</span></td>
|
|
720
|
-
<td>Markdown w/ <code>REQ-UI-*</code>, <code>REQ-FN-*</code>, <code>REQ-RAG-*</code>, <code>REQ-NFR-*</code></td>
|
|
721
|
-
<td><code>/analyst</code> (<code>*split-brd</code>)</td>
|
|
722
|
-
<td>The ONE checklist — every REQ class in a single Requirements Status table. Input for <code>*build-phase</code> (which routes REQ-UI-* to <code>/trblazeui</code> and REQ-RAG-* to <code>/techierag</code> as sub-agents). Scopes (<code>*verify ui|functional|all</code>) filter this one table by REQ prefix. Agent-only working doc — never rendered to HTML.</td>
|
|
723
|
-
</tr>
|
|
724
|
-
<tr>
|
|
725
|
-
<td><code>docs/<APP>-UIDesign.md</code> + <code>.html</code><br><code>docs/mockups/*.html</code></td>
|
|
726
|
-
<td><span class="audience h">H</span></td>
|
|
727
|
-
<td>MD + HTML</td>
|
|
728
|
-
<td><code>/analyst</code> (<code>*mockups</code>, greenfield)</td>
|
|
729
|
-
<td>Per-screen UI Design Spec with a <code>region → TrBlazeUI control</code> component map + rendered TrBlazeUI-styled mockups. Approved with the BRD + Architecture before build; what <code>/trblazeui</code> builds from; the verifier's visual baseline (§4b).</td>
|
|
730
|
-
</tr>
|
|
731
|
-
<tr>
|
|
732
|
-
<td><code>PROJECT-STATUS.md</code> + <code>.html</code></td>
|
|
733
|
-
<td><span class="audience h">H</span> <span class="audience a">AI</span></td>
|
|
734
|
-
<td>MD + HTML</td>
|
|
735
|
-
<td><code>/analyst</code> then <code>/flow-master</code></td>
|
|
736
|
-
<td>Single source of "where am I".</td>
|
|
737
|
-
</tr>
|
|
738
|
-
<tr>
|
|
739
|
-
<td><code>CLAUDE.md</code></td>
|
|
740
|
-
<td><span class="audience a">AI</span></td>
|
|
741
|
-
<td>Markdown</td>
|
|
742
|
-
<td><code>/analyst</code> (day 1)</td>
|
|
743
|
-
<td>Auto-loaded by Claude Code; points to coding standards, BRD, Architecture.</td>
|
|
744
|
-
</tr>
|
|
745
|
-
<tr>
|
|
746
|
-
<td><code>.editorconfig</code></td>
|
|
747
|
-
<td><span class="audience a">AI</span> (toolchain)</td>
|
|
748
|
-
<td>EditorConfig</td>
|
|
749
|
-
<td><code>/analyst</code> (day 1)</td>
|
|
750
|
-
<td>Machine-checkable subset of coding standards (file-scoped namespace, async suffix, no-underscore field naming rule).</td>
|
|
751
|
-
</tr>
|
|
752
|
-
<tr>
|
|
753
|
-
<td>Requirements Status table (inside the one checklist)</td>
|
|
754
|
-
<td><span class="audience a">AI</span> <span class="audience h">H</span></td>
|
|
755
|
-
<td>MD table</td>
|
|
756
|
-
<td>build agents + <code>/verifier</code></td>
|
|
757
|
-
<td>Per-REQ status/%/remarks — single source of truth; REQ ID → PASS/FAIL/Blocked evidence.</td>
|
|
758
|
-
</tr>
|
|
759
|
-
<tr>
|
|
760
|
-
<td><code>docs/<APP>-TrBlazeUI-Feedback.md</code><br><code>docs/<APP>-TechieRag-Feedback.md</code></td>
|
|
761
|
-
<td><span class="audience h">H</span></td>
|
|
762
|
-
<td>Markdown</td>
|
|
763
|
-
<td>All implementing agents</td>
|
|
764
|
-
<td>Issues to ship back to each library's team — <strong>one file per library</strong> (separate codebases, separate teams; each file is handed to its owning team, who use this same framework to fix them).</td>
|
|
765
|
-
</tr>
|
|
766
|
-
<tr>
|
|
767
|
-
<td><code>docs/<APP>-UsageGuide.md</code> + <code>.html</code></td>
|
|
768
|
-
<td><span class="audience h">H</span></td>
|
|
769
|
-
<td>MD + HTML</td>
|
|
770
|
-
<td><code>/flow-master</code></td>
|
|
771
|
-
<td>Final handoff: install, run, test, smoke checklist.</td>
|
|
772
|
-
</tr>
|
|
773
|
-
<tr>
|
|
774
|
-
<td><code>docs/<APP>-DevGuide.md</code> + <code>.html</code><br><small>(large apps: split per role into <code>docs/devguides/<APP>-DevGuide-{Role}.md</code> + index)</small></td>
|
|
775
|
-
<td><span class="audience h">H</span></td>
|
|
776
|
-
<td>MD + HTML</td>
|
|
777
|
-
<td><code>/flow-master</code> (<code>*devguide</code>)</td>
|
|
778
|
-
<td>Developer reference: every screen → control → service method → stored procedure, grouped by user role. Used to trace bugs and verify AI-generated code. Auto-generated at handoff; re-runnable anytime. See <a href="#docs">§6</a>.</td>
|
|
779
|
-
</tr>
|
|
780
|
-
<tr>
|
|
781
|
-
<td><code>docs/<APP>-ProductGuide.md</code> + <code>.html</code><br><small>(large apps: split per role into <code>docs/productguides/<APP>-ProductGuide-{Role}.md</code> + index)</small></td>
|
|
782
|
-
<td><span class="audience h">H</span> (end users / external)</td>
|
|
783
|
-
<td>MD + HTML</td>
|
|
784
|
-
<td><code>/flow-master</code> (<code>*productguide</code>)</td>
|
|
785
|
-
<td>End-user how-to manual: what each screen is for and how to do each task, illustrated with the screenshots captured for the DevGuide. The user-facing sibling of the DevGuide (same screens, different audience). On-demand; <code>--update</code> refreshes changed screens; always emits MD + HTML. See <a href="#docs">§6</a>.</td>
|
|
786
|
-
</tr>
|
|
787
|
-
<tr>
|
|
788
|
-
<td><code>.tfcore/TOKEN-GUIDE.md</code></td>
|
|
789
|
-
<td><span class="audience h">H</span></td>
|
|
790
|
-
<td>Markdown</td>
|
|
791
|
-
<td>framework (ships with scaffold)</td>
|
|
792
|
-
<td>Token-efficiency guide — where AI tokens go and how to keep usage low. See <a href="#quickref">§14</a>.</td>
|
|
793
|
-
</tr>
|
|
794
|
-
</table>
|
|
795
|
-
|
|
796
|
-
<div class="panel">
|
|
797
|
-
<strong>Mermaid in HTML.</strong> <code>/flow-master</code> renders BRD.html and Architecture.html as self-contained HTML with <code><script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script></code> and <code>mermaid.initialize({startOnLoad:true, theme:'dark'})</code>. ```mermaid fences in the MD become SVG diagrams in the HTML.
|
|
798
|
-
</div>
|
|
799
|
-
|
|
800
|
-
<!-- ============================================================ -->
|
|
801
|
-
<h2 id="flows">7. Workflows<span class="anchor-link"><a href="#flows">#</a></span></h2>
|
|
802
|
-
|
|
803
|
-
<div class="panel ok">
|
|
804
|
-
<strong>No paste-and-substitute friction:</strong> every workflow step below is wrapped as a proper TechieFlow task that takes <code>{AppName}</code> as an argument. Run <code>/analyst *day1-brownfield TrTools</code> and the analyst executes the full multi-step task with the right file paths and templates already wired up. The agent will ask for the app name only if you forget to pass it.
|
|
805
|
-
<br><br>
|
|
806
|
-
The task files live in <code>.tfcore/tasks/</code>: <code>day1-brownfield.md</code>, <code>day1-greenfield.md</code>, <code>mockups.md</code>, <code>render-workflow-docs.md</code>, <code>split-brd.md</code>, <code>build-phase.md</code> (the ONE unified build), <code>verify-phase.md</code>, <code>fix-issues.md</code>, <code>triage-issues.md</code>, <code>devguide.md</code>, <code>handoff-phase.md</code>. Open any of them to see exactly what the agent will do.
|
|
807
|
-
</div>
|
|
808
|
-
|
|
809
|
-
<div class="panel warn">
|
|
810
|
-
<strong>If <code>*<command></code> says "I don't have that command":</strong> Claude Code cached the old agent persona. Two things to check:
|
|
811
|
-
<ol class="tight">
|
|
812
|
-
<li>Re-run the scaffold for this project: <code>scaffold-brownfield.sh .</code> or <code>scaffold-greenfield.sh .</code>. It includes a force-sync step that copies agent files from <code>.tfcore/agents/</code> to <code>.claude/commands/TechieFlow/agents/</code> (the path Claude Code actually loads).</li>
|
|
813
|
-
<li><strong>Restart Claude Code</strong> in this project so it re-scans skills. The slash-command registry only refreshes at startup.</li>
|
|
814
|
-
</ol>
|
|
815
|
-
Rule of thumb: edit agent files only in <code>.tfcore/agents/</code>; the scaffold force-mirrors them to <code>.claude/commands/TechieFlow/agents/</code>. Never edit the harness copy directly — it'll be overwritten next scaffold.
|
|
816
|
-
</div>
|
|
817
|
-
|
|
818
|
-
<div class="tabs">
|
|
819
|
-
<button class="active" data-tab="bf">Brownfield (existing app)</button>
|
|
820
|
-
<button data-tab="gf">Greenfield (new app)</button>
|
|
821
|
-
</div>
|
|
822
|
-
|
|
823
|
-
<!-- BROWNFIELD -->
|
|
824
|
-
<div class="tabpanel active" id="tab-bf">
|
|
825
|
-
|
|
826
|
-
<div class="panel">
|
|
827
|
-
<strong>Prereq:</strong> ran <code>scaffold-brownfield.sh</code> in the project root.
|
|
828
|
-
<br><span class="small"><strong>Typical agent invocations:</strong> 4–6 (day-1, split-brd, build-phase ×1–2, handoff). <strong>Manual checkpoints:</strong> 2 (BRD/Architecture/Standards + DevGuide-screenshot review, final UAT).</span>
|
|
829
|
-
</div>
|
|
830
|
-
|
|
831
|
-
<div class="flow">
|
|
832
|
-
|
|
833
|
-
<div class="step">
|
|
834
|
-
<div class="num">1</div>
|
|
835
|
-
<div class="body">
|
|
836
|
-
<h4>Reverse-doc + create all six day-1 deliverables</h4>
|
|
837
|
-
<p>Produces, in ONE bulk pass (no per-section/per-requirement confirmation): <code><APP>-Architecture.md</code>, <code><APP>-BRD.md</code> (feature catalog + BRD ledger), <code><APP>-Coding-Standards.md</code>, <code>.editorconfig</code>, <code>PROJECT-STATUS.md</code>, <code>CLAUDE.md</code>, the <code><APP>-UsageGuide.md</code>, and — because brownfield already has built code — the screen-by-screen <code><APP>-DevGuide.md</code> (§7.6) — <strong>plus the HTML render of every doc</strong> (no separate render step). Updates <code>core-config.yaml</code> with the app-specific doc paths.</p>
|
|
838
|
-
<p class="cmds"><span class="badge cmd">/analyst</span> <span class="badge task">*day1-brownfield TrTools</span></p>
|
|
839
|
-
<p class="small">Substitute <code>TrTools</code> with your app name. Asks at most twice: app name (if omitted) and which existing docs to harvest (<code>all</code> = default / a selection / extra paths / drafting instructions). It never asks merge-vs-new: deliverables are always written fresh at canonical names and pre-existing/superseded docs are archived to <code>docs/OldDocs/</code>. If a dev/phase plan exists, it's migrated into the one <code><APP>-Checklist.md</code> in the same run (completed phases pre-marked Done — skip step 3 below). <strong>Brownfield-only:</strong> because the repo already has built code, it also generates the screen-by-screen <strong>DevGuide</strong> (§7.6 — the as-built page → control → service → data-access → proc map). The DevGuide's OBSERVE pass boots the app, <strong>captures a screenshot of every screen</strong> to <code>docs/screenshots/<APP>/</code>, embeds them, and presents an <strong>owner visual-review gate</strong> ("here is how each screen renders — what needs to change?") — the brownfield counterpart to greenfield mockups. (Commonly <code>STATIC-ONLY</code> at day-1 until the stack is up; found defects land in the one checklist.) Greenfield day-1 has no code, so instead it produces UI <strong>mockups</strong> (§7.10). Task: <code>.tfcore/tasks/day1-brownfield.md</code>.</p>
|
|
840
|
-
</div>
|
|
841
|
-
</div>
|
|
842
|
-
|
|
843
|
-
<div class="arrow">↓</div>
|
|
844
|
-
|
|
845
|
-
<div class="step">
|
|
846
|
-
<div class="num">2</div>
|
|
847
|
-
<div class="body">
|
|
848
|
-
<h4>Review the rendered HTMLs — manual checkpoint (≈15 min)</h4>
|
|
849
|
-
<p class="small">No command — day-1 already rendered everything. Open <code><APP>-BRD.html</code> (business intent right?), <code><APP>-Architecture.html</code> (matches what you want?), <code>PROJECT-STATUS.html</code> (next command correct?), skim Coding Standards. Cheapest catch-mistakes point. Edit the <code>.md</code> sources directly for anything wrong, then re-render just those files: <code>/generate-html @docs/<APP>-BRD.md</code> (see <a href="#docs">§6</a>).</p>
|
|
850
|
-
</div>
|
|
851
|
-
</div>
|
|
852
|
-
|
|
853
|
-
<div class="arrow">↓</div>
|
|
854
|
-
|
|
855
|
-
<div class="step">
|
|
856
|
-
<div class="num">3</div>
|
|
857
|
-
<div class="body">
|
|
858
|
-
<h4>Split BRD into the one Checklist</h4>
|
|
859
|
-
<p class="cmds"><span class="badge cmd">/analyst</span> <span class="badge task">*split-brd TrTools</span></p>
|
|
860
|
-
<p class="small">Every BRD-N maps to one or more REQ-UI-*/REQ-FN-*/REQ-RAG-*/REQ-NFR-* in the single <code>docs/<APP>-Checklist.md</code> (one Requirements Status table), each back-linked to its source BRD. Each <code>REQ-UI-*</code> cites the mockup screen it realizes (greenfield). Task: <code>.tfcore/tasks/split-brd.md</code>.</p>
|
|
861
|
-
<p class="small"><strong>Manual checkpoint:</strong> read the checklist, adjust if needed.</p>
|
|
862
|
-
</div>
|
|
863
|
-
</div>
|
|
864
|
-
|
|
865
|
-
<div class="arrow">↓</div>
|
|
866
|
-
|
|
867
|
-
<div class="step">
|
|
868
|
-
<div class="num">4</div>
|
|
869
|
-
<div class="body">
|
|
870
|
-
<h4>Build phase — ONE unified build (chains self-smoke + verifier)</h4>
|
|
871
|
-
<p class="cmds"><span class="badge cmd">/flow-master</span> <span class="badge task">*build-phase TrTools</span></p>
|
|
872
|
-
<p class="small">There is no longer a separate UI / RAG / functional build. <code>*build-phase</code> reads the one checklist, clusters ALL open REQs, and fans them out — <strong>calling <code>/trblazeui</code> (REQ-UI-*, building from the approved mockups) and <code>/techierag</code> (REQ-RAG-*) as sub-agents</strong>, and building REQ-FN-* / REQ-NFR-* itself. It then <strong>self-smokes (data + visual)</strong> and auto-chains <code>/verifier</code>. You never invoke <code>/trblazeui</code> or <code>/techierag</code> directly — flow-master orchestrates them. Task: <code>.tfcore/tasks/build-phase.md</code>.</p>
|
|
873
|
-
</div>
|
|
874
|
-
</div>
|
|
875
|
-
|
|
876
|
-
<div class="arrow">↓</div>
|
|
877
|
-
|
|
878
|
-
<div class="step">
|
|
879
|
-
<div class="num">5</div>
|
|
880
|
-
<div class="body">
|
|
881
|
-
<h4 id="verify">Verify loop (until green)</h4>
|
|
882
|
-
<p><code>*build-phase</code> self-chains <code>/verifier</code>, which writes verdicts into the one checklist's Requirements Status table and applies BOTH gates — the <strong>data-render gate</strong> (§4a: every control renders its data) AND the <strong>visual-truth gate</strong> (§4b: no overlap, every control in-viewport and non-zero-size at desktop + mobile, screenshot inspected, diffed against the mockup when one exists). A REQ is <code>Verified</code> only if acceptance passes AND data renders AND the screen looks right.</p>
|
|
883
|
-
|
|
884
|
-
<p><strong>The performance gate (§4c, added 2026-08-10) — opt-in by declaring a number.</strong> Render and visual say nothing about <em>speed</em>: a page that shows every control perfectly and takes nine seconds passed every gate the framework had. §4c closes that, and it is deliberately the narrowest of the four. It grades a REQ <strong>only</strong> if that REQ's acceptance criteria carry a machine-read budget line:</p>
|
|
885
|
-
<pre><code>perf-budget: p95 load <= 2000ms @ concurrency 1
|
|
886
|
-
perf-budget: p95 ttfb <= 500ms @ concurrency 50</code></pre>
|
|
887
|
-
<p>No line, no gate — and that is the correct outcome, not a gap to fill. A threshold you never agreed to would produce failures you never asked for, and the first false failure is the moment gate verdicts stop being believed. Measurement is the shipped harness <code>.tfcore/utils/tf-perf.sh</code> (TTFB and full-load p50/p95/max at graded concurrency, warm-up discarded, per-path breakdown so you can see <em>which</em> page is slow).</p>
|
|
888
|
-
<table>
|
|
889
|
-
<thead><tr><th>Measured vs budget</th><th>Verdict</th><th>Effect</th></tr></thead>
|
|
890
|
-
<tbody>
|
|
891
|
-
<tr><td>≤ budget</td><td><code>PERF-OK</code></td><td>gate passes</td></tr>
|
|
892
|
-
<tr><td>> budget, ≤ budget × 1.25</td><td><code>PERF-MARGINAL</code></td><td><strong>never blocks <code>Verified</code></strong> — a dated remark, so drift is visible before it becomes a failure</td></tr>
|
|
893
|
-
<tr><td>> budget × 1.25</td><td><code>PERF-FAIL</code></td><td>→ <code>Needs re-verify</code></td></tr>
|
|
894
|
-
</tbody>
|
|
895
|
-
</table>
|
|
896
|
-
<p>The gate <strong>refuses to fail</strong> a REQ on a Debug build, on fewer than 20 samples behind the p95, when errors occurred during the run, or on a visibly contended host — each becomes <code>PERF-UNMEASURED</code> with the reason stated, because a wrong perf failure costs more than a missing one. MAUI native heads are not perf-gated (no HTTP surface; app-launch and frame timing are a different discipline with different tooling). Write budgets in the BRD §11 Performance NFR; <code>*split-brd</code> copies the line verbatim into the REQ, and <code>*metrics</code> reports the gate's catch rate against how many records actually <em>ran</em> it, never against the whole distribution (<code>SCHEMA.md</code> §3.5).</p>
|
|
897
|
-
<p class="small">If Vidur reports misses, just re-run <code>/flow-master *build-phase TrTools</code> — it detects FIX mode and fans out repair subagents (layout/visual fixes route back to <code>/trblazeui</code>). Or re-verify a scope directly with <code>/TechieFlow:agents:verifier *verify ui|functional|all</code> (it filters the one table by REQ prefix). Loop until green; <code>Blocked</code> (library-gap) items pass through. Vidur also runs the <strong>standards-compliance grep checks</strong> from <code><APP>-Coding-Standards.md</code> §"Enforcement".</p>
|
|
898
|
-
</div>
|
|
899
|
-
</div>
|
|
900
|
-
|
|
901
|
-
<div class="arrow">↓</div>
|
|
902
|
-
|
|
903
|
-
<div class="step">
|
|
904
|
-
<div class="num">6</div>
|
|
905
|
-
<div class="body">
|
|
906
|
-
<h4>Handoff: usage doc + dev guide + status + library-feedback consolidation + HTML refresh</h4>
|
|
907
|
-
<p class="cmds"><span class="badge cmd">/flow-master</span> <span class="badge task">*handoff-phase TrTools</span></p>
|
|
908
|
-
<p class="small">Produces UsageGuide doc (test users + test plan + setup), runs <code>*devguide</code> (§3a — generates the screen-by-screen Developer Guide documenting the code as-built, capturing a screenshot of every screen), sets PROJECT-STATUS phase to Handoff, re-renders human-facing HTMLs (BRD, Architecture, UIDesign, UsageGuide, DevGuide, PROJECT-STATUS — <strong>not</strong> the checklist), consolidates each per-library feedback file with summary counts. It also points owners at <code>*productguide <APP></code> (<a href="#docs">§6</a>) — the optional end-user how-to manual, built from the same screens + screenshots the DevGuide just captured. Task: <code>.tfcore/tasks/handoff-phase.md</code>.</p>
|
|
909
|
-
<p class="small"><strong>Manual checkpoint:</strong> 15-min UAT against the smoke checklist. Then hand each <code><APP>-<Library>-Feedback.md</code> to its team / file as GitHub issues (§9.2). <strong>Found a bug after shipping?</strong> Drop screenshots into a folder and run <code>*fix-issues</code> (§7.11) — or <code>*triage-issues</code> (§7.12) to analyze + log it in the checklist first, without fixing.</p>
|
|
910
|
-
</div>
|
|
911
|
-
</div>
|
|
912
|
-
|
|
913
|
-
</div>
|
|
914
|
-
|
|
915
|
-
</div><!-- /tab-bf -->
|
|
916
|
-
|
|
917
|
-
<!-- GREENFIELD -->
|
|
918
|
-
<div class="tabpanel" id="tab-gf">
|
|
919
|
-
|
|
920
|
-
<div class="panel">
|
|
921
|
-
<strong>Prereq:</strong> scaffold + <code>dotnet new sln/blazor</code> + library NuGets + <code>dotnet build</code> (deploys library agent files).
|
|
922
|
-
</div>
|
|
923
|
-
|
|
924
|
-
<div class="flow">
|
|
925
|
-
|
|
926
|
-
<div class="step">
|
|
927
|
-
<div class="num">1</div>
|
|
928
|
-
<div class="body">
|
|
929
|
-
<h4>Brief + BRD + Architecture + Coding-Standards + CLAUDE.md + PROJECT-STATUS + .editorconfig</h4>
|
|
930
|
-
<p class="cmds"><span class="badge cmd">/analyst</span> <span class="badge task">*day1-greenfield MyNewApp</span></p>
|
|
931
|
-
<p class="small">Asks once for the concept (ANY length — sentence, bullets, half-baked notes) and once for optional harvest paths / drafting instructions, then produces the day-1 artifacts in bulk — including a TARGET architecture with stack defaults (Blazor Server + TrBlazeUI + TechieRag-if-AI + SQLite-for-dev) and the UI <strong>mockups</strong> (<code>docs/<APP>-UIDesign.md</code> + <code>docs/mockups/*.html</code>, §7.10) — <strong>plus the HTML render of every doc</strong> (no separate render step). Substitute <code>MyNewApp</code> with your actual app name. Task: <code>.tfcore/tasks/day1-greenfield.md</code>.</p>
|
|
932
|
-
</div>
|
|
933
|
-
</div>
|
|
934
|
-
|
|
935
|
-
<div class="arrow">↓</div>
|
|
936
|
-
|
|
937
|
-
<div class="step">
|
|
938
|
-
<div class="num">2</div>
|
|
939
|
-
<div class="body">
|
|
940
|
-
<h4>Review the rendered HTMLs AND the mockups — manual checkpoint (approve before build)</h4>
|
|
941
|
-
<p>No command — day-1 already rendered everything. Read the BRD/Architecture HTMLs AND open <code>docs/mockups/*.html</code> + <code>docs/<APP>-UIDesign.md</code>: this is the visual design the UI will be built to match, so flag any screen that's wrong NOW. Edit the <code>.md</code> sources and re-render with <code>/generate-html @docs/file.md</code>, or run <code>*mockups <APP> --update</code>. The BRD + Architecture + mockups are <strong>approved together</strong> before any build.</p>
|
|
942
|
-
<p class="small">This is your last cheap chance to redirect before code gets written.</p>
|
|
943
|
-
</div>
|
|
944
|
-
</div>
|
|
945
|
-
|
|
946
|
-
<div class="arrow">↓</div>
|
|
947
|
-
|
|
948
|
-
<div class="step">
|
|
949
|
-
<div class="num">3–6</div>
|
|
950
|
-
<div class="body">
|
|
951
|
-
<h4>Split BRD → Build phase → Verify → Handoff</h4>
|
|
952
|
-
<p>Identical to brownfield steps 3–6. Same prompts, same one checklist, same unified <code>*build-phase</code> (which builds REQ-UI-* from your approved mockups via <code>/trblazeui</code>), same data + visual gates, same standards-compliance discipline.</p>
|
|
953
|
-
</div>
|
|
954
|
-
</div>
|
|
955
|
-
|
|
956
|
-
</div>
|
|
957
|
-
|
|
958
|
-
</div><!-- /tab-gf -->
|
|
959
|
-
|
|
960
|
-
<h3 id="evolving-docs">7.9 Evolving the day-1 docs (the concept/requirements changed)</h3>
|
|
961
|
-
|
|
962
|
-
<p>Day-1 produces a first-pass BRD + Architecture, but a project keeps moving — the greenfield concept is still being discussed, or a requirement shifts mid-development. You do <strong>not</strong> have to hand-edit and hope, and you should <strong>not</strong> silently let the docs drift out of date. Pick by how big the change is:</p>
|
|
963
|
-
|
|
964
|
-
<table>
|
|
965
|
-
<thead><tr><th>Situation</th><th>Command</th><th>What it does</th></tr></thead>
|
|
966
|
-
<tbody>
|
|
967
|
-
<tr>
|
|
968
|
-
<td><strong>Concept/requirements evolved</strong> — add / reword / drop features, a new integration, a stack tweak — but most of the docs are still right</td>
|
|
969
|
-
<td><code>*amend-docs <APP> "<what changed>"</code><br><span class="small">(analyst or flow-master)</span></td>
|
|
970
|
-
<td>Surgically amends the BRD + Architecture <strong>in place</strong>: appends new <code>BRD-N</code> (IDs are append-only — modified IDs are edited in place, removed ones struck through, never renumbered), updates the feature catalog + §4 Development-status, ripples new/changed REQs into the checklist (appends new rows, flags modified ones for re-verify — never blindly re-splits), re-renders the HTML, and runs the status gate. Confirms the parsed change-set once, then applies in bulk. <strong>Preserves every unchanged section</strong> — no <code>OldDocs</code> archive.</td>
|
|
971
|
-
</tr>
|
|
972
|
-
<tr>
|
|
973
|
-
<td><strong>Pure additions</strong> and you want to confirm each requirement one at a time</td>
|
|
974
|
-
<td><code>*create-brd <APP> <topic></code> → <code>author-brd</code><br><span class="small">(analyst)</span></td>
|
|
975
|
-
<td>Interactive, per-item elicitation; appends confirmed <code>BRD-N</code> to the existing BRD. (<code>*amend-docs</code> defers to this for the additive part if you ask.)</td>
|
|
976
|
-
</tr>
|
|
977
|
-
<tr>
|
|
978
|
-
<td><strong>"What's built" view</strong> is what you want refreshed (not the requirements)</td>
|
|
979
|
-
<td>automatic, or <code>*refresh-status <APP></code></td>
|
|
980
|
-
<td>The status gate already re-derives <code>PROJECT-STATUS</code> + the BRD §4 rollup at the end of every build/verify/handoff. <code>*refresh-status</code> rebuilds them on demand (see §8a).</td>
|
|
981
|
-
</tr>
|
|
982
|
-
<tr>
|
|
983
|
-
<td><strong>Full pivot</strong> — most of the BRD/Architecture is now wrong</td>
|
|
984
|
-
<td>re-run <code>*day1-greenfield</code> / <code>*day1-brownfield</code></td>
|
|
985
|
-
<td>The §1.6 collision policy archives the old docs to <code>docs/OldDocs/</code> and writes fresh. Use this only for a wholesale redo, never for an incremental change (it would discard unchanged content + history).</td>
|
|
986
|
-
</tr>
|
|
987
|
-
<tr>
|
|
988
|
-
<td><strong>You just hand-edited a <code>.md</code></strong></td>
|
|
989
|
-
<td><code>/generate-html @docs/<file>.md</code></td>
|
|
990
|
-
<td>Re-renders that one doc's HTML so the human-readable view isn't stale.</td>
|
|
991
|
-
</tr>
|
|
992
|
-
</tbody>
|
|
993
|
-
</table>
|
|
994
|
-
|
|
995
|
-
<p class="small">Rule of thumb: <strong>amend, don't regenerate.</strong> <code>*amend-docs</code> is the default for an evolving project; re-running day-1 is the escape hatch for a true restart. After amending, if new requirements were added to an already-split project, run <code>*split-brd</code> (or the build phase the report points at) to carry them into the build.</p>
|
|
996
|
-
|
|
997
|
-
<h3 id="mockups">7.10 Greenfield UI mockups (<code>*mockups</code>)</h3>
|
|
998
|
-
|
|
999
|
-
<p>A greenfield app has no code, so its UI is built freehand from prose — which is exactly why a new app's UI comes out broken (overlapping controls, wrong layout, nothing to verify against). The analyst produces <strong>mockups at day-1</strong> to give the build an approved visual contract and the verifier a baseline to diff against:</p>
|
|
1000
|
-
|
|
1001
|
-
<p class="cmds"><span class="badge cmd">/analyst</span> <span class="badge task">*mockups MyNewApp</span></p>
|
|
1002
|
-
|
|
1003
|
-
<p>Reads the TrBlazeUI component catalog FIRST (so it designs only with controls that exist), then produces <code>docs/<APP>-UIDesign.md</code> — a per-screen spec with a <code>region → TrBlazeUI control</code> component map — plus rendered <code>docs/mockups/*.html</code> styled to look like TrBlazeUI, one per key screen from the BRD §9 feature catalog. Auto-run inside <code>*day1-greenfield</code>; re-runnable with <code>*mockups <APP> --update</code> to refresh only changed screens after an <code>*amend-docs</code> that added UI. The mockups are approved alongside the BRD + Architecture, are what <code>/trblazeui</code> builds from, and are the image the visual-truth gate (<a href="#quickref">§4b</a>) diffs the live screen against. <strong>Mockups are greenfield only</strong> — a greenfield app has no code to screenshot yet, so its mockups are the pre-build visual contract; brownfield already has built code and instead reviews real screenshots in the DevGuide's OBSERVE pass (§7.6). Note this is about <em>mockups</em>, not screenshots: once a greenfield app is built, its DevGuide OBSERVE pass captures real per-screen screenshots exactly like brownfield (<a href="#docs">§6</a>). Task: <code>.tfcore/tasks/mockups.md</code>.</p>
|
|
1004
|
-
|
|
1005
|
-
<h3 id="fix-issues">7.11 Fixing issues you found by running the app (<code>*fix-issues</code>)</h3>
|
|
1006
|
-
|
|
1007
|
-
<p>When the verifier passed but the running UI is still broken — overlapping controls, blank screens, wrong data — there is ONE front door:</p>
|
|
1008
|
-
|
|
1009
|
-
<p class="cmds"><span class="badge cmd">/flow-master</span> <span class="badge task">*fix-issues MyApp ./bugshots</span></p>
|
|
1010
|
-
|
|
1011
|
-
<p>Drop a folder of <strong>screenshots</strong> (plus an optional <code>bugs.md</code> describing what's wrong on each) and flow-master: reads every screenshot (vision), reproduces each issue live with Playwright, triages it (layout / data / logic / RAG), and <strong>fans the fix out to the right builder</strong> — <code>/trblazeui</code> for layout, its own subagents for data/logic, <code>/techierag</code> for RAG. <strong>You never invoke a builder agent yourself — flow-master calls them as sub-agents.</strong> It then re-smokes (data + visual) and re-verifies the affected REQs, and updates the DevGuide + the one checklist + PROJECT-STATUS. This is the answer to "the verifier passed but the UI is broken — who do I call?". Task: <code>.tfcore/tasks/fix-issues.md</code>. Only want the bugs <em>analyzed and logged</em>, not fixed? That's <code>*triage-issues</code> (§7.12).</p>
|
|
1012
|
-
|
|
1013
|
-
<h3 id="triage-issues">7.12 Analyzing UAT / production bugs WITHOUT fixing (<code>*triage-issues</code>)</h3>
|
|
1014
|
-
|
|
1015
|
-
<p>Bugs found at UAT or in production usually need a <strong>plan and a paper trail before anyone touches code</strong>: which REQs regressed, what's a brand-new defect, what still passes. <code>*fix-issues</code> is the wrong tool for that moment — its deliverable is fixed code. The analyze-only front door is:</p>
|
|
1016
|
-
|
|
1017
|
-
<p class="cmds"><span class="badge cmd">/flow-master</span> <span class="badge task">*triage-issues MyApp ./uat-bugs</span> · add <code>verify</code> to also regression-re-verify sibling features</p>
|
|
1018
|
-
|
|
1019
|
-
<p>Hand it a folder of screenshots <em>and/or a written bug list</em> (UAT reports often arrive as prose). Flow-master reproduces each issue live with Playwright and delivers <strong>documentation only</strong>: regressed REQs are demoted to <code>Needs re-verify</code> with a dated <code>⚠ UAT bug</code> remark, unspecified defects become new <code>Planned</code> REQ rows with acceptance criteria, the DevGuide's known-issues lines are refreshed, and PROJECT-STATUS's "Next command" points at <code>*fix-issues {App} {folder}</code> naming the REQ IDs. With the optional <code>verify</code> argument it also EXECUTES a scoped verify-phase over the affected screens' sibling REQs ("check the rest still works"). <strong>It never edits <code>src/</code> or <code>tests/</code> and never spawns a builder sub-agent</strong> — fixing is a separate decision you make afterwards by running <code>*fix-issues</code>. Task: <code>.tfcore/tasks/triage-issues.md</code>.</p>
|
|
1020
|
-
|
|
1021
|
-
<!-- ============================================================ -->
|
|
1022
|
-
<h2 id="resume">8. Resuming a cold project<span class="anchor-link"><a href="#resume">#</a></span></h2>
|
|
1023
|
-
|
|
1024
|
-
<p>Two flavours of resume. Pick by asking one question: <strong>do you trust <code>PROJECT-STATUS.md</code>?</strong></p>
|
|
1025
|
-
|
|
1026
|
-
<div class="panel warn">
|
|
1027
|
-
<strong>8a. The session BROKE mid-phase → run <code>*refresh-status</code> first.</strong>
|
|
1028
|
-
<p>If the last session died in the middle of a build or verify — lost internet, model access revoked/changed mid-run, terminal killed, agent crashed — then the mandatory status gate never ran. <code>PROJECT-STATUS.md</code> is now <em>stale or wrong</em>: it may point at an old "Next command", undercount work that landed after its last write, or claim a passing build that's since broken. Do NOT trust it. Run the recovery command, which rebuilds PROJECT-STATUS from <em>ground-truth evidence</em> (the checklist Requirements Status table + what's actually in the working tree, including file modification times + a fresh <code>dotnet build</code> — no git; git is manual in this framework) and tells you the exact command to resume with:</p>
|
|
1029
|
-
<p class="cmds"><span class="badge cmd">/TechieFlow:agents:flow-master</span> <code>*refresh-status <APP></code> — OpenCode: <code>/flow-master *refresh-status <APP></code> · add <code>verify</code> to also re-run the verifier on any REQ whose true state is ambiguous.</p>
|
|
1030
|
-
<p style="margin-bottom:0">It never edits source code — it only reconstructs status. When it finishes, follow its "next command", then drop into the clean flow below. This is the answer to "an experimental model lost access mid-development and I don't know where it left things."</p>
|
|
1031
|
-
</div>
|
|
1032
|
-
|
|
1033
|
-
<p><strong>8b. Clean cold resume</strong> (you came back to a project whose last phase <em>did</em> finish and wrote PROJECT-STATUS): trust the file and walk the four steps.</p>
|
|
1034
|
-
|
|
1035
|
-
<div class="flow">
|
|
1036
|
-
<div class="step">
|
|
1037
|
-
<div class="num">1</div>
|
|
1038
|
-
<div class="body">
|
|
1039
|
-
<h4>Open three HTML files in browser</h4>
|
|
1040
|
-
<p><code>PROJECT-STATUS.html</code> (where am I), <code><APP>-BRD.html</code> (why was I doing this), <code><APP>-Architecture.html</code> (what's the shape). < 5 min.</p>
|
|
1041
|
-
</div>
|
|
1042
|
-
</div>
|
|
1043
|
-
<div class="arrow">↓</div>
|
|
1044
|
-
<div class="step">
|
|
1045
|
-
<div class="num">2</div>
|
|
1046
|
-
<div class="body">
|
|
1047
|
-
<h4>"What changed" check</h4>
|
|
1048
|
-
<pre><code class="lang-bash">cd /path/to/project
|
|
1049
|
-
git log --oneline -20 && git status
|
|
1050
|
-
dotnet build</code></pre>
|
|
1051
|
-
</div>
|
|
1052
|
-
</div>
|
|
1053
|
-
<div class="arrow">↓</div>
|
|
1054
|
-
<div class="step">
|
|
1055
|
-
<div class="num">3</div>
|
|
1056
|
-
<div class="body">
|
|
1057
|
-
<h4>Re-verify</h4>
|
|
1058
|
-
<p class="cmds"><span class="badge cmd">/verifier</span> → <em>"Re-verify the checklist's Requirements Status table and run standards-compliance greps from docs/<APP>-Coding-Standards.md. Note regressions."</em></p>
|
|
1059
|
-
</div>
|
|
1060
|
-
</div>
|
|
1061
|
-
<div class="arrow">↓</div>
|
|
1062
|
-
<div class="step">
|
|
1063
|
-
<div class="num">4</div>
|
|
1064
|
-
<div class="body">
|
|
1065
|
-
<h4>Execute the "Next command" from <code>PROJECT-STATUS.md</code></h4>
|
|
1066
|
-
</div>
|
|
1067
|
-
</div>
|
|
1068
|
-
</div>
|
|
1069
|
-
|
|
1070
|
-
<div class="panel warn">
|
|
1071
|
-
<strong>Discipline:</strong> every phase (build, verify, handoff) ends with <code>/flow-master</code> updating PROJECT-STATUS. Never skip it. And when a run is cut off before it can — <code>*refresh-status <APP></code> (§8a) is the safety net that rebuilds it from evidence.
|
|
1072
|
-
</div>
|
|
1073
|
-
|
|
1074
|
-
<!-- ============================================================ -->
|
|
1075
|
-
<h2 id="libraries">9. Custom library agents — routing rules<span class="anchor-link"><a href="#libraries">#</a></span></h2>
|
|
1076
|
-
|
|
1077
|
-
<p><code>/trblazeui</code> and <code>/techierag</code> are <strong>library agents</strong> — flow-master calls them as <strong>sub-agents</strong> during <code>*build-phase</code> and <code>*fix-issues</code> (and the analyst calls <code>/trblazeui</code> for its component catalog during <code>*mockups</code>). You drive the build/fix through flow-master; it routes each REQ cluster to the right builder by its prefix.</p>
|
|
1078
|
-
|
|
1079
|
-
<table>
|
|
1080
|
-
<tr><th>Trigger</th><th>Routed (by <code>*build-phase</code> / <code>*fix-issues</code>) to</th><th>Reads (besides <APP>-Coding-Standards.md)</th></tr>
|
|
1081
|
-
<tr><td><code>REQ-UI-*</code> — UI work (pages, components, forms, dashboards)</td><td><code>/trblazeui</code> (sub-agent) — builds from the mockups</td><td><code>.trblazeui/TrBlazeUI-AI-Reference.md</code> + the Checklist + <code>docs/mockups/*.html</code></td></tr>
|
|
1082
|
-
<tr><td><code>REQ-RAG-*</code> — AI/RAG/LLM (embedding, vector store, chat, tools)</td><td><code>/techierag</code> (sub-agent)</td><td><code>.techierag/TechieRag-AI-Reference.md</code> + the Checklist</td></tr>
|
|
1083
|
-
<tr><td><code>REQ-FN-*</code> / <code>REQ-NFR-*</code> — backend / business logic / data / APIs / non-functional</td><td><code>/flow-master</code> own subagents</td><td>the Checklist + Architecture</td></tr>
|
|
1084
|
-
<tr><td>Reverse-doc, BRD/Architecture/Standards, requirements splitting, mockups</td><td><code>/analyst</code></td><td>codebase / brief</td></tr>
|
|
1085
|
-
<tr><td>Verification of any scope (data + visual gates)</td><td><code>/verifier</code></td><td>the Checklist + DevGuide + running app + standards grep checks</td></tr>
|
|
1086
|
-
<tr><td>Unified build / fix-issues / HTML renders / status / handoff / consolidation</td><td><code>/flow-master</code></td><td>everything</td></tr>
|
|
1087
|
-
</table>
|
|
1088
|
-
|
|
1089
|
-
<h3 id="add-library">9.1 Adding a new custom library agent</h3>
|
|
1090
|
-
<ol class="tight">
|
|
1091
|
-
<li>Library's NuGet adds an MSBuild target that copies on consumer build: <code>.<libname>/<LibName>-AI-Reference.md</code>, <code>.claude/<libname>.md</code>, <code>.opencode/command/<libname>.md</code>.</li>
|
|
1092
|
-
<li>Agent file's frontmatter: <code>description</code>, <code>mode: primary</code>, <code>tools</code>. Body: load reference doc on activation + REQUIRED READING clause for <code>docs/<APP>-Coding-Standards.md</code>.</li>
|
|
1093
|
-
<li>Add routing row to the table above.</li>
|
|
1094
|
-
<li>The new library gets its OWN feedback file — <code><APP>-<LibName>-Feedback.md</code> with its own issue-ID prefix, from the shared template. Never share a feedback file between libraries.</li>
|
|
1095
|
-
<li>Update <code>build-phase</code>'s cluster-routing (and <code>fix-issues</code>'s triage) to route the new ID prefix to the new sub-agent.</li>
|
|
1096
|
-
</ol>
|
|
1097
|
-
|
|
1098
|
-
<h3 id="library-feedback">9.2 Library issue tracking flow</h3>
|
|
1099
|
-
<ol class="tight">
|
|
1100
|
-
<li>Implementing agents log on encounter — into the OWNING library's file (<code><APP>-TrBlazeUI-Feedback.md</code> for TR-NNN, <code><APP>-TechieRag-Feedback.md</code> for TR-RAG-NNN). Clause baked into §7 prompts.</li>
|
|
1101
|
-
<li>Verifier escalates library bugs → <code>Blocked</code> status in the checklist's Requirements Status table + entry in that library's feedback file.</li>
|
|
1102
|
-
<li><code>/flow-master</code> consolidates each file separately at handoff: dedupe, severity sort, summary header (splits + archives any legacy combined <code><APP>-Library-Feedback.md</code>).</li>
|
|
1103
|
-
<li>You hand each file to its team — they use this same framework, so the file drops straight into their flow — or file as GitHub issues: <code>gh issue create --repo your-org/TrBlazeUI --title "…" --body-file …</code></li>
|
|
1104
|
-
</ol>
|
|
1105
|
-
|
|
1106
|
-
<!-- ============================================================ -->
|
|
1107
|
-
<h2 id="standards-enforcement">10. Coding standards — how enforcement actually works<span class="anchor-link"><a href="#standards-enforcement">#</a></span></h2>
|
|
1108
|
-
|
|
1109
|
-
<p>"Every agent follows the standards" is achieved through <strong>three layered mechanisms</strong>. None alone is sufficient; all three together close the gaps.</p>
|
|
1110
|
-
|
|
1111
|
-
<div class="grid3">
|
|
1112
|
-
<div class="panel">
|
|
1113
|
-
<h4>1. Prompt-level (every session)</h4>
|
|
1114
|
-
<p class="small">Every implementation prompt in §7 starts with "REQUIRED READING: docs/<APP>-Coding-Standards.md". The agent loads it before writing any code. Cross-harness reliable.</p>
|
|
1115
|
-
</div>
|
|
1116
|
-
<div class="panel">
|
|
1117
|
-
<h4>2. <code>CLAUDE.md</code> auto-load</h4>
|
|
1118
|
-
<p class="small">Claude Code auto-loads <code>CLAUDE.md</code> at project root into every session. It says "Always follow docs/<APP>-Coding-Standards.md before any code write." Catches even direct user prompts that forgot the boilerplate.</p>
|
|
1119
|
-
</div>
|
|
1120
|
-
<div class="panel">
|
|
1121
|
-
<h4>3. <code>.editorconfig</code> + verifier greps</h4>
|
|
1122
|
-
<p class="small">Machine-checkable rules go in <code>.editorconfig</code> (Roslyn enforces in the IDE / build). Non-checkable rules (a/v prefixes, test-name underscores) become grep patterns the verifier runs in the verify pass.</p>
|
|
1123
|
-
</div>
|
|
1124
|
-
</div>
|
|
1125
|
-
|
|
1126
|
-
<div class="panel">
|
|
1127
|
-
<strong>Standing standard — Serilog file logging in EVERY .NET app (2026-07-09).</strong> Every executable head — Blazor web, API, MAUI, desktop, console/CLI, background service — wires <strong>Serilog with a rolling file sink</strong> (<code>logs/<app>-.log</code>, daily rolling; MAUI/desktop root it in the per-app data dir) at startup, logs unhandled exceptions, and exposes app logging only through <code>ILogger<T></code> (class libraries reference logging abstractions, never Serilog). This is baked in end-to-end so you never have to ask: the BRD template carries a standing Observability NFR, day-1 always emits it (brownfield marks it <code>Done (pre-existing)</code> when an equivalent stack is already wired), <code>*split-brd</code> turns it into a <code>REQ-NFR-*</code> row, the coding-standards §Logging block carries the wiring recipe, and <code>*build-phase</code> wires Serilog into any new head it scaffolds even when no REQ names logging.</div>
|
|
1128
|
-
|
|
1129
|
-
<div class="panel">
|
|
1130
|
-
<strong>Standing standard — the primary head carries the PRODUCT name (2026-07-10).</strong> The product's primary executable head project is named exactly <code><APP></code> (<code>src/<APP>/<APP>.csproj</code>); a single-head product's one head IS <code><APP></code>. <strong><code><APP>.App</code> is banned</strong> — "App" says nothing the product name doesn't. Secondary heads of a multi-head product take a <em>descriptive</em> dotted suffix (<code><APP>.Api</code>, <code><APP>.Desktop</code>, <code><APP>.Cli</code>); satellites keep their conventional names (<code><APP>.Core</code>, <code><APP>UI</code> RCL, <code><APP>.Core.Tests</code>). Baked into the coding-standards canonical block (day1-brownfield §4 → "Project & solution naming") and <code>*build-phase</code> §3 (scaffold-time rule; an existing <code><APP>.App</code> gets a rename REQ, never propagated).</div>
|
|
1131
|
-
|
|
1132
|
-
<p>The grep patterns belong inside <code>docs/<APP>-Coding-Standards.md</code> under an "Enforcement" section. Sample grep block (already in §11.3 template):</p>
|
|
1133
|
-
|
|
1134
|
-
<pre><code class="lang-bash"># Forbidden field forms
|
|
1135
|
-
grep -rE "private(\s+readonly)?\s+\w+\s+_[a-z]" src/ # underscore prefix
|
|
1136
|
-
# Instance field must start with `obj` (not bare PascalCase, not _underscore)
|
|
1137
|
-
grep -rE "private(\s+readonly)?\s+\w+\s+(?!obj)[A-Z]\w+\s*[;=]" src/ | grep -v "static\|const"
|
|
1138
|
-
|
|
1139
|
-
# Forbidden test-method form
|
|
1140
|
-
grep -rE "public\s+(async\s+)?Task\s+\w+_\w+\s*\(" tests/
|
|
1141
|
-
|
|
1142
|
-
# Parameter without a-prefix (heuristic; grep catches "(string Foo" but not all cases)
|
|
1143
|
-
grep -rE "\(\s*\w+\s+[A-Z]\w+\s*[,)]" src/</code></pre>
|
|
1144
|
-
|
|
1145
|
-
<!-- ============================================================ -->
|
|
1146
|
-
<h2 id="wsl-runtime">11. MAUI builds & runs — from WSL (bridged) or macOS (native)<span class="anchor-link"><a href="#wsl-runtime">#</a></span></h2>
|
|
1147
|
-
|
|
1148
|
-
<p class="small"><strong>WSL (Windows) — bridge every dotnet call to the Windows side via <code>winrun</code> (§0):</strong></p>
|
|
1149
|
-
<pre><code class="lang-bash">cd /mnt/c/path/to/maui-project
|
|
1150
|
-
winrun "dotnet build -c Release"
|
|
1151
|
-
winrun "dotnet test"
|
|
1152
|
-
winrun "dotnet build -t:Run -f net9.0-windows10.0.19041.0"</code></pre>
|
|
1153
|
-
<p class="small"><strong>macOS — no bridge; dotnet runs natively (ladder §A):</strong></p>
|
|
1154
|
-
<pre><code class="lang-bash">cd /path/to/maui-project
|
|
1155
|
-
dotnet build -c Release
|
|
1156
|
-
dotnet test
|
|
1157
|
-
dotnet build -t:Run -f net9.0-maccatalyst # desktop head on Mac = Mac Catalyst
|
|
1158
|
-
dotnet build -t:Run -f net9.0-android # Android head (emulator via Android Studio)</code></pre>
|
|
1159
|
-
|
|
1160
|
-
<p>On macOS the Windows head (<code>net9.0-windows…</code>) can't build — the Mac desktop head is <strong>Mac Catalyst</strong>, and iOS builds natively too (Xcode required, <a href="#platforms">§16</a>). The <code>winrun</code> lines apply only inside WSL.</p>
|
|
1161
|
-
|
|
1162
|
-
<p>For verifier on a MAUI <strong>Windows</strong> app: <em>"This is a MAUI Windows app. Build/run/test via `winrun`. UI automation: FlaUI or Appium-Windows-driver Windows-side, NOT Playwright. Output evidence the same as Blazor projects."</em> On a Mac the equivalent prompt names the <strong>Catalyst</strong> head and the local <code>mac2</code> Appium driver instead.</p>
|
|
1163
|
-
|
|
1164
|
-
<h3>Mobile & Mac-desktop heads — runtime-observe over Appium</h3>
|
|
1165
|
-
<p>The §4a data-render and §4b visual-truth gates reach the MAUI <strong>Android / iOS / Mac Catalyst</strong> heads through an <strong>Appium</strong> WebDriver endpoint — the native analogue of Playwright (same screenshot + element-tree evidence, so the gates run unchanged). One-time host setup is <a href="#device-bootstrap">§0b</a>; the per-head driver map lives in <code>build-invocation-ladder.md §D</code>. <strong>Builds don't change</strong> — on WSL, Android still builds via <code>cmd.exe</code> (ladder rung #4) and iOS/Catalyst on the paired Mac; on a Mac-native setup all three build locally with plain <code>dotnet build</code> and the Appium endpoints are all <code>localhost</code>. This is purely how the verifier reaches the <em>running</em> UI after a green build.</p>
|
|
1166
|
-
<table>
|
|
1167
|
-
<thead><tr><th>Head</th><th>Where it runs (WSL setup)</th><th>Appium driver</th><th>WSL reaches it via</th><th>macOS-native reaches it via</th></tr></thead>
|
|
1168
|
-
<tbody>
|
|
1169
|
-
<tr><td>MAUI Android</td><td>emulator on the Windows host (Android SDK)</td><td><code>uiautomator2</code></td><td><code>http://localhost:4723</code> (mirrored networking); verifier boots emulator + Appium itself</td><td><code>http://localhost:4723</code> — emulator + Appium run on the Mac itself</td></tr>
|
|
1170
|
-
<tr><td>MAUI iOS</td><td>Simulator on a LAN Mac</td><td><code>xcuitest</code></td><td><code>http://<mac-ip>:4723</code>; Mac must be up or head is <code>⚠ STATIC-ONLY</code></td><td><code>http://localhost:4723</code> — local Simulator (Xcode)</td></tr>
|
|
1171
|
-
<tr><td>MAUI Mac Catalyst</td><td>the same LAN Mac (desktop .app)</td><td><code>mac2</code></td><td><code>http://<mac-ip>:4723</code></td><td><code>http://localhost:4723</code> — the .app runs right here</td></tr>
|
|
1172
|
-
<tr><td>MAUI Windows</td><td>Windows side</td><td>FlaUI / Appium-Windows (unchanged)</td><td><code>winrun</code> / <code>cmd.exe</code></td><td>n/a — this head doesn't exist on a Mac</td></tr>
|
|
1173
|
-
</tbody>
|
|
1174
|
-
</table>
|
|
1175
|
-
<p>Selectors target each control's <code>AutomationId</code> (a coding standard, §10). A head with no registered endpoint in <code>core-config.yaml → runtimeVerification.appium</code>, or an unreachable host, is stamped <code>⚠ STATIC-ONLY</code> for that head — never a faked <code>Verified</code>.</p>
|
|
1176
|
-
|
|
1177
|
-
<div class="panel warn">
|
|
1178
|
-
<strong>Window binding & input discipline (all native heads, especially MAUI Windows):</strong> the driver session is bound to the app under test <em>by identity</em> — the PID the agent launched → that process's top-level window handle (Appium Windows <code>appium:appTopLevelWindow</code> / FlaUI <code>Application.Attach(pid)</code>), or the app package/bundle id on mobile — and every interaction is <strong>element-scoped via <code>AutomationId</code> inside that bound window</strong>, with focus verified before input and handles re-resolved after dialogs. Global keyboard/mouse injection (FlaUI <code>Keyboard.Type</code>, coordinate clicks, <code>SendKeys</code>) is <strong>banned</strong>: it types into whatever window happens to hold focus — historically, a completely different window than the app. Full rules: <code>verify-phase.md §3b</code>.
|
|
1179
|
-
</div>
|
|
1180
|
-
|
|
1181
|
-
<!-- ============================================================ -->
|
|
1182
|
-
<h2 id="permissions">12. Permissions (yolo-except-git-writes)<span class="anchor-link"><a href="#permissions">#</a></span></h2>
|
|
1183
|
-
|
|
1184
|
-
<div class="panel warn">
|
|
1185
|
-
<strong>TechieFlow's <code>*yolo</code> IS the permission switch now (2026-08-21):</strong> <code>*yolo</code> — or the word YOLO in any command, an active Claude Code <code>/goal</code>, or a <code>tf-goal.sh</code> run — writes the flag <code>.tfcore/.session/yolo.json</code>; the PreToolUse hook reads it and stops asking for deletes/<code>sudo</code>, allows read-only git, and the agent runs to completion with no pauses. Git <strong>writes</strong> stay denied in every mode. Rule: <code>.tfcore/tasks/_yolo-mode.md</code>; details in §12a below.
|
|
1186
|
-
</div>
|
|
1187
|
-
|
|
1188
|
-
<p>The pre-built config <strong>auto-allows</strong> Read/Glob/Grep/Edit/Write/MultiEdit and <strong>all Bash</strong> (bare <code>"Bash"</code>) — so create/update/<strong>move</strong> run with zero prompts. <strong>Deletes and <code>sudo</code> ask via the hook</strong> (<em>not</em> a settings <code>ask</code> rule — Claude Code honours a settings <code>ask</code> even in bypass mode and even when a hook says allow, so it could never be switched off). <strong>Denies</strong> catastrophic <code>rm -rf</code> root/home paths <strong>and every <code>git</code>/<code>gh</code> WRITE subcommand</strong> (<code>commit|push|add|reset|checkout|switch|restore|merge|rebase|stash|clean|pull|fetch|…</code>, <code>gh pr|issue|repo|release create|merge|close|…</code>) — git is manual in TechieFlow; agents never write it, so it is a hard deny in every permission mode. Precedence is <code>deny → ask → hook → allow</code>. <em>(Cross-project tip: to let a session work in another app's folder without per-path prompts, add that root to <code>permissions.additionalDirectories</code> in this project's settings.json — keep those machine-specific paths out of any shared template.)</em></p>
|
|
1189
|
-
|
|
1190
|
-
<div class="panel warn">
|
|
1191
|
-
<strong>The git ban is TWO layers, because prefix rules alone leak.</strong> <code>Bash(git commit*)</code> is a literal prefix match — it never sees <code>cd src && git commit</code> or <code>echo done; git add -A</code>, which the bare <code>"Bash"</code> allow would wave straight through. That is exactly how agents kept "accidentally" running git during status updates. So the config also wires a <strong>PreToolUse hook</strong> — <code>.tfcore/hooks/block-git.sh</code> — that parses every Bash call (compound forms, <code>bash -c</code>, <code>eval</code>, <code>$(…)</code>, wrappers like <code>sudo</code>/<code>env</code>/<code>xargs</code>) and classifies each <code>git</code>/<code>gh</code> node as <strong>read</strong> (<code>status</code>/<code>log</code>/<code>diff</code>/<code>show</code>/<code>blame</code>/<code>grep</code>/<code>branch</code>/<code>tag -l</code>/<code>stash list</code>/<code>remote -v</code>/<code>config --get</code>, <code>gh pr list|view</code>) or <strong>write</strong> (everything else). Writes are blocked always; reads are blocked outside YOLO and allowed in YOLO. The block message carries the local-evidence recipe (checklist tables + working-tree files + fresh build) so the agent continues correctly instead of flailing. You still run git yourself: in a separate terminal, or by typing <code>!git …</code> in the session (user-typed bang commands bypass agent tool permissions).
|
|
1192
|
-
</div>
|
|
1193
|
-
|
|
1194
|
-
<div class="panel warn">
|
|
1195
|
-
<strong>Why bare <code>"Bash"</code> and NOT a per-command list:</strong> a <code>Bash(prefix *)</code> rule is a literal prefix match. On WSL the agent can't call plain <code>dotnet</code> (not in PATH) — it calls <code>~/.dotnet/dotnet build</code>, <code>cmd.exe /c "dotnet build"</code>, <code>dotnet dev-certs</code>, or compound <code>cd … && …</code>, none of which match an enumerated <code>Bash(dotnet *)</code>. The old list-everything config prompted ~100× in a single UI phase. Allowing all Bash and restricting only deletes/sudo (ask) and git/gh (deny + hook) is immune to command-path variants.
|
|
1196
|
-
</div>
|
|
1197
|
-
|
|
1198
|
-
<details>
|
|
1199
|
-
<summary>Config (canonical version in scaffold-brownfield.sh / scaffold-greenfield.sh)</summary>
|
|
1200
|
-
<pre><code class="lang-json">{
|
|
1201
|
-
"permissions": {
|
|
1202
|
-
"defaultMode": "acceptEdits",
|
|
1203
|
-
"allow": [
|
|
1204
|
-
"Bash",
|
|
1205
|
-
"Edit", "Write", "MultiEdit", "NotebookEdit",
|
|
1206
|
-
"Read", "Glob", "Grep", "TodoWrite", "WebFetch", "WebSearch", "Task"
|
|
1207
|
-
],
|
|
1208
|
-
"ask": [],
|
|
1209
|
-
"deny": [
|
|
1210
|
-
"Bash(rm -rf /)", "Bash(rm -rf /*)", "Bash(rm -rf ~)", "Bash(rm -rf ~/*)",
|
|
1211
|
-
"Bash(git commit*)", "Bash(git push*)", "Bash(git add*)", "Bash(git reset*)",
|
|
1212
|
-
"Bash(git checkout*)", "Bash(git switch*)", "Bash(git restore*)", "Bash(git merge*)",
|
|
1213
|
-
"… every other git WRITE subcommand (rebase, cherry-pick, revert, clean, pull, fetch, init, clone, …) …",
|
|
1214
|
-
"Bash(gh pr create*)", "Bash(gh pr merge*)", "Bash(gh issue create*)", "… every gh WRITE verb …"
|
|
1215
|
-
]
|
|
1216
|
-
},
|
|
1217
|
-
"hooks": {
|
|
1218
|
-
"PreToolUse": [
|
|
1219
|
-
{ "matcher": "Bash",
|
|
1220
|
-
"hooks": [ { "type": "command",
|
|
1221
|
-
"command": "bash \"$CLAUDE_PROJECT_DIR/.tfcore/hooks/block-git.sh\"" } ] },
|
|
1222
|
-
{ "matcher": "Write|Edit|MultiEdit",
|
|
1223
|
-
"hooks": [ { "type": "command",
|
|
1224
|
-
"command": "bash \"$CLAUDE_PROJECT_DIR/.tfcore/hooks/guard-status.sh\"" },
|
|
1225
|
-
{ "type": "command",
|
|
1226
|
-
"command": "bash \"$CLAUDE_PROJECT_DIR/.tfcore/hooks/guard-verify.sh\"" } ] }
|
|
1227
|
-
]
|
|
1228
|
-
}
|
|
1229
|
-
}</code></pre>
|
|
1230
|
-
</details>
|
|
1231
|
-
|
|
1232
|
-
<div class="panel">
|
|
1233
|
-
<strong>PROJECT-STATUS shape is enforced mechanically too (2026-07-09).</strong> A second PreToolUse hook — <code>.tfcore/hooks/guard-status.sh</code>, matcher <code>Write|Edit|MultiEdit</code> — blocks any write to <code>PROJECT-STATUS.md</code> that violates the crisp fixed-shape snapshot rule: an H2 outside the template's section set (per-run dated sections like <code>## *verify all — coverage matrix (DATE)</code> are the classic disease), a heading naming a command run, a paragraph stuffed into <code>current_phase:</code>, or a full-file write past ~120 lines. The block message tells the agent exactly how to reshape (overwrite the template sections in place, ONE Verification-log row per run, detail into the checklist Remarks). Same philosophy as the git ban: prose rules kept failing, so the harness enforces it. See <code>.tfcore/tasks/_status-update-gate.md</code>.
|
|
1234
|
-
</div>
|
|
1235
|
-
|
|
1236
|
-
<div class="panel">
|
|
1237
|
-
<strong><code>Verified</code> verdicts are enforced mechanically too (2026-07-10).</strong> A third PreToolUse hook — <code>.tfcore/hooks/guard-verify.sh</code>, matcher <code>Write|Edit|MultiEdit</code> — blocks any write to a <code>*-Checklist.md</code> that <em>introduces</em> a <code>Verified</code> status cell unless a same-day run ledger <code>docs/.last-verify.json</code> exists, which only an <em>executed</em> <code>verify-phase</code> run writes (verify-phase §6: boot → scoped tests → §4a data-render + §4b visual-truth gates → ledger → verdicts). This exists because a build orchestrator did its own smoke and wrote the <code>Verified</code> verdicts itself (TrSetup, 2026-07-09) — self-attestation the "chain the verifier" prose didn't stop. A self-smoke's ceiling is <code>Implemented</code> (<code>_smoke-test-policy.md §"Smoke is NOT verify"</code>); <code>*refresh-status</code> may reconcile a lagging Status column to a row's <em>pre-existing</em> dated verdict by writing the ledger with <code>"mode":"reconcile"</code>. Demotions (e.g. <code>Verified → Needs re-verify</code>) are never blocked.
|
|
1238
|
-
</div>
|
|
1239
|
-
|
|
1240
|
-
<div class="panel">
|
|
1241
|
-
<strong>Existing project still prompting?</strong> Just run the normal framework update — <code>update-framework.sh</code> now <strong>refreshes <code>settings.json</code> to this config by default</strong>, so every app stays in sync without any special flag:
|
|
1242
|
-
<p class="small"><strong>WSL (Windows):</strong></p>
|
|
1243
|
-
<pre><code class="lang-bash">/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/app</code></pre>
|
|
1244
|
-
<p class="small"><strong>macOS:</strong></p>
|
|
1245
|
-
<pre><code class="lang-bash">/Volumes/MacD/MyCode/TechieFlow/update-framework.sh /path/to/app</code></pre>
|
|
1246
|
-
It's idempotent (skips the write when already current), backs up any differing old file to <code>settings.json.bak</code>, and never touches <code>settings.local.json</code>. Restart Claude Code afterward. To opt out for a deliberately locked-down project, add <code>--keep-permissions</code>.
|
|
1247
|
-
</div>
|
|
1248
|
-
|
|
1249
|
-
<!-- ============================================================ -->
|
|
1250
|
-
<h3 id="yolo">12a. YOLO / goal mode — "I've given you all the permissions; run until it's done" (2026-08-21)<span class="anchor-link"><a href="#yolo">#</a></span></h3>
|
|
1251
|
-
|
|
1252
|
-
<p><code>*yolo</code> used to be agent-side only (skip elicitation) and the owner still got prompted for every delete and blocked on every git read — which is how a VM goal run took <strong>3 days</strong>, mostly waiting for a human. Now <code>*yolo</code>, the word <strong>YOLO</strong> anywhere in a command, an active Claude Code <strong><code>/goal</code></strong>, or a <code>tf-goal.sh</code> run all mean the same thing, defined in <code>.tfcore/tasks/_yolo-mode.md</code>:</p>
|
|
1253
|
-
|
|
1254
|
-
<table>
|
|
1255
|
-
<thead><tr><th></th><th>Normal</th><th>YOLO</th></tr></thead>
|
|
1256
|
-
<tbody>
|
|
1257
|
-
<tr><td><code>rm</code> / <code>rmdir</code> / <code>sudo</code></td><td>hook asks</td><td><strong>allowed, no prompt</strong> (catastrophic <code>rm -rf /</code>/<code>~</code> still denied)</td></tr>
|
|
1258
|
-
<tr><td>git/gh <strong>reads</strong> (<code>status</code>/<code>log</code>/<code>diff</code>/<code>blame</code>, <code>gh pr view</code>)</td><td>blocked</td><td><strong>allowed</strong></td></tr>
|
|
1259
|
-
<tr><td>git/gh <strong>writes</strong> (<code>commit</code>/<code>push</code>/<code>add</code>/<code>reset</code>/<code>checkout</code>/<code>stash</code>/<code>tag</code>, <code>gh pr create|merge</code>)</td><td>blocked</td><td><strong>blocked — always</strong></td></tr>
|
|
1260
|
-
<tr><td>Elicitation, phase-boundary pauses, "confirm the BRD-N list", "ask once" questions</td><td>pause</td><td><strong>decide the default, record it, continue</strong></td></tr>
|
|
1261
|
-
<tr><td>Build pass scope</td><td>whole checklist (§2b)</td><td>whole checklist <strong>+ automatic FIX loop</strong> on verifier FAIL rows (build-phase §6c, ≤5 cycles)</td></tr>
|
|
1262
|
-
<tr><td>Turn ending</td><td>may hand back</td><td><strong>only</strong> when the goal is complete (<code>tf-yolo.sh done complete</code>) or every remaining REQ is owner-gated (<code>done blocked</code>)</td></tr>
|
|
1263
|
-
</tbody>
|
|
1264
|
-
</table>
|
|
1265
|
-
|
|
1266
|
-
<div class="panel">
|
|
1267
|
-
<strong>Mechanics.</strong> The flag is <code>.tfcore/.session/yolo.json</code> (<code>bash .tfcore/utils/tf-yolo.sh on|off|status</code>; never committed). <code>block-git.sh</code> reads it (plus <code>TF_YOLO=1</code> and the hook payload's <code>permission_mode</code> — Claude Code's <code>bypassPermissions</code>/<code>auto</code> count as YOLO); the OpenCode plugin reads the same flag and auto-approves its <code>rm */sudo *</code> asks via <code>permission.ask</code>. <strong>Why the delete prompt moved out of <code>settings.json</code>:</strong> Claude Code honours a settings <code>ask</code> rule <em>even in bypass mode and even when a hook says allow</em> — so as long as <code>Bash(rm *)</code> sat in <code>ask</code>, no mode could stop the prompt. A hook-issued <code>ask</code> can be withheld; a settings <code>ask</code> cannot.
|
|
1268
|
-
</div>
|
|
1269
|
-
|
|
1270
|
-
<div class="panel warn">
|
|
1271
|
-
<div class="panel warn"><strong>Codex permission difference.</strong> <code>.codex/hooks.json</code> routes shell and file changes through <code>.tfcore/hooks/codex-adapter.py</code>, and <code>.codex/rules/techieflow.rules</code> supplies command policy. Codex blocks every agent-issued <code>git</code> and <code>gh</code> command in normal and YOLO modes, including reads. <code>$techieflow-yolo</code> changes TechieFlow pause/delete behavior but never relaxes this boundary. Trust the repository and inspect <code>/hooks</code> after scaffold/update.</div>
|
|
1272
|
-
|
|
1273
|
-
<strong>Usage limits (5-hour / weekly).</strong> Nothing inside a session can wait a limit out, so the wait lives in a supervisor:
|
|
1274
|
-
<pre><code class="lang-bash">bash .tfcore/utils/tf-goal.sh /path/to/App "Take MyApp to Handoff: build every open REQ, verify all, fix until every row is Verified."
|
|
1275
|
-
bash .tfcore/utils/tf-goal.sh --harness opencode --model opencode-go/kimi-k3 /path/to/App @goal.md
|
|
1276
|
-
bash .tfcore/utils/tf-goal.sh --resume /path/to/App # after a reboot</code></pre>
|
|
1277
|
-
It runs the goal headless (<code>claude -p --permission-mode bypassPermissions</code> / <code>opencode run --auto</code>), parses the reset time from the limit message (<code>resets 7pm (Asia/Kolkata)</code>, <code>resets in 2h 14m</code>, <code>usage limit reached|<epoch></code>, weekly <code>resets Tue 3pm</code>), <strong>sleeps until reset + 15 min</strong> (<code>--buffer-min</code>), logs <code>RETRY AT …</code> to <code>.tfcore/.session/goal.log</code>, and <strong>resumes the same session</strong>. Crashes back off 2 → 30 min; an agent that stops without finishing is re-prompted; it exits only on the agent's sentinel (<code>0</code> complete, <code>3</code> owner-blocked, <code>4</code> max cycles). The agent's side of the bargain is the status gate — every phase ends with PROJECT-STATUS + checklist written, so a resume is lossless.
|
|
1278
|
-
</div>
|
|
1279
|
-
|
|
1280
|
-
<div class="panel">
|
|
1281
|
-
<strong>Build passes are whole-checklist, YOLO or not.</strong> The other 3-day culprit: build-phase runs that implemented a few REQs, wrote "next command: <code>*build-phase</code> for the remaining REQs" and stopped. <code>build-phase.md §2b</code> bans that ending — a pass is done when <strong>every</strong> working-list REQ is ≥ <code>Implemented</code> (or a logged <code>Blocked</code>/owner-gated blocker), the verifier has been chained, and (in YOLO) its FAIL rows have been looped. Long list ⇒ more sub-agent clusters, never a shorter pass. <code>_status-update-gate.md</code> item 5 carries the matching rule for the next-command line.
|
|
1282
|
-
</div>
|
|
1283
|
-
|
|
1284
|
-
<h2 id="agents">13. Agent cheat sheet<span class="anchor-link"><a href="#agents">#</a></span></h2>
|
|
1285
|
-
|
|
1286
|
-
<div class="panel">
|
|
1287
|
-
<strong>These six are the COMPLETE agent roster.</strong> The stock TechieFlow story-flow agents (<code>dev</code>, <code>pm</code>, <code>po</code>, <code>qa</code>, <code>sm</code>, <code>ux-expert</code>) and their story tasks/templates/workflows were trimmed from the scaffold on 2026-06-12 — the compressed flow never used them, and several behaved wrongly in it (wrong stack assumptions, dated <code>docs/qa</code> outputs). They are no longer included; obtain a full story-by-story agent set separately if you ever need that classic flow.
|
|
1288
|
-
<br><br>
|
|
1289
|
-
<strong>Which agent when:</strong>
|
|
1290
|
-
<ul class="tight">
|
|
1291
|
-
<li>Starting or re-documenting a project → <code>/analyst</code> (day-1 tasks, mockups, split-brd).</li>
|
|
1292
|
-
<li>Writing code → <code>/flow-master *build-phase</code> (the ONE unified build — it calls <code>/trblazeui</code> and <code>/techierag</code> as sub-agents; you don't invoke them directly).</li>
|
|
1293
|
-
<li>Proving it works → <code>/verifier</code> (<code>*verify ui|functional|all</code> — filters the one checklist; data + visual gates).</li>
|
|
1294
|
-
<li>Verifier passed but the running UI is broken → <code>/flow-master *fix-issues</code> (drop screenshots; it triages + routes the fix).</li>
|
|
1295
|
-
<li>UAT / production bugs you want analyzed + logged in the checklist, NOT fixed yet → <code>/flow-master *triage-issues</code> (docs-only deliverable; fixing stays your call).</li>
|
|
1296
|
-
<li>Developer code-map (screen → control → service → proc) → <code>/flow-master *devguide</code>.</li>
|
|
1297
|
-
<li>End-user how-to manual (what each screen is for + how to do things) → <code>/flow-master *productguide</code>.</li>
|
|
1298
|
-
<li>Docs/HTML/status/handoff chores → <code>/flow-master</code>.</li>
|
|
1299
|
-
<li>Architecture deep-dive beyond what day-1 produced → <code>/architect</code> (optional).</li>
|
|
1300
|
-
</ul>
|
|
1301
|
-
</div>
|
|
1302
|
-
|
|
1303
|
-
<table>
|
|
1304
|
-
<tr><th>Command</th><th>Role</th><th>Best for</th><th>Writes</th></tr>
|
|
1305
|
-
<tr><td><code>/analyst</code></td><td>Chanakya, business analyst</td><td>Reverse-doc; BRD; Architecture; Coding Standards; <strong>mockups</strong> (<code>*mockups</code>, greenfield); the one Checklist (<code>*split-brd</code>); status init; .editorconfig; CLAUDE.md</td><td><code><APP>-BRD.md</code>, <code><APP>-Architecture.md</code>, <code><APP>-Coding-Standards.md</code>, <code><APP>-UIDesign.md</code> + <code>docs/mockups/*.html</code>, <code><APP>-Checklist.md</code>, <code>PROJECT-STATUS.md</code>, <code>CLAUDE.md</code>, <code>.editorconfig</code></td></tr>
|
|
1306
|
-
<tr><td><code>/trblazeui</code></td><td>Blazor + TrBlazeUI <strong>(library agent — called as a sub-agent by <code>*build-phase</code> / <code>*fix-issues</code>)</strong></td><td>REQ-UI-* per the mockups; reads coding standards</td><td><code>src/</code> (Razor), <code><APP>-TrBlazeUI-Feedback.md</code></td></tr>
|
|
1307
|
-
<tr><td><code>/techierag</code></td><td>TechieRag RAG/LLM <strong>(library agent — called as a sub-agent by <code>*build-phase</code> / <code>*fix-issues</code>)</strong></td><td>REQ-RAG-* items; reads coding standards</td><td><code>src/</code> (RAG services), <code><APP>-TechieRag-Feedback.md</code></td></tr>
|
|
1308
|
-
<tr><td><code>/flow-master</code></td><td>Madhav, master & orchestrator</td><td>The single super-agent. Runs the <strong>unified <code>*build-phase</code></strong> (clusters all open REQs, calls <code>/trblazeui</code> + <code>/techierag</code> as sub-agents, builds REQ-FN-*/REQ-NFR-* itself, self-smokes data+visual, chains the verifier); the <strong><code>*fix-issues</code></strong> bug-fix front door (triages screenshots → routes the fix) and its analyze-only sibling <strong><code>*triage-issues</code></strong> (logs UAT/prod bugs in the checklist, never fixes); HTML renders, status refresh, consolidation, handoff doc; the screen-by-screen Developer Guide (<code>*devguide</code>) and the end-user Product Guide (<code>*productguide</code>)</td><td><code>src/</code>, <code>tests/unit/</code>, <code><APP>-BRD.html</code>, <code><APP>-Architecture.html</code>, <code>PROJECT-STATUS.md/html</code>, <code><APP>-UsageGuide.md</code>, <code><APP>-DevGuide.md/html</code>, <code><APP>-ProductGuide.md/html</code>, <code><APP>-Checklist.md</code> (verdicts), <code><APP>-<Library>-Feedback.md</code> (per-library consolidation)</td></tr>
|
|
1309
|
-
<tr><td><code>/verifier</code></td><td>Vidur, autonomous test runner</td><td>Verifying any scope + standards grep checks + the <strong>render gate (§4a)</strong> (every control listed in the DevGuide renders its data) AND the <strong>visual-truth gate (§4b)</strong> (no overlap, every control in-viewport and non-zero-size at desktop + mobile, screenshot inspected, diffed against the mockup when one exists) AND the <strong>perf gate (§4c)</strong> on any REQ declaring a <code>perf-budget:</code>. A REQ is <code>Verified</code> only if acceptance passes AND data renders AND the screen looks right. <code>Done (pre-existing)</code> gets the full sweep — stays Done only if it runtime-renders + looks right, else <code>Needs re-verify</code>. After each run Vidur writes verdicts to the one checklist AND refreshes the DevGuide's observed render/visual tags.</td><td><code><APP>-Checklist.md</code> Requirements Status table (verdicts), DevGuide observed render/visual tags, <code>tests/playwright/*</code>, <code><APP>-<Library>-Feedback.md</code> (on library bugs — the owning library's file)</td></tr>
|
|
1310
|
-
<tr><td><code>/architect</code></td><td>Solutions architect</td><td>Optional deep arch dive; <code>/analyst</code> does basic architecture by default</td><td><code><APP>-Architecture.md</code> (delegated by analyst, optional)</td></tr>
|
|
1311
|
-
</table>
|
|
1312
|
-
|
|
1313
|
-
<!-- ============================================================ -->
|
|
1314
|
-
<h2 id="quickref">14. Full command reference<span class="anchor-link"><a href="#quickref">#</a></span></h2>
|
|
1315
|
-
|
|
1316
|
-
<div class="panel warn">
|
|
1317
|
-
<strong>Slash-command syntax — Claude Code vs OpenCode:</strong>
|
|
1318
|
-
Claude Code registers TechieFlow-native agents under the path-derived namespace <code>TechieFlow:agents:<name></code>. OpenCode registers the equivalent agents as <code>/flow-master</code>, <code>/flow-analyst</code>, <code>/flow-architect</code>, and <code>/flow-verifier</code>. Each command cell below is an exact, copyable command. Use the macOS framework path where applicable.
|
|
1319
|
-
</div>
|
|
1320
|
-
|
|
1321
|
-
<table>
|
|
1322
|
-
<tr><th>Goal</th><th>Command Purpose / Definition</th><th>Claude Command</th><th>OpenCode Command</th></tr>
|
|
1323
|
-
<tr><td>Scaffold (brownfield)</td><td>Deploy the framework into an existing application.</td><td><pre><code>./scaffold-brownfield.sh /path/to/existing-app</code></pre></td><td><pre><code>./scaffold-brownfield.sh /path/to/existing-app</code></pre></td></tr>
|
|
1324
|
-
<tr><td>Scaffold (greenfield)</td><td>Deploy the framework and starter folders into a new application.</td><td><pre><code>./scaffold-greenfield.sh /path/to/new-app</code></pre></td><td><pre><code>./scaffold-greenfield.sh /path/to/new-app</code></pre></td></tr>
|
|
1325
|
-
<tr><td>Update framework</td><td>Force-refresh framework files in an existing project; preserves work product.</td><td><pre><code>/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/app</code></pre></td><td><pre><code>/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/app</code></pre></td></tr>
|
|
1326
|
-
<tr><td>Render MD → HTML</td><td>Re-render one or more human-facing Markdown documents as HTML.</td><td><pre><code>/generate-html @docs/File.md</code></pre></td><td><pre><code>/generate-html @docs/File.md</code></pre></td></tr>
|
|
1327
|
-
<tr><td>Day-1 brownfield</td><td>Reverse-document an existing app and create the day-1 deliverables, UsageGuide, and DevGuide.</td><td><pre><code>/TechieFlow:agents:analyst *day1-brownfield {AppName}</code></pre></td><td><pre><code>/flow-analyst *day1-brownfield {AppName}</code></pre></td></tr>
|
|
1328
|
-
<tr><td>Day-1 greenfield</td><td>Create the BRD, Architecture, Coding Standards, status, CLAUDE.md, and UI mockups for a new app.</td><td><pre><code>/TechieFlow:agents:analyst *day1-greenfield {AppName}</code></pre></td><td><pre><code>/flow-analyst *day1-greenfield {AppName}</code></pre></td></tr>
|
|
1329
|
-
<tr><td>Re-render workflow docs</td><td>Refresh the BRD, Architecture, and PROJECT-STATUS HTML documents.</td><td><pre><code>/TechieFlow:agents:flow-master *render-workflow-docs {AppName}</code></pre></td><td><pre><code>/flow-master *render-workflow-docs {AppName}</code></pre></td></tr>
|
|
1330
|
-
<tr><td>Greenfield UI mockups</td><td>Create or update the per-screen UI design specification and TrBlazeUI-styled mockups.</td><td><pre><code>/TechieFlow:agents:analyst *mockups {AppName}</code></pre></td><td><pre><code>/flow-analyst *mockups {AppName}</code></pre></td></tr>
|
|
1331
|
-
<tr><td>Split BRD → Checklist</td><td>Turn BRD items into the single Checklist with REQ-UI/FN/RAG/NFR requirements.</td><td><pre><code>/TechieFlow:agents:analyst *split-brd {AppName}</code></pre></td><td><pre><code>/flow-analyst *split-brd {AppName}</code></pre></td></tr>
|
|
1332
|
-
<tr><td>Amend docs</td><td>Apply an incremental requirements or architecture change without regenerating unchanged documents.</td><td><pre><code>/TechieFlow:agents:analyst *amend-docs {AppName} "<what changed>"</code></pre></td><td><pre><code>/flow-analyst *amend-docs {AppName} "<what changed>"</code></pre></td></tr>
|
|
1333
|
-
<tr><td>Build — unified phase</td><td>Build all open REQs, route UI/RAG work to library agents, self-smoke, and chain verification.</td><td><pre><code>/TechieFlow:agents:flow-master *build-phase {AppName}</code></pre></td><td><pre><code>/flow-master *build-phase {AppName}</code></pre></td></tr>
|
|
1334
|
-
<tr><td>Fix issues</td><td>Reproduce screenshot-reported issues, route fixes, then re-smoke and re-verify.</td><td><pre><code>/TechieFlow:agents:flow-master *fix-issues {AppName} {folder}</code></pre></td><td><pre><code>/flow-master *fix-issues {AppName} {folder}</code></pre></td></tr>
|
|
1335
|
-
<tr><td>Triage UAT/production bugs</td><td>Analyze and log bugs without editing code; optionally regression-verify sibling features.</td><td><pre><code>/TechieFlow:agents:flow-master *triage-issues {AppName} {evidence} [verify]</code></pre></td><td><pre><code>/flow-master *triage-issues {AppName} {evidence} [verify]</code></pre></td></tr>
|
|
1336
|
-
<tr><td>Verify gates and standards</td><td>Run acceptance tests, standards greps, data-render, visual-truth, and applicable performance gates.</td><td><pre><code>/TechieFlow:agents:verifier *verify <scope></code></pre></td><td><pre><code>/flow-verifier *verify <scope></code></pre></td></tr>
|
|
1337
|
-
<tr><td>End of session</td><td>Update project status and regenerate its HTML representation.</td><td><pre><code>/TechieFlow:agents:flow-master Update PROJECT-STATUS.md (phase, next, log); regenerate PROJECT-STATUS.html.</code></pre></td><td><pre><code>/flow-master Update PROJECT-STATUS.md (phase, next, log); regenerate PROJECT-STATUS.html.</code></pre></td></tr>
|
|
1338
|
-
<tr><td>Final handoff</td><td>Generate the final UsageGuide, DevGuide, status, and library-feedback consolidation.</td><td><pre><code>/TechieFlow:agents:flow-master *handoff-phase {AppName}</code></pre></td><td><pre><code>/flow-master *handoff-phase {AppName}</code></pre></td></tr>
|
|
1339
|
-
<tr><td>Generate / refresh Developer Guide</td><td>Map the implemented screens, observe the running app, and reconcile the Developer Guide.</td><td><pre><code>/TechieFlow:agents:flow-master *devguide {AppName}</code></pre></td><td><pre><code>/flow-master *devguide {AppName}</code></pre></td></tr>
|
|
1340
|
-
<tr><td>Generate / refresh Product Guide</td><td>Generate the screenshot-illustrated, task-oriented manual for external users.</td><td><pre><code>/TechieFlow:agents:flow-master *productguide {AppName} [scope] [--update]</code></pre></td><td><pre><code>/flow-master *productguide {AppName} [scope] [--update]</code></pre></td></tr>
|
|
1341
|
-
<tr><td>Token efficiency guide</td><td>Open the framework guidance for reducing unnecessary AI context and token usage.</td><td><pre><code>less .tfcore/TOKEN-GUIDE.md</code></pre></td><td><pre><code>less .tfcore/TOKEN-GUIDE.md</code></pre></td></tr>
|
|
1342
|
-
<tr><td>Recover broken session</td><td>Rebuild PROJECT-STATUS from ground truth after an interrupted phase.</td><td><pre><code>/TechieFlow:agents:flow-master *refresh-status {AppName}</code></pre></td><td><pre><code>/flow-master *refresh-status {AppName}</code></pre></td></tr>
|
|
1343
|
-
<tr><td>MAUI build + test</td><td>Build and test the MAUI project through the Windows bridge or natively on macOS.</td><td><pre><code>winrun "dotnet build && dotnet test"</code></pre></td><td><pre><code>winrun "dotnet build && dotnet test"</code></pre></td></tr>
|
|
1344
|
-
<tr><td>Resume project</td><td>Check the working tree and perform a fresh build before continuing.</td><td><pre><code>git status && dotnet build</code></pre></td><td><pre><code>git status && dotnet build</code></pre></td></tr>
|
|
1345
|
-
<tr><td>Log a miss (<a href="#misses">§17</a>)</td><td>Record one missed requirement as telemetry + a checklist line. No boot, no repro, no code.</td><td><pre><code>/TechieFlow:agents:flow-master *log-miss {AppName} "{what was missed}"</code></pre></td><td><pre><code>/flow-master *log-miss {AppName} "{what was missed}"</code></pre></td></tr>
|
|
1346
|
-
<tr><td>Development telemetry report</td><td>Generate the aggregated development metrics report.</td><td><pre><code>/TechieFlow:agents:flow-master *metrics {AppName}</code></pre></td><td><pre><code>/flow-master *metrics {AppName}</code></pre></td></tr>
|
|
1347
|
-
<tr><td>Telemetry quick look</td><td>Print the read-only telemetry report directly in the terminal.</td><td><pre><code>.tfcore/telemetry/tf-metrics.sh --report .</code></pre></td><td><pre><code>.tfcore/telemetry/tf-metrics.sh --report .</code></pre></td></tr>
|
|
1348
|
-
</table>
|
|
1349
|
-
|
|
1350
|
-
<table class="quickref-legacy">
|
|
1351
|
-
<tr><th>Goal</th><th>Command (Claude Code form)</th></tr>
|
|
1352
|
-
<tr><td>Scaffold (brownfield)</td><td><code>./scaffold-brownfield.sh /path/to/existing-app</code> (or run from the template repo)</td></tr>
|
|
1353
|
-
<tr><td>Scaffold (greenfield)</td><td><code>./scaffold-greenfield.sh /path/to/new-app</code> (or run from the template repo)</td></tr>
|
|
1354
|
-
<tr><td>Update framework in existing project (<a href="#update-framework">§3</a>)</td><td>WSL: <code>/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/app</code> · macOS: <code>/Volumes/MacD/MyCode/TechieFlow/update-framework.sh /path/to/app</code> (add <code>--dry-run</code> to preview; restart Claude Code after)</td></tr>
|
|
1355
|
-
<tr><td>Render any MD → HTML (ad-hoc)</td><td><code>/generate-html @docs/File.md</code> (multiple <code>@paths</code> ok; <code>@dir/</code> = top-level *.md, non-recursive; day-1 auto-renders its own docs — this is for re-renders after edits)</td></tr>
|
|
1356
|
-
<tr><td>Day-1 brownfield (6 deliverables + UsageGuide + DevGuide)</td><td><code>/TechieFlow:agents:analyst *day1-brownfield {AppName}</code></td></tr>
|
|
1357
|
-
<tr><td>Day-1 greenfield (6 deliverables)</td><td><code>/TechieFlow:agents:analyst *day1-greenfield {AppName}</code></td></tr>
|
|
1358
|
-
<tr><td>Re-render BRD/Architecture/Status trio (day-1 renders these automatically)</td><td><code>/TechieFlow:agents:flow-master *render-workflow-docs {AppName}</code></td></tr>
|
|
1359
|
-
<tr><td>Greenfield UI mockups (<a href="#mockups">§7.10</a>)</td><td><code>/TechieFlow:agents:analyst *mockups {AppName}</code> — per-screen UIDesign spec + TrBlazeUI-styled <code>docs/mockups/*.html</code>; auto-run at greenfield day-1; <code>--update</code> refreshes changed screens. The visual contract the build matches and the verifier diffs against.</td></tr>
|
|
1360
|
-
<tr><td>Split BRD → the one Checklist</td><td><code>/TechieFlow:agents:analyst *split-brd {AppName}</code> — writes <code>docs/{AppName}-Checklist.md</code> (all REQ-UI/FN/RAG/NFR-* in one Requirements Status table).</td></tr>
|
|
1361
|
-
<tr><td><strong>Amend docs as the project evolves</strong> (<a href="#evolving-docs">§7.9</a>)</td><td><code>/TechieFlow:agents:analyst *amend-docs {AppName} "<what changed>"</code> (or <code>/flow-master</code>) — surgically updates BRD + Architecture in place (append-only IDs), ripples to PROJECT-STATUS / BRD §4 / the checklist, re-renders. Incremental alternative to re-running day-1.</td></tr>
|
|
1362
|
-
<tr><td><strong>Build — ONE unified phase</strong> (chains self-smoke + verifier)</td><td><code>/TechieFlow:agents:flow-master *build-phase {AppName}</code> (OpenCode: <code>/flow-master *build-phase {AppName}</code>) — clusters all open REQs, calls <code>/trblazeui</code> (REQ-UI-*, from the mockups) and <code>/techierag</code> (REQ-RAG-*) as sub-agents, builds REQ-FN-*/REQ-NFR-* itself, self-smokes (data + visual), then chains the verifier. Re-run for FIX mode on flagged REQs. (The old separate UI / RAG / functional build commands are dissolved into this one.)</td></tr>
|
|
1363
|
-
<tr><td><strong>Fix issues found by running the app</strong> (<a href="#fix-issues">§7.11</a>)</td><td><code>/TechieFlow:agents:flow-master *fix-issues {AppName} {folder}</code> — drop a folder of screenshots (+ optional <code>bugs.md</code>); flow-master reproduces each with Playwright, triages (layout/data/logic/RAG), fans the fix to the right builder (trblazeui / its subagents / techierag), re-smokes + re-verifies, updates DevGuide + checklist + PROJECT-STATUS. The answer to "verifier passed but the UI is broken."</td></tr>
|
|
1364
|
-
<tr><td><strong>Analyze + log UAT/production bugs WITHOUT fixing</strong> (<a href="#triage-issues">§7.12</a>)</td><td><code>/TechieFlow:agents:flow-master *triage-issues {AppName} {evidence} [verify]</code> — screenshots folder and/or a written bug list; flow-master reproduces each with Playwright, demotes regressed REQs to <code>Needs re-verify</code> (dated <code>⚠ UAT bug</code> remarks), adds new <code>Planned</code> rows for unspecified defects, optionally re-verifies sibling features (<code>verify</code>), updates DevGuide known-issues + PROJECT-STATUS (next command = the <code>*fix-issues</code> pointer). Never edits code — fixing stays your decision.</td></tr>
|
|
1365
|
-
<tr><td>Verify + standards greps + data, visual & perf gates</td><td><code>/TechieFlow:agents:verifier *verify <scope></code> — scope is <code>ui</code> | <code>functional</code> | <code>all</code> | explicit REQ IDs; <strong>filters the one checklist by REQ prefix</strong> (no separate file). Runs standards-compliance greps, acceptance tests, the <strong>render gate</strong> (verify-phase §4a: every control renders its data) AND the <strong>visual-truth gate</strong> (§4b: no overlap, every control in-viewport and non-zero-size at desktop + mobile, screenshot inspected, mockup-diffed where one exists) and, for any REQ declaring a <code>perf-budget:</code>, the <strong>perf gate</strong> (§4c). A REQ is <code>Verified</code> only if acceptance passes AND data renders AND the screen looks right. <code>Done (pre-existing)</code> gets the full sweep. Verdicts land in the checklist; Vidur also refreshes the DevGuide's observed render/visual tags.</td></tr>
|
|
1366
|
-
<tr><td>End-of-session</td><td><code>/TechieFlow:agents:flow-master Update PROJECT-STATUS.md (phase, next, log); regenerate PROJECT-STATUS.html.</code></td></tr>
|
|
1367
|
-
<tr><td>Final handoff (incl. DevGuide)</td><td><code>/TechieFlow:agents:flow-master *handoff-phase {AppName}</code></td></tr>
|
|
1368
|
-
<tr><td>Generate / refresh Developer Guide</td><td><code>/TechieFlow:agents:flow-master *devguide {AppName}</code> — generates <code>docs/{AppName}-DevGuide.md</code> + <code>.html</code> (split per role for large apps) via the 3-pass MAP → OBSERVE → RECONCILE model (§6). Add <code>--update</code> to refresh only changed screens. Stamped <code>⚠ STATIC-ONLY</code> if the app cannot be booted. Auto-run at handoff; re-runnable anytime. The DevGuide is the verifier's per-control test map — see §6.</td></tr>
|
|
1369
|
-
<tr><td>Generate / refresh end-user Product Guide (<a href="#docs">§6</a>)</td><td><code>/TechieFlow:agents:flow-master *productguide {AppName} [scope] [--update]</code> — the screenshot-illustrated, task-oriented how-to manual for EXTERNAL users (what each screen is for + how to do things). Reuses the DevGuide's screen inventory + the screenshots under <code>docs/screenshots/<APP>/</code> (re-shoots any missing via the verifier render sweep); fans out per role, splitting large apps into <code>docs/productguides/</code>. <strong>Always emits MD + HTML.</strong> On-demand; <code>--update</code> refreshes only changed screens. The user-facing sibling of the DevGuide.</td></tr>
|
|
1370
|
-
<tr><td>Token efficiency guide</td><td><code>.tfcore/TOKEN-GUIDE.md</code> — ships with every project. Explains where AI tokens go and the levers to keep usage low (don't load whole docs/repos; checklists markdown-only; fan out to subagents; incremental updates via <code>*amend-docs</code> / <code>*devguide --update</code>; recover with <code>*refresh-status</code> instead of re-running).</td></tr>
|
|
1371
|
-
<tr><td><strong>Recover broken session</strong> (status stale/wrong)</td><td><code>/TechieFlow:agents:flow-master *refresh-status {AppName}</code> — rebuilds PROJECT-STATUS from ground truth (checklist tables + working-tree files & mtimes + fresh build; no git — git is manual) when a phase died before its status gate ran. Add <code>verify</code> to re-verify ambiguous REQs. Never edits source. See §8a.</td></tr>
|
|
1372
|
-
<tr><td>MAUI build+test</td><td>WSL: <code>winrun "dotnet build && dotnet test"</code> · macOS: <code>dotnet build && dotnet test</code> (native, no bridge — <a href="#wsl-runtime">§11</a>)</td></tr>
|
|
1373
|
-
<tr><td>Resume cold project (status trustworthy)</td><td>Open <code>PROJECT-STATUS.html</code> + <code><APP>-BRD.html</code> + <code><APP>-Architecture.html</code> → <code>git status && dotnet build</code> → <code>/TechieFlow:agents:verifier</code> re-verify → execute "Next command". If the last session was cut off mid-phase, run <code>*refresh-status</code> first (row above).</td></tr>
|
|
1374
|
-
<tr><td>An agent missed something (<a href="#misses">§17</a>)</td><td><code>/TechieFlow:agents:flow-master *log-miss {AppName} "{what was missed}"</code> — a record + the checklist line, in seconds</td></tr>
|
|
1375
|
-
<tr><td>Development telemetry report (<a href="#telemetry">§17</a>)</td><td><code>/TechieFlow:agents:flow-master *metrics {AppName}</code> — writes <code>docs/metrics/METRICS.md</code> + <code>.html</code></td></tr>
|
|
1376
|
-
<tr><td>Telemetry, quick look in the terminal (<a href="#telemetry">§17</a>)</td><td><code>cd /path/to/app && .tfcore/telemetry/tf-metrics.sh --report .</code> — read-only, no agent</td></tr>
|
|
1377
|
-
</table>
|
|
1378
|
-
|
|
1379
|
-
<h3>Codex command equivalents</h3>
|
|
1380
|
-
<p>Codex exposes workflows as project skills rather than literal Claude/OpenCode slash commands. Type the <code>$techieflow-*</code> name with its arguments; scaffold/update generates these skills from <code>.tfcore/tasks/</code>.</p>
|
|
1381
|
-
<table>
|
|
1382
|
-
<tr><th>Workflow</th><th>Codex command</th></tr>
|
|
1383
|
-
<tr><td>Day 1</td><td><code>$techieflow-day1-brownfield {AppName}</code> / <code>$techieflow-day1-greenfield {AppName}</code></td></tr>
|
|
1384
|
-
<tr><td>Requirements</td><td><code>$techieflow-author-brd {AppName}</code> / <code>$techieflow-amend-docs {AppName} "<change>"</code></td></tr>
|
|
1385
|
-
<tr><td>Design / checklist</td><td><code>$techieflow-mockups {AppName}</code> / <code>$techieflow-split-brd {AppName}</code></td></tr>
|
|
1386
|
-
<tr><td>Build / verify</td><td><code>$techieflow-build {AppName}</code> / <code>$techieflow-verify all {AppName}</code></td></tr>
|
|
1387
|
-
<tr><td>Fix / triage</td><td><code>$techieflow-fix-issues {AppName} {evidence}</code> / <code>$techieflow-triage-issues {AppName} {evidence}</code></td></tr>
|
|
1388
|
-
<tr><td>Guides</td><td><code>$techieflow-devguide {AppName}</code> / <code>$techieflow-productguide {AppName}</code></td></tr>
|
|
1389
|
-
<tr><td>Handoff / recovery</td><td><code>$techieflow-handoff {AppName}</code> / <code>$techieflow-refresh-status {AppName}</code></td></tr>
|
|
1390
|
-
<tr><td>Rendering</td><td><code>$techieflow-render-workflow-docs {AppName}</code> / <code>$techieflow-generate-html @docs/File.md</code></td></tr>
|
|
1391
|
-
<tr><td>Metrics / YOLO</td><td><code>$techieflow-metrics-report {AppName}</code> / <code>$techieflow-yolo on|off|status</code></td></tr>
|
|
1392
|
-
<tr><td>Unattended goal</td><td><code>bash .tfcore/utils/tf-goal.sh --harness codex <app-dir> "<goal>"</code></td></tr>
|
|
1393
|
-
</table>
|
|
1394
|
-
<div class="panel warn"><strong>Codex boundary:</strong> trust the repository and review <code>/hooks</code>. Every agent-issued <code>git</code> and <code>gh</code> command stays forbidden even in YOLO. The supervisor uses <code>codex exec --json --sandbox workspace-write -c approval_policy="never"</code> and resumes its recorded session after limits or restarts.</div>
|
|
1395
|
-
|
|
1396
|
-
<p><small>The trblazeui and techierag personas are NuGet-deployed to <code>.claude/<name>.md</code> and <code>.opencode/command/<name>.md</code>. Claude Code only scans <code>.claude/commands/</code>, so the scaffold/update scripts copy them to <code>.claude/commands/<name>.md</code> (the short <code>/trblazeui</code> <code>/techierag</code> forms then work). If the short form is missing: <code>dotnet build</code>, then re-run <code>update-framework.sh</code>. Library maintainers must update the package source files listed in <code>docs/TechieFlow-Library-Persona-Propagation.md</code>; consumer copies are not the source of truth.</small></p>
|
|
1397
|
-
|
|
1398
|
-
<!-- ============================================================ -->
|
|
1399
|
-
<h2 id="faq">15. FAQ & gotchas<span class="anchor-link"><a href="#faq">#</a></span></h2>
|
|
1400
|
-
|
|
1401
|
-
<details>
|
|
1402
|
-
<summary>Rendering docs to HTML burns enormous tokens every phase. Is the model really writing all that by hand?</summary>
|
|
1403
|
-
<p><strong>It was, until 2026-08-27. It no longer should be.</strong> There was no renderer in the framework: <code>html-render-shell.md</code> was a 494-line prose specification, and both render tasks told the agent to implement it by hand (<em>“Use the Write tool — never bash heredocs”</em>). One phase that re-rendered four documents emitted ~300 KB of HTML, roughly <strong>75–80k output tokens</strong>, for documents whose content barely changed — and <code>PROJECT-STATUS.html</code> is mandatory at the end of <em>every</em> phase.</p>
|
|
1404
|
-
<p>There is now one command:</p>
|
|
1405
|
-
<pre><code class="language-bash">bash .tfcore/utils/tf-render-html.sh docs/MyApp-BRD.md PROJECT-STATUS.md</code></pre>
|
|
1406
|
-
<p>It writes a sibling <code>.html</code> for each input and is dependency-free — Python 3 standard library only, no pandoc, no node, no pip. Crucially it <strong>extracts the §2 CSS, §3 theme script and §7 JS out of <code>html-render-shell.md</code> at render time</strong> rather than duplicating them, so the shell cannot drift from its own documentation: edit the spec and the next render picks it up.</p>
|
|
1407
|
-
<p>Three problems went away with the tokens. <strong>Drift</strong> — hand-authored output was never reproducible, and the old instruction to “verify each HTML mentally” was self-review by the model that had just written it. <strong>Truncation</strong> — a 130 KB file emitted in one generation could silently cut off, and no gate read rendered output. <strong>An unenforceable rule</strong> — projects quietly wrote their own renderers instead, diverging from the shell.</p>
|
|
1408
|
-
<p>The checklist ban is now <em>mechanical</em>: passing a <code>*-Checklist.md</code> is refused with exit 2 rather than depending on the agent remembering. The renderer also runs the §5.5 Mermaid self-check and warns about unquoted flowchart labels or a reserved <code>end</code> node id — those are defects in the <strong>source markdown</strong>; fix the diagram and re-render, never edit generated HTML.</p>
|
|
1409
|
-
<p><code>html-render-shell.md</code> remains the specification. Read it to understand or change the shell — you no longer need to read it to render. Reported by the TfLens team as TF-003; it was a gap, not a regression (no task ever referenced a missing script).</p>
|
|
1410
|
-
</details>
|
|
1411
|
-
|
|
1412
|
-
<details>
|
|
1413
|
-
<summary>Does <code>update-framework.sh</code> update the root <code>opencode.jsonc</code>? Mine looks very old.</summary>
|
|
1414
|
-
<p><strong>It does now — it did not until 2026-08-27, and that was a real defect.</strong> The 2026-08-20 two-file split moved framework config into the framework-owned <code>.opencode/opencode.jsonc</code> (refreshed every run, wins on conflicting keys) and demoted the root file to project-only keys: extra agents, MCP, LSP. It was then preserved unconditionally, forever.</p>
|
|
1415
|
-
<p>A survey of all ten apps carrying the file found that <strong>none of them has any project-only content</strong> — no project agent, no project command, no <code>mcp</code> or <code>lsp</code> block. Nine held a 138–154 line copy of a template that had grown to 925 lines, and all nine were missing the <code>trblazeui</code>/<code>techierag</code> agent blocks. So the preserve rule protected nothing while guaranteeing the file rotted.</p>
|
|
1416
|
-
<p>Worse, two apps still wired <code>build-ui-phase</code> / <code>build-rag-phase</code> / <code>build-functional-phase</code> — commands dissolved on 2026-06-26 — as <code>{file:}</code> references to task files that no longer exist. <strong>A dead <code>{file:}</code> ref hard-fails OpenCode’s entire config load</strong>, so those repos were silently loading no framework agents or commands at all.</p>
|
|
1417
|
-
<p>The root file now refreshes the same way <code>.claude/settings.json</code> does: replaced when nothing project-owned would be lost (old file kept as <code>opencode.jsonc.bak</code>), preserved — with the project-only keys named in the output — when there is, and every dead <code>{file:}</code> ref reported either way.</p>
|
|
1418
|
-
</details>
|
|
1419
|
-
|
|
1420
|
-
<details>
|
|
1421
|
-
<summary>An agent says a framework file — <code>tf-metrics.sh</code>, a task, a template — is “not present anywhere in this tree”. It obviously is. Why?</summary>
|
|
1422
|
-
<p><strong>Because the framework is invisible to every default file-search tool, and until 2026-08-27 nothing told the agents that.</strong> Two independent filters stack, and you have to defeat both:</p>
|
|
1423
|
-
<ul>
|
|
1424
|
-
<li><code>.tfcore/</code>, <code>.claude/</code>, <code>.codex/</code>, <code>.opencode/</code> and <code>.agents/skills/</code> are <strong>hidden dot-directories</strong> — ripgrep (which backs the agents’ Grep tool) skips hidden paths by default.</li>
|
|
1425
|
-
<li>They are also in the <strong>managed <code>.gitignore</code> block</strong> that the scaffolders write into every app (<a href="#scaffolding">§3</a>) — and ripgrep honours <code>.gitignore</code> by default too.</li>
|
|
1426
|
-
</ul>
|
|
1427
|
-
<p>So <code>rg --hidden</code> is <em>not</em> enough in an app repo; it takes <code>rg --hidden --no-ignore</code> (<code>rg -uu</code>). And because nothing under <code>.tfcore/</code> is <em>tracked</em> in an app, <code>git grep</code> and <code>git ls-files</code> return zero rows as well. An agent that globs for a filename gets nothing back and reasonably concludes the framework is not installed.</p>
|
|
1428
|
-
<p><strong>This is not a bug to fix by un-ignoring the framework.</strong> The ignore block is deliberate and load-bearing — the deployed copies are re-synced from the template by <code>update-framework.sh</code> and must never be committed in an app (<a href="#scaffolding">§3</a>). The fix is on the agent side: every framework file has exactly one canonical path, and whatever needs it names that path, so existence is confirmed by <strong>reading the literal path</strong>, never by searching for the name. That rule now lives in <code>.tfcore/tasks/_status-update-gate.md</code> §“The framework tree is INVISIBLE to search” (a shared include, so it reaches every checklist-executing task), is restated in <a href="#verify">verify-phase</a>’s verdict rules, and ships in the <code>AGENTS.md</code> / <code>CLAUDE.md</code> hard rules for new apps.</p>
|
|
1429
|
-
<p><strong>Why it matters more than a wasted search:</strong> the false negative does not stay in the transcript. It gets written into a checklist Remarks cell, a BRD §4 status row, or a blocker — and the next agent reads it as established fact and inherits the conclusion. A verify pass can close a gate that was never actually blocked.</p>
|
|
1430
|
-
<p><strong>When it really <em>is</em> missing:</strong> a fresh clone genuinely has no <code>.tfcore/</code>, because it was never committed. That repo needs <code>update-framework.sh <repo></code> run once <em>on that machine</em> (see <a href="#platforms">§16</a>). One command — never a reason to reimplement what the missing file does.</p>
|
|
1431
|
-
</details>
|
|
1432
|
-
|
|
1433
|
-
<details>
|
|
1434
|
-
<summary>My repo root is full of <code>test-results/</code>, <code>test-results-cluster-a/</code> or <code>scripts-cluster-b/</code> folders. Why?</summary>
|
|
1435
|
-
<p>That was a real defect, fixed 2026-08-10. Playwright writes run artifacts to <code>test-results/</code> by default, and a verify fan-out that wanted per-cluster isolation invented <em>siblings</em> — <code>test-results-cluster-a/</code>, <code>test-results-tr054/</code>, one per run, forever. The ignore block only carried the bare <code>test-results/</code>, which does <strong>not</strong> match the suffixed names, so they surfaced untracked at every commit — exactly the triage burden the block exists to prevent.</p>
|
|
1436
|
-
<p>The fix: <a href="#verify">verify-phase</a> §1 now pins <code>outputDir: './tests/.artifacts/test-results'</code> in <code>playwright.config.ts</code> (creating the config if absent, <em>editing</em> it if it lacks the setting), bans repo-root artifact directories and <code>--output test-results-<slug></code> outright, and permits isolation only as a subfolder (<code>--output tests/.artifacts/<slug></code>). <code>tests/.artifacts/</code> is in the managed ignore block, and Playwright wipes it at the start of each run, so it stops growing. Legacy root-level dirs are deleted by verify-phase §1 on its next pass, or by you right now — they are pure machine output and fully regenerable.</p>
|
|
1437
|
-
<p><strong>The <code>scripts-cluster-*/</code> variant was the same bug one layer up, fixed the same day.</strong> That first fix pinned where the tools <em>write</em> but never said where an agent should put the harness scripts it <em>authors</em>, so the next fan-out simply moved the litter: four <code>scripts-cluster-b|f|g|i/</code> folders holding hand-written <code>smoke-*.mjs</code>. Those scripts also imported the Playwright <em>library</em> directly, which bypasses <code>playwright.config.ts</code> entirely — so the <code>outputDir</code> pin could never have reached them, and one of them hardcoded an absolute path to a <code>test-results-cluster-b</code> it created itself. The rule now covers both halves: run harnesses go in <code>tests/.artifacts/harness/</code>, <code>/scripts-*/</code> is in the ignore block, and verify-phase §1 sweeps root-level <code>scripts-*/</code> alongside <code>test-results*/</code>. <strong>Your own <code>scripts/</code> folder is safe</strong> — the pattern requires the hyphen and the root anchor, and the sweep excludes it explicitly.</p>
|
|
1438
|
-
<p><strong>What are the screenshots even for?</strong> Failure evidence with a session lifetime: <code>screenshot: 'only-on-failure'</code> means a passing run produces almost nothing, and the ones a failing run produces exist so §6 can cite a path in a checklist Remark <em>today</em>. They are never work product and never committed. The screenshots that <em>are</em> deliberately kept and tracked are the DevGuide's reviewed set under <code>docs/screenshots/<APP>/</code> — a different thing entirely.</p>
|
|
1439
|
-
</details>
|
|
1440
|
-
|
|
1441
|
-
<details>
|
|
1442
|
-
<summary><code>docs/metrics/commits.jsonl</code> appeared in every repo and it's empty. Bug?</summary>
|
|
1443
|
-
<p>By design. <code>install-metrics.sh</code> seeds all five streams so every repo has the same shape and no writer has to check whether its file exists. Each then fills only when its event happens: <code>gates.jsonl</code> on the first <code>*verify</code>, <code>runs.jsonl</code> on the first framework command, <code>sessions.jsonl</code> when a session ends, and <code>commits.jsonl</code> on <strong>your first commit after telemetry was installed</strong>. Commit the empty files with everything else: a tracked empty stream makes the first record a one-line diff instead of a file appearing from nowhere. See <a href="#telemetry">§17</a>.</p>
|
|
1444
|
-
</details>
|
|
1445
|
-
|
|
1446
|
-
<details>
|
|
1447
|
-
<summary>I committed everything, and <code>commits.jsonl</code> immediately shows as modified again.</summary>
|
|
1448
|
-
<p><strong>That repo is still on the retired <code>post-commit</code> hook.</strong> Run <code>update-framework.sh <repo></code> on that machine; the refresh installs the <code>pre-commit</code> hook and removes the old one.</p>
|
|
1449
|
-
<p>Why it happened: <code>post-commit</code> could only describe commit N once N existed, so its line could never be <em>inside</em> N. The file was dirty the instant every commit finished — permanently, with no reachable clean state, because committing the pending line creates a new commit whose record is then pending in turn. On a repo worked from two machines it also blocked <code>git pull</code> whenever that file had changed upstream.</p>
|
|
1450
|
-
<p>Since 2026-08-11 the record is written <em>before</em> the commit is sealed and staged into it, so the tree is clean when the commit finishes. The lag is unchanged — HEAD is still the previous commit at that point, so commit N's own record ships in N+1 — but it is <em>committed</em> rather than <em>pending</em>. See <a href="#telemetry">§17</a>.</p>
|
|
1451
|
-
</details>
|
|
1452
|
-
|
|
1453
|
-
<details>
|
|
1454
|
-
<summary>So if I pull on another machine — or set the code up on a brand-new one — do I lose that last unpushed line?</summary>
|
|
1455
|
-
<p><strong>No.</strong> That line describes a commit, and the commit itself <em>is</em> pushed. The other machine pulls it, and its hook walks <code>git log</code>, sees a commit the file doesn't carry, and writes the record. On a brand-new machine the same thing happens at a larger scale: <code>git log</code> holds the entire history, so one reconcile reproduces every record. This is exactly why the stream is maintained as a <em>projection of the log</em> rather than as an independent ledger — the log is the thing git already replicates, so it is the only thing that has to survive.</p>
|
|
1456
|
-
<p>To fill a machine in immediately instead of waiting for its next commit: <code>.tfcore/telemetry/tf-metrics.sh --backfill-commits .</code></p>
|
|
1457
|
-
<p><strong>The flip side, which is handled:</strong> the original machine also wrote that record locally. Once both versions are in the repo, <code>merge=union</code> keeps <em>both</em> — the same <code>sha</code> twice. That is the deliberate trade: union merge guarantees no record is ever dropped, and <code>tf-metrics.sh</code> de-duplicates commits on <code>sha</code> at read time (reporting how many it collapsed) so nothing is ever counted twice. Only <code>commits.jsonl</code> can duplicate this way; runs/gates/sessions record events that happen on one machine and can't be reconstructed elsewhere.</p>
|
|
1458
|
-
<p>Since the record ships inside a commit rather than sitting pending afterwards, the file matches HEAD between commits — nothing to stage before a pull.</p>
|
|
1459
|
-
</details>
|
|
1460
|
-
|
|
1461
|
-
<details>
|
|
1462
|
-
<summary>I work on the same repo from two machines. How do I collect the telemetry from both?</summary>
|
|
1463
|
-
<p><strong>You don't — it collects itself.</strong> The streams are tracked files, so they travel with <code>push</code>/<code>pull</code>. Two things make that work without friction, and the framework refresh sets up both:</p>
|
|
1464
|
-
<ul>
|
|
1465
|
-
<li><code>.gitattributes</code> gives <code>docs/metrics/*.jsonl</code> <strong><code>merge=union</code></strong>. Two machines appending to one append-only log would otherwise conflict on nearly every sync, and hand-resolving such a conflict is exactly how records get silently dropped. Union merge keeps <em>both</em> sides' lines. A record can end up duplicated or out of chronological order as a result — consumers sort on <code>ts</code> and de-duplicate commits on <code>sha</code>, so that costs nothing.</li>
|
|
1466
|
-
<li>The <code>pre-commit</code> hook <strong>reconciles</strong> instead of appending one line: it records every commit reachable from <code>HEAD</code> that the file doesn't already carry, then stages that one file so the records ship inside the commit. Pull the other machine's work, commit here, and its history lands too. <code>git log</code> is itself an append-only log that push/pull already replicates; <code>commits.jsonl</code> is a projection of it.</li>
|
|
1467
|
-
</ul>
|
|
1468
|
-
<p>The one thing that does <em>not</em> travel is the hook: <code>.git/hooks/</code> is not part of the repository, so <strong>every clone needs its own</strong>. Run <code>update-framework.sh <repo></code> once on each machine — <code>tf-metrics.sh --report</code> also warns when the clone you're standing in has no hook. To fill a machine's history immediately rather than waiting for a commit, run <code>.tfcore/telemetry/tf-metrics.sh --backfill-commits .</code> (idempotent — already-recorded shas are skipped).</p>
|
|
1469
|
-
</details>
|
|
1470
|
-
|
|
1471
|
-
<details>
|
|
1472
|
-
<summary>GitHub on Windows says: <em>"This file uses 'LF' line endings, but Git is configured to convert them to 'CRLF' the next time the file is checked out."</em></summary>
|
|
1473
|
-
<p>That is <code>core.autocrlf=true</code> (the Git-for-Windows default) meeting a repo whose <code>.gitattributes</code> says only <code>* text=auto</code>. <code>text=auto</code> normalizes the <em>committed blob</em> to LF but still lets the <em>working tree</em> be smudged to CRLF on checkout — so the file on disk and the file Git will next write disagree, and Git tells you so. It's the same mechanism that CRLF-broke every <code>*.sh</code> in this framework (including the guard hooks) on 2026-07-11.</p>
|
|
1474
|
-
<p>Fixed by pinning the working tree instead of leaving it to per-machine config. The scaffold/update scripts now manage a <code>.gitattributes</code> block in every repo:</p>
|
|
1475
|
-
<pre><code>* text=auto eol=lf
|
|
1476
|
-
*.bat text eol=crlf
|
|
1477
|
-
*.cmd text eol=crlf
|
|
1478
|
-
docs/metrics/*.jsonl text eol=lf merge=union</code></pre>
|
|
1479
|
-
<p><code>eol=lf</code> pins the working tree to LF on macOS, WSL and native Windows alike; <code>*.bat</code>/<code>*.cmd</code> keep CRLF because the Windows command processor requires it. It matters most for <code>docs/metrics/*.jsonl</code>, which is appended to by machine — a log must never acquire mixed line endings.</p>
|
|
1480
|
-
<p>Run <code>update-framework.sh <repo></code> to get the block, then <strong>once per repo, yourself</strong>: <code>git add --renormalize . && git commit -m "Normalize line endings"</code> so the committed blobs match the new rules. The script prints that reminder when it adds the block. (Agents can't run it — git is manual here.)</p>
|
|
1481
|
-
</details>
|
|
1482
|
-
|
|
1483
|
-
<details>
|
|
1484
|
-
<summary>What if the agent ignores the coding standards mid-implementation?</summary>
|
|
1485
|
-
<p>The verifier's standards-compliance grep checks (§10, item 3) catch the most common violations and produce coverage misses. When you see a miss like <code>STANDARDS: underscore-field in src/Foo.cs:42</code> flagged in the checklist's Requirements Status table, tell the implementing agent: <em>"Fix the standards violations flagged in the Requirements Status table of docs/<APP>-Checklist.md per docs/<APP>-Coding-Standards.md."</em> Loop until clean.</p>
|
|
1486
|
-
</details>
|
|
1487
|
-
|
|
1488
|
-
<details>
|
|
1489
|
-
<summary>What if existing brownfield code doesn't use the <code>obj</code> field prefix?</summary>
|
|
1490
|
-
<p>First: the prefix only applies if THIS project chose <code>obj</code> — the field prefix is a per-project day-1 decision recorded in <code>docs/<APP>-Coding-Standards.md</code> (e.g. AstroLyfe uses bare PascalCase, no prefix). If it did, the analyst flags it as standards drift in the day-1 output summary. You then either: (a) let the standards-compliance grep checks in the verify pass catch them and fold the fixes into the regular build loop (the implementing agent renames as it touches the file), or (b) explicitly ask flow-master for a one-shot rename pass: <em>"Rename every non-obj-prefixed instance field in src/ to use the obj prefix per docs/<APP>-Coding-Standards.md, in one commit per file."</em> Option (a) is lower-risk; option (b) is faster if you want a clean baseline.</p>
|
|
1491
|
-
</details>
|
|
1492
|
-
|
|
1493
|
-
<details>
|
|
1494
|
-
<summary>I want to change the coding standards mid-project. Will the agents pick it up?</summary>
|
|
1495
|
-
<p>Yes — they read <code>docs/<APP>-Coding-Standards.md</code> on every invocation. Update the file, then in the next implementation prompt include <em>"NOTE: the coding standards file was updated; conform new code to it and flag any existing non-conforming areas in your output summary."</em></p>
|
|
1496
|
-
</details>
|
|
1497
|
-
|
|
1498
|
-
<details>
|
|
1499
|
-
<summary>Should the architecture document be updated as the code changes?</summary>
|
|
1500
|
-
<p>Yes. For a deliberate change to scope/structure (new module, new flow, stack tweak), run <code>*amend-docs <APP> "<what changed>"</code> (<a href="#evolving-docs">§7.9</a>) — it amends Architecture.md (and the BRD) in place and re-renders. For incidental "as-built" drift discovered during implementation, the implementing agent notes it and <code>/flow-master</code> reconciles at handoff ("update Architecture.md to reflect 'as-built', then regenerate the HTML").</p>
|
|
1501
|
-
</details>
|
|
1502
|
-
|
|
1503
|
-
<details>
|
|
1504
|
-
<summary><code>scaffold-brownfield.sh</code> / <code>scaffold-greenfield.sh</code> re-run wiped my work?</summary>
|
|
1505
|
-
<p>No for your work product — framework files copy with <code>rsync --ignore-existing</code>. EXCEPTION: the harness agent mirror under <code>.claude/commands/TechieFlow/agents/</code> is force-synced from <code>.tfcore/agents/</code> on every run — edit agents only in <code>.tfcore/agents/</code>. (The old <code>.opencode/command/TechieFlow/</code> mirror no longer exists — OpenCode loads agents/tasks from <code>opencode.jsonc</code> <code>{file:./.tfcore/...}</code> references.)</p>
|
|
1506
|
-
</details>
|
|
1507
|
-
|
|
1508
|
-
<details>
|
|
1509
|
-
<summary><code>*yolo</code> doesn't stop Bash prompts.</summary>
|
|
1510
|
-
<p>It does now (2026-08-21, §12a). <code>*yolo</code> writes <code>.tfcore/.session/yolo.json</code>; the PreToolUse hook reads it and stops asking for <code>rm</code>/<code>rmdir</code>/<code>sudo</code> and allows read-only git. Still prompted? (1) The app's <code>.claude/settings.json</code> predates the change and still has <code>Bash(rm *)</code> under <code>ask</code> — run <code>update-framework.sh <app></code>; a settings <code>ask</code> prompts in every mode, even bypass. (2) The agent forgot <code>tf-yolo.sh on</code> — type <code>*yolo</code> again or run it yourself. Git <strong>writes</strong> prompt for nobody — denied outright in every mode.</p>
|
|
1511
|
-
</details>
|
|
1512
|
-
|
|
1513
|
-
<details>
|
|
1514
|
-
<summary>My unattended goal run stopped on "You've hit your limit · resets …".</summary>
|
|
1515
|
-
<p>Use the supervisor, not a bare session: <code>bash .tfcore/utils/tf-goal.sh <app-dir> "<goal>"</code> (§12a). It parses the reset time, sleeps until reset + 15 min, and resumes the same session; <code>--resume <app-dir></code> continues after a reboot. Watch <code>.tfcore/.session/goal.log</code>.</p>
|
|
1516
|
-
</details>
|
|
1517
|
-
|
|
1518
|
-
<details>
|
|
1519
|
-
<summary><code>*build-phase</code> implemented a few REQs and told me to run it again for the rest.</summary>
|
|
1520
|
-
<p>That ending is banned (build-phase §2b). Re-run it — FRESH/FIX detection picks up the open rows — and if it happens again, quote §2b back: a pass is done when every working-list REQ is ≥ <code>Implemented</code>; context pressure means more sub-agent clusters, not a shorter pass.</p>
|
|
1521
|
-
</details>
|
|
1522
|
-
|
|
1523
|
-
<details>
|
|
1524
|
-
<summary>Mermaid not rendering in BRD.html / Architecture.html.</summary>
|
|
1525
|
-
<p>(1) Offline + CDN script blocked — inline mermaid.min.js instead. (2) Missing <code>mermaid.initialize</code> — check end of HTML. (3) Malformed code fence — confirm <code>```mermaid</code> on its own line and valid Mermaid syntax.</p>
|
|
1526
|
-
</details>
|
|
1527
|
-
|
|
1528
|
-
<details>
|
|
1529
|
-
<summary>Verifier says "Playwright not installed".</summary>
|
|
1530
|
-
<p>Vidur self-heals browser binaries. If install fails: did you run §0?</p>
|
|
1531
|
-
</details>
|
|
1532
|
-
|
|
1533
|
-
<details>
|
|
1534
|
-
<summary>Agent implemented things <em>not</em> in the requirements doc.</summary>
|
|
1535
|
-
<p><em>"Revert anything not tied to a REQ-* ID."</em> Add new REQ first if you actually want it.</p>
|
|
1536
|
-
</details>
|
|
1537
|
-
|
|
1538
|
-
<details>
|
|
1539
|
-
<summary>Slash command <code>/trblazeui</code> shows "no skill".</summary>
|
|
1540
|
-
<p>Run <code>dotnet build</code> once to fire the TrBlazeUI NuGet deploy target. If still missing: <code>dotnet build -t:TrBlazeUIRedeployAgentFiles</code>. Restart Claude Code so it rescans skills.</p>
|
|
1541
|
-
</details>
|
|
1542
|
-
|
|
1543
|
-
<details>
|
|
1544
|
-
<summary>Should I commit the HTML files?</summary>
|
|
1545
|
-
<p>Yes for all of <code>PROJECT-STATUS.html</code>, <code><APP>-BRD.html</code>, <code><APP>-Architecture.html</code>, <code><APP>-<Library>-Feedback.md</code>. Browseable on GitHub without cloning, and they're the human-facing artifacts.</p>
|
|
1546
|
-
</details>
|
|
1547
|
-
|
|
1548
|
-
<details>
|
|
1549
|
-
<summary>Standard TechieFlow story-by-story flow — ever?</summary>
|
|
1550
|
-
<p>Only with a second person. For solo + Claude Max, the compressed flow is strictly faster. The stock story-flow agents and tasks no longer ship with this scaffold (trimmed 2026-06-12) — obtain a full story-by-story agent set separately if that day comes.</p>
|
|
1551
|
-
</details>
|
|
1552
|
-
|
|
1553
|
-
<details>
|
|
1554
|
-
<summary>How do I keep token usage down?</summary>
|
|
1555
|
-
<p>Read <code>.tfcore/TOKEN-GUIDE.md</code> (ships with every project). Key levers: don't load whole docs or repo trees into context; checklists stay markdown-only (never rendered to HTML — HTML adds weight with no AI benefit); fan work out to subagents instead of loading everything in one session; use <code>*amend-docs</code> and <code>*devguide --update</code> for incremental refreshes instead of re-running phases from scratch; use <code>*refresh-status</code> to recover a broken session instead of re-running the whole phase.</p>
|
|
1556
|
-
</details>
|
|
1557
|
-
|
|
1558
|
-
<details>
|
|
1559
|
-
<summary>A screen passed verification but was rendering blank OR was visually broken — how is it prevented now?</summary>
|
|
1560
|
-
<p>Before the gates, verification only checked acceptance-test pass/fail (HTTP 200, no exception, element present). A screen could pass while its data table showed zero rows, or while every control rendered its data but the controls <strong>overlapped / sat off-screen / were clipped</strong> so the running app was unusable. Two gates close both holes:</p>
|
|
1561
|
-
<ul class="tight">
|
|
1562
|
-
<li><strong>Render gate (verify-phase §4a):</strong> the verifier asserts every control listed in the DevGuide actually renders its data — no blank table, no count-over-zero-rows, no empty chart.</li>
|
|
1563
|
-
<li><strong>Visual-truth gate (§4b):</strong> it then asserts the screen LOOKS right — no control overlap, every control in-viewport and non-zero-size, checked at desktop + mobile widths, the screenshot inspected, and diffed against the mockup when one exists.</li>
|
|
1564
|
-
</ul>
|
|
1565
|
-
<p>A REQ is <code>Verified</code> only if acceptance passes AND data renders AND the screen looks right; otherwise it drops to <code>Needs re-verify</code> / <code>FAIL</code>. <code>Done (pre-existing)</code> is treated as an unverified migrated claim and gets the same sweep. The DevGuide's observed render/visual tags are refreshed each run, keeping DevGuide ⇄ Checklist ⇄ Verifier runtime-true.</p>
|
|
1566
|
-
</details>
|
|
1567
|
-
|
|
1568
|
-
<details>
|
|
1569
|
-
<summary>The verifier passed but the running UI is broken — who do I call?</summary>
|
|
1570
|
-
<p><code>/TechieFlow:agents:flow-master *fix-issues {AppName} {folder}</code> (§7.11). Drop a folder of screenshots of the broken screens (optionally a <code>bugs.md</code> naming what's wrong on each). Flow-master reads them (vision), reproduces each issue live with Playwright, triages it (layout / data / logic / RAG), and <strong>fans the fix out to the right builder</strong> — <code>/trblazeui</code> for layout, its own subagents for data/logic, <code>/techierag</code> for RAG. You never invoke a builder agent yourself. It then re-smokes (data + visual), re-verifies the affected REQs, and updates the DevGuide + checklist + PROJECT-STATUS.</p>
|
|
1571
|
-
</details>
|
|
1572
|
-
|
|
1573
|
-
<details>
|
|
1574
|
-
<summary>I found bugs at UAT / in production — I want them analyzed and logged, but NOT fixed yet</summary>
|
|
1575
|
-
<p><code>/TechieFlow:agents:flow-master *triage-issues {AppName} {evidence}</code> (§7.12). Same evidence channel as <code>*fix-issues</code> (a screenshots folder), plus it accepts a written bug list. Flow-master reproduces each issue live and delivers <strong>docs only</strong>: regressed REQs demoted to <code>Needs re-verify</code> with dated <code>⚠ UAT bug</code> remarks, new <code>Planned</code> REQ rows for unspecified defects, refreshed DevGuide known-issues, and a PROJECT-STATUS whose next command is the <code>*fix-issues</code> pointer naming the REQ IDs. Add <code>verify</code> to also regression-re-verify the affected screens' sibling REQs. It never edits <code>src/</code>/<code>tests/</code> and never spawns a builder — you decide when the fixing starts.</p>
|
|
1576
|
-
</details>
|
|
1577
|
-
|
|
1578
|
-
<details>
|
|
1579
|
-
<summary>How does a developer understand or verify the AI-generated code?</summary>
|
|
1580
|
-
<p>Run <code>/TechieFlow:agents:flow-master *devguide {AppName}</code> (also auto-run at handoff). It produces <code>docs/{AppName}-DevGuide.md</code> + a styled <code>.html</code>: every screen grouped by user role, each with a flowchart tracing the full stack (Razor page → service → data-access → stored procedure/query), a Controls table (with observed render-status from the OBSERVE pass), and a Data-lineage table. Use it to find the right service method for a bug, confirm the correct stored procedure is called, or check that a control is bound to the right DTO property. Re-run with <code>--update</code> after implementing changes to refresh only the affected screens. See <a href="#docs">§6</a> for the full schema and the 3-pass generation model.</p>
|
|
1581
|
-
</details>
|
|
1582
|
-
|
|
1583
|
-
<h2 id="platforms">16. Running on macOS / native Windows / Linux<span class="anchor-link"><a href="#platforms">#</a></span></h2>
|
|
1584
|
-
|
|
1585
|
-
<p>This framework was built on the owner's <strong>WSL-on-Windows</strong> machine, so §0/§11 and the build-invocation ladder describe that setup. But the framework itself is <strong>portable</strong> — the agents, tasks, templates, and slash-commands are plain Markdown and run identically under Claude Code or OpenCode on <strong>macOS, native Windows, or native Linux</strong>. Only two things are environment-specific: how <code>dotnet</code> is invoked, and the runtime-verification bridges (headless Playwright for Blazor; the §0b Appium endpoints for MAUI Android/iOS/Mac-Catalyst; FlaUI/Appium-Windows for the MAUI Windows head). Here is what changes per platform.</p>
|
|
1586
|
-
|
|
1587
|
-
<div class="panel">
|
|
1588
|
-
<strong>What is the SAME everywhere:</strong> the <code>scaffold-*.sh</code> / <code>update-framework.sh</code> scripts (bash), all <code>/TechieFlow:*</code> slash commands, the day-1 → split → build → verify → handoff flow, every doc template, and the <code>.claude/settings.json</code> permission model. The scaffold scripts need <code>bash</code> + <code>rsync</code> + <code>realpath</code> (preinstalled on macOS 12.3+ and Linux; on native Windows run them from <strong>WSL or Git Bash</strong>).
|
|
1589
|
-
</div>
|
|
1590
|
-
|
|
1591
|
-
<table>
|
|
1592
|
-
<tr><th>Concern</th><th>WSL-on-Windows (reference)</th><th>macOS</th><th>native Windows</th><th>native Linux</th></tr>
|
|
1593
|
-
<tr><td><code>dotnet</code> invocation</td><td>ladder §B: <code>~/.dotnet/dotnet</code>, <code>cmd.exe /c</code>, <code>winrun</code></td><td><strong>ladder §A: <code>dotnet build</code></strong> (in PATH)</td><td><strong>ladder §C: <code>dotnet build</code></strong> (in PATH)</td><td><strong>ladder §A: <code>dotnet build</code></strong> (in PATH)</td></tr>
|
|
1594
|
-
<tr><td>MAUI iOS / Mac Catalyst</td><td>Windows side via <code>cmd.exe</code> (needs paired Mac for iOS)</td><td><strong>native</strong> — needs Xcode + <code>sudo dotnet workload install maui</code></td><td>needs a paired Mac build host</td><td>not supported (no Apple toolchain)</td></tr>
|
|
1595
|
-
<tr><td>MAUI Android</td><td>Windows side via <code>cmd.exe</code></td><td>native — Android SDK + JDK</td><td>native — Android SDK + JDK</td><td>native — Android SDK + JDK</td></tr>
|
|
1596
|
-
<tr><td>MAUI Windows head</td><td>Windows side via <code>cmd.exe</code></td><td>not supported</td><td>native</td><td>not supported</td></tr>
|
|
1597
|
-
<tr><td>Browser verification (verifier)</td><td>headless Playwright CLI (§0 bootstrap)</td><td>Playwright with system Chromium</td><td>Playwright with system browser</td><td>headless Playwright CLI</td></tr>
|
|
1598
|
-
<tr><td>Native UI verification (Android/iOS/Catalyst)</td><td><strong>Appium endpoints (§0b)</strong>: Android on Windows host, iOS/Catalyst on a LAN Mac</td><td>local Appium (Android emulator + iOS Sim + Catalyst, all native)</td><td>local Appium (Android emulator + Catalyst); iOS via the paired Mac's Appium</td><td>local Appium (Android only)</td></tr>
|
|
1599
|
-
<tr><td>Scaffold scripts</td><td>run in WSL</td><td>run in Terminal (zsh/bash)</td><td>run in WSL or Git Bash</td><td>run in shell</td></tr>
|
|
1600
|
-
</table>
|
|
1601
|
-
|
|
1602
|
-
<p>The agents resolve this automatically: the build-invocation ladder (<code>.tfcore/templates/v4custom/build-invocation-ladder.md</code>) now starts with a <strong>platform-detection probe</strong> (<code>uname -a</code> → <code>Darwin</code> = macOS, <code>…microsoft…</code> = WSL, plain <code>Linux</code> = native Linux, absent = native Windows) and picks ladder §A / §B / §C accordingly. On macOS/Windows/Linux there is a single rung — <code>dotnet build</code> — and a missing MAUI workload is fixed once with <code>dotnet workload install maui</code> (on macOS with <code>sudo</code>: the SDK dir <code>/usr/local/share/dotnet</code> is root-owned, and without it workload/SDK updates fail with <em>"Inadequate permissions. Run the command with elevated privileges."</em>), never logged as a project blocker.</p>
|
|
1603
|
-
|
|
1604
|
-
<div class="panel ok"><strong>macOS quick start (Claude Code on Mac):</strong>
|
|
1605
|
-
<ol>
|
|
1606
|
-
<li>Run the one-time <a href="#mac-bootstrap">§0a macOS bootstrap</a> — Xcode CLT/license, Homebrew, .NET SDK + Node, Playwright per project; <code>sudo dotnet workload install maui</code> (sudo required on macOS) + Xcode / Android SDK only for MAUI apps.</li>
|
|
1607
|
-
<li>Scaffold as usual: <code>/path/to/TechieFlow/scaffold-brownfield.sh /path/to/your-app</code> (or <code>scaffold-greenfield.sh</code>).</li>
|
|
1608
|
-
<li>Start Claude Code in the app folder and run <code>/TechieFlow:agents:analyst *day1-brownfield <AppName></code> — identical to WSL.</li>
|
|
1609
|
-
</ol>
|
|
1610
|
-
The <code>winrun</code> bridge and <code>cmd.exe</code> rungs simply don't apply on Mac; the agents won't reach for them once <code>uname</code> reports <code>Darwin</code>.</div>
|
|
1611
|
-
|
|
1612
|
-
<div class="panel ok"><strong>NuGet credentials for macOS:</strong> store the private GitHub Packages source in <code>$HOME/.nuget/NuGet/NuGet.Config</code> (for example <code>/Users/srkra/.nuget/NuGet/NuGet.Config</code>), not in the project. NuGet, Claude Code, and native OpenCode discover it automatically. Windows uses <code>%AppData%\NuGet\NuGet.Config</code>. OpenCode Docker mounts the Windows directory read-only at <code>/root/.nuget/NuGet</code>. A repository <code>nuget.config</code>, if needed for source mapping, must contain no PAT.</div>
|
|
1613
|
-
|
|
1614
|
-
<div class="panel warn"><strong>Moving an existing project (or this framework repo) from Windows/WSL to a Mac:</strong>
|
|
1615
|
-
<ol>
|
|
1616
|
-
<li><strong>Can't see <code>.tfcore/</code>, <code>.claude/</code>, <code>.opencode/</code> in Finder?</strong> Finder hides dot-files by default. Press <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>.</kbd> in any Finder window to toggle them on (the setting sticks), or run <code>defaults write com.apple.finder AppleShowAllFiles -bool true && killall Finder</code>. The Terminal always sees them: <code>ls -la</code>. Nothing is missing just because Finder doesn't show it — check with <code>ls -la</code> first.</li>
|
|
1617
|
-
<li><strong>Moved an APP repo via git (clone/pull)?</strong> Then the framework folders genuinely AREN'T there — every deployed framework copy (<code>.tfcore/</code>, <code>.claude/</code>, <code>.opencode/</code>, <code>/CLAUDE.md</code>, <code>/WORKFLOW.html</code>, <code>/opencode.jsonc</code>) is <em>gitignored by design</em> (they're copies; this repo is the source of truth). Re-deploy them: <code>ls -la</code> the app — if <code>.tfcore/</code> exists, run <code>/path/to/TechieFlow/update-framework.sh /path/to/app</code>; if it's absent, run <code>/path/to/TechieFlow/scaffold-brownfield.sh /path/to/app</code> (safe on an app with existing docs/code — it uses <code>--ignore-existing</code> and never touches <code>src/</code>, <code>docs/</code>, or tests). Add <code>--dry-run</code> to <code>update-framework.sh</code> to preview.</li>
|
|
1618
|
-
<li><strong>Per-project gitignored files don't come back from a scaffold.</strong> <code>CLAUDE.md</code>, <code>.tfcore/core-config.yaml</code> customizations, and <code>.claude/settings.local.json</code> are per-project work product that git never carried. A plain <em>folder copy</em> from the old machine keeps them; a git clone loses them — copy them over from the Windows machine, or regenerate (<code>CLAUDE.md</code> comes back via day-1 / <code>*refresh-status</code>).</li>
|
|
1619
|
-
<li><strong>Scripts won't execute (<code>permission denied</code>)?</strong> A copy through a Windows filesystem drops the executable bit. Fix once: <code>chmod +x /path/to/TechieFlow/*.sh /path/to/TechieFlow/.tfcore/hooks/*.sh</code> (or run them as <code>bash script.sh</code>). Hooks inside apps are invoked via <code>bash</code> so they don't need it, but the same <code>chmod</code> doesn't hurt.</li>
|
|
1620
|
-
<li><strong>No path edits needed:</strong> since 2026-07-11 the three scripts locate the framework from their own directory (no hardcoded <code>/mnt/c/…</code>), and they run fine on macOS's stock <code>bash</code>/<code>rsync</code>.</li>
|
|
1621
|
-
<li><strong>Afterwards, restart Claude Code</strong> in the app folder so the freshly deployed agent/task definitions and <code>settings.json</code> load.</li>
|
|
1622
|
-
</ol></div>
|
|
1623
|
-
|
|
1624
|
-
<div class="panel"><strong>native Windows quick start (Claude Code / OpenCode on Windows, not WSL):</strong>
|
|
1625
|
-
<ol>
|
|
1626
|
-
<li>Install the .NET SDK (winget / official installer); confirm <code>dotnet --info</code>.</li>
|
|
1627
|
-
<li>For MAUI: <code>dotnet workload install maui</code>. Windows + Android heads build natively; <strong>iOS / Mac Catalyst need a paired Mac build host</strong>.</li>
|
|
1628
|
-
<li>Run the scaffold scripts from <strong>WSL or Git Bash</strong> (they're bash). Then drive the framework from Claude Code on Windows normally — the ladder uses §C (<code>dotnet build</code>).</li>
|
|
1629
|
-
</ol></div>
|
|
1630
|
-
|
|
1631
|
-
<div class="panel ok"><strong>OpenCode in a Windows Docker container:</strong> use the dedicated <a href="#opencode-docker">Containerized OpenCode host bridge</a> under §0. The container is Linux, so it uses the SSH-backed <code>winrun</code> wrapper rather than direct <code>cmd.exe</code> interop.</div>
|
|
1632
|
-
|
|
1633
|
-
<div class="panel"><strong>native Linux quick start:</strong>
|
|
1634
|
-
<ol>
|
|
1635
|
-
<li>Install the .NET SDK via your distro or the official script; confirm <code>dotnet --info</code>.</li>
|
|
1636
|
-
<li>MAUI on Linux supports the <strong>Android</strong> head only (<code>net9.0-android</code>) — iOS / Mac Catalyst / Windows heads can't build without their toolchains (a genuine platform limit, not a wrong-rung error).</li>
|
|
1637
|
-
<li>Scaffold and run exactly as on macOS (ladder §A).</li>
|
|
1638
|
-
</ol></div>
|
|
1639
|
-
|
|
1640
|
-
<p><strong>Notes.</strong> The framework never <em>requires</em> MAUI — many apps are Blazor-only and build with plain <code>dotnet build</code> everywhere. The full per-platform <code>dotnet</code> invocation detail lives in <code>.tfcore/templates/v4custom/build-invocation-ladder.md</code> (what the agents read); this section is the human-facing summary.</p>
|
|
1641
|
-
|
|
1642
|
-
<h2 id="telemetry">17. Development telemetry — what the framework measures about itself<span class="anchor-link"><a href="#telemetry">#</a></span></h2>
|
|
1643
|
-
|
|
1644
|
-
<div class="panel ok"><strong>Full guide</strong> — annotated example records for every stream, the report walkthrough, how model/tokens/cost land on run records, and the FAQ: <code>docs/TechieFlow-Telemetry-Guide.md</code> (+ rendered <code>.html</code>) <em>in the TechieFlow framework repo</em>. Field-by-field contract: <code>.tfcore/telemetry/SCHEMA.md</code> (deployed in this app).</div>
|
|
1645
|
-
|
|
1646
|
-
<p>TechieFlow already produced this evidence and used to throw it away. Every <code>*verify</code> run applies four separately-named gates to individually-identified requirements and writes verdicts into the Requirements Status table; <code>docs/.last-verify.json</code> recorded the run. Then the next run overwrote it, the table was mutated in place, and the history was gone. Telemetry keeps it.</p>
|
|
1647
|
-
|
|
1648
|
-
<p><strong>Four questions, and nothing else:</strong></p>
|
|
1649
|
-
<ol>
|
|
1650
|
-
<li><strong>First-pass rate</strong> — what fraction of REQs reach <code>Verified</code> on attempt 1?</li>
|
|
1651
|
-
<li><strong>Gate catch distribution</strong> — of all failures, which gate caught them?</li>
|
|
1652
|
-
<li><strong>Escape rate</strong> — what fraction of defects reached UAT/production (logged by <code>*triage-issues</code>) instead of being caught by a gate?</li>
|
|
1653
|
-
<li><strong>Miss attribution and rework cost</strong> (added 2026-08-28) — <em>what</em> was missed, <em>which phase / agent / model</em> let it through, and <em>what did fixing it cost</em>?</li>
|
|
1654
|
-
</ol>
|
|
1655
|
-
|
|
1656
|
-
<p>There is deliberately <strong>no cycle-time-per-feature</strong>. The unit of work here is <em>the run</em>, not the ticket.</p>
|
|
1657
|
-
|
|
1658
|
-
<h3>Where it lands</h3>
|
|
1659
|
-
|
|
1660
|
-
<p>Five append-only JSONL streams in <code>docs/metrics/</code>, <strong>tracked by version control on purpose</strong> — this is the project's own development history, and the one thing the framework cannot reconstruct afterwards.</p>
|
|
1661
|
-
|
|
1662
|
-
<table>
|
|
1663
|
-
<thead><tr><th>File</th><th>One record per</th><th>Written by</th></tr></thead>
|
|
1664
|
-
<tbody>
|
|
1665
|
-
<tr><td><code>runs.jsonl</code></td><td>framework command run</td><td>each phase task, at completion (the status gate is the trigger)</td></tr>
|
|
1666
|
-
<tr><td><code>gates.jsonl</code></td><td>REQ verdict per verify run — <strong>the primary stream</strong></td><td><code>verify-phase</code> §6a, and <code>triage-issues</code> for escapes</td></tr>
|
|
1667
|
-
<tr><td><code>sessions.jsonl</code></td><td>agent session</td><td>the <code>SessionEnd</code> hook (<code>.tfcore/hooks/metrics-session.sh</code>)</td></tr>
|
|
1668
|
-
<tr><td><code>commits.jsonl</code></td><td>commit</td><td>your own <code>pre-commit</code> hook — never an agent</td></tr>
|
|
1669
|
-
<tr><td><code>misses.jsonl</code></td><td>a requirement or behaviour an agent <strong>missed</strong> (<code>miss</code>), what repairing it cost (<code>miss-fix</code>), and a field completed later (<code>miss-amend</code>)</td><td><code>verify-phase</code>, <code>build-phase</code>, <code>triage-issues</code>, <code>fix-issues</code>, <code>amend-docs</code>, <code>*log-miss</code></td></tr>
|
|
1670
|
-
</tbody>
|
|
1671
|
-
</table>
|
|
1672
|
-
|
|
1673
|
-
<p>Schema, enums and every known limitation: <code>.tfcore/telemetry/SCHEMA.md</code>. Doctrine for agents: <code>.tfcore/tasks/_metrics-emit-gate.md</code>.</p>
|
|
1674
|
-
|
|
1675
|
-
<h3>Setup — there isn't one</h3>
|
|
1676
|
-
|
|
1677
|
-
<p>Telemetry rides the normal framework refresh. There is <strong>no separate install command</strong>:</p>
|
|
1678
|
-
|
|
1679
|
-
<p><strong>on WSL/Linux:</strong></p>
|
|
1680
|
-
<pre><code>/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/YourApp
|
|
1681
|
-
</code></pre>
|
|
1682
|
-
|
|
1683
|
-
<p><strong>on macOS:</strong></p>
|
|
1684
|
-
<pre><code>/Volumes/MacD/MyCode/TechieFlow/update-framework.sh /path/to/YourApp
|
|
1685
|
-
</code></pre>
|
|
1686
|
-
|
|
1687
|
-
<p>That one command creates <code>docs/metrics/</code>, seeds the five streams, installs the <code>pre-commit</code> hook, and warns if an ignore rule would swallow the data. The scaffolds do the same on a fresh project. It is idempotent, so every later refresh keeps it current.</p>
|
|
1688
|
-
|
|
1689
|
-
<p><strong>project_type is auto-detected once</strong> (a packable <code>.csproj</code> → <code>library</code>; <code>.razor</code>/<code>.xaml</code> present → <code>app</code>; no source → <code>docs</code>; this repo → <code>framework</code>), printed loudly, written to <code>core-config.yaml</code>, and then never guessed again — <code>core-config.yaml</code> is a preserved file, so your classification survives every refresh. Correct a wrong guess with:</p>
|
|
1690
|
-
|
|
1691
|
-
<pre><code>.tfcore/telemetry/install-metrics.sh . --type app|library|docs|framework
|
|
1692
|
-
</code></pre>
|
|
1693
|
-
|
|
1694
|
-
<p><strong>Nothing here invokes git.</strong> The hooks directory is found by reading the filesystem — installing a hook is a file copy, not a git operation — so <code>block-git.sh</code> is untouched and no permission prompt appears, whoever runs the refresh.</p>
|
|
1695
|
-
|
|
1696
|
-
<h3>Updating the metrics — you don't</h3>
|
|
1697
|
-
|
|
1698
|
-
<p>There is no "update metrics" step. The streams fill themselves as you work: every <code>*build-phase</code>, <code>*verify all</code>, <code>*fix-issues</code>, <code>*triage-issues</code>, <code>*handoff-phase</code> and day-1 run appends its own record as its last action, the <code>SessionEnd</code> hook adds a session, and your own commits add themselves. If you never think about telemetry again, it still accumulates.</p>
|
|
1699
|
-
|
|
1700
|
-
<p>The only thing that needs doing per repo is the framework refresh you already run:</p>
|
|
1701
|
-
|
|
1702
|
-
<pre><code>/mnt/c/3AIGenCode/TechieFlow/update-framework.sh /path/to/YourApp
|
|
1703
|
-
</code></pre>
|
|
1704
|
-
|
|
1705
|
-
<h3>Viewing the metrics — two ways</h3>
|
|
1706
|
-
|
|
1707
|
-
<p><strong>1. Quick look, in the terminal.</strong> No agent, no tokens, read-only — run it from inside the app repo:</p>
|
|
1708
|
-
|
|
1709
|
-
<pre><code>cd /path/to/YourApp
|
|
1710
|
-
.tfcore/telemetry/tf-metrics.sh --report .
|
|
1711
|
-
</code></pre>
|
|
1712
|
-
|
|
1713
|
-
<p>Prints first-pass rate, gate catch distribution, escape rate, rework ratio, batch size, throughput, commit cadence and the miss report — already segmented, with <code>insufficient data</code> wherever there are fewer than three supporting records.</p>
|
|
1714
|
-
|
|
1715
|
-
<p><strong>2. The full report, as a document.</strong> Ask flow-master; it writes <code>docs/metrics/METRICS.md</code> and renders <code>docs/metrics/METRICS.html</code> (open that in a browser — it uses the same themed shell as your other docs):</p>
|
|
1716
|
-
|
|
1717
|
-
<p><strong>Claude Code:</strong></p>
|
|
1718
|
-
<pre><code>/TechieFlow:agents:flow-master *metrics YourApp
|
|
1719
|
-
</code></pre>
|
|
1720
|
-
|
|
1721
|
-
<p><strong>OpenCode:</strong></p>
|
|
1722
|
-
<pre><code>/flow-master *metrics YourApp
|
|
1723
|
-
</code></pre>
|
|
1724
|
-
|
|
1725
|
-
<h3>Across several projects at once</h3>
|
|
1726
|
-
|
|
1727
|
-
<pre><code>.tfcore/telemetry/tf-metrics.sh --rollup . /path/to/OtherApp /path/to/Third
|
|
1728
|
-
</code></pre>
|
|
1729
|
-
|
|
1730
|
-
<p>Still segmented — <code>app</code> and <code>library</code> repos are reported side by side, never averaged together. Or hand the same paths to the command: <code>*metrics YourApp /path/to/OtherApp</code>.</p>
|
|
1731
|
-
|
|
1732
|
-
<h3>Seeding history from what you already have (optional, once per repo)</h3>
|
|
1733
|
-
|
|
1734
|
-
<p>Your repos have years of history the streams know nothing about. Two backfills can import some of it. <strong>Both are yours to run, never an agent's</strong> — and always preview with <code>--dry-run</code> first:</p>
|
|
1735
|
-
|
|
1736
|
-
<pre><code>cd /path/to/YourApp
|
|
1737
|
-
.tfcore/telemetry/tf-metrics.sh --backfill-commits . --dry-run
|
|
1738
|
-
.tfcore/telemetry/tf-metrics.sh --backfill-commits .
|
|
1739
|
-
</code></pre>
|
|
1740
|
-
|
|
1741
|
-
<p><strong>Commit backfill is trustworthy.</strong> It walks the commit log, which is itself an append-only log, so reconstructed commits are exactly as good as live ones and are reported together with them. This is also the reason the <code>pre-commit</code> hook is optional.</p>
|
|
1742
|
-
|
|
1743
|
-
<pre><code>.tfcore/telemetry/tf-metrics.sh --backfill-gates . --dry-run
|
|
1744
|
-
</code></pre>
|
|
1745
|
-
|
|
1746
|
-
<p><strong>Gate backfill is context, not evidence.</strong> It reads each REQ's current row in <code><APP>-Checklist.md</code> plus any dated remarks. But that table is a snapshot that gets overwritten in place, not a log — a REQ that failed three times and then passed looks identical to one that passed first try. Every record it writes is stamped <code>backfilled: true</code> with an <code>inferred</code> list, is reported in its own separate column, and <strong>can never support a published first-pass rate</strong>. Useful for volume and shape; not for a number you would defend.</p>
|
|
1747
|
-
|
|
1748
|
-
<h3>If a project is classified wrong</h3>
|
|
1749
|
-
|
|
1750
|
-
<p>The refresh auto-detects <code>project_type</code> once and prints what it chose. If it guessed wrong — the giveaway is a library reported as though the visual gate could fire on it — correct it and it stays corrected:</p>
|
|
1751
|
-
|
|
1752
|
-
<pre><code>.tfcore/telemetry/install-metrics.sh . --type app|library|docs|framework
|
|
1753
|
-
</code></pre>
|
|
1754
|
-
|
|
1755
|
-
<h3>What to expect early on</h3>
|
|
1756
|
-
|
|
1757
|
-
<p>The streams start empty, and the report refuses to invent numbers from thin data — you will see <code>insufficient data (n=…)</code> on most rows until roughly three verify runs have happened. That is the report working, not a fault. The first genuinely interesting reading usually comes after a build → verify → fix cycle or two.</p>
|
|
1758
|
-
|
|
1759
|
-
<table>
|
|
1760
|
-
<thead><tr><th>You want to…</th><th>Run</th></tr></thead>
|
|
1761
|
-
<tbody>
|
|
1762
|
-
<tr><td>Turn telemetry on for a repo</td><td><code>update-framework.sh /path/to/YourApp</code> (nothing else)</td></tr>
|
|
1763
|
-
<tr><td>Glance at the numbers now</td><td><code>.tfcore/telemetry/tf-metrics.sh --report .</code></td></tr>
|
|
1764
|
-
<tr><td>Produce the readable report</td><td><code>*metrics YourApp</code> → <code>docs/metrics/METRICS.html</code></td></tr>
|
|
1765
|
-
<tr><td>Compare several projects</td><td><code>tf-metrics.sh --rollup . /path/to/OtherApp</code></td></tr>
|
|
1766
|
-
<tr><td>Import commit history</td><td><code>tf-metrics.sh --backfill-commits .</code></td></tr>
|
|
1767
|
-
<tr><td>Import checklist history</td><td><code>tf-metrics.sh --backfill-gates .</code> (context only)</td></tr>
|
|
1768
|
-
<tr><td>Fix a wrong classification</td><td><code>install-metrics.sh . --type library</code></td></tr>
|
|
1769
|
-
</tbody>
|
|
1770
|
-
</table>
|
|
1771
|
-
|
|
1772
|
-
<h3 id="misses">Misses — the fourth question</h3>
|
|
1773
|
-
|
|
1774
|
-
<p>A <code>gates.jsonl</code> record says a REQ <em>failed</em>. A <strong>miss</strong> record says <em>what was missed</em>, <em>which phase let it through</em>, and — through its <code>miss-fix</code> sibling — <em>what the repair cost</em>. It is the only stream that can hold a <strong>design-phase miss</strong> (“the BRD never specified the export screen”), because it is the only one not written by the verifier: by the time verification runs, a specification gap has either been papered over or built wrongly.</p>
|
|
1775
|
-
|
|
1776
|
-
<div class="panel ok"><strong>The 20-second front door.</strong><br>
|
|
1777
|
-
<pre><code>/TechieFlow:agents:flow-master *log-miss {AppName} "the export button ignores the active date filter"
|
|
1778
|
-
/flow-master *log-miss {AppName} "..." (OpenCode) # add --fixed if it is already repaired</code></pre>
|
|
1779
|
-
It classifies what you said, attributes it, writes the <code>misses.jsonl</code> record <em>and</em> the checklist line (a demotion with a dated <code>⚠ miss</code> remark, or a new <code>Planned</code> row with acceptance when nothing owns it). <strong>It never boots the app, never reproduces, never edits code</strong> — <code>*triage-issues</code> does all three, which is right for UAT triage and far too heavy for one sentence. That friction is exactly why these misses used to be recorded nowhere at all.</div>
|
|
1780
|
-
|
|
1781
|
-
<p>Everything else emits automatically: <code>verify-phase</code> on every failing gate, <code>build-phase</code> when a REQ turns out to be unbuildable as written, <code>triage-issues</code> on a UAT or production bug, <code>fix-issues</code> when it closes one.</p>
|
|
1782
|
-
|
|
1783
|
-
<p><strong>One defect is one miss.</strong> A REQ that fails three verify passes collapses onto the record already open for it, so the miss count measures quality rather than retry patience. A new record is written only when the <em>kind</em> of failure changes — which is genuinely new information.</p>
|
|
1784
|
-
|
|
1785
|
-
<p><strong>“Open” and “live” are deliberately different.</strong> A miss closed as <code>wont-fix</code> is a <em>decision</em>, not a backlog item, so the report does not count it as open — but the collapse check still treats it as a live defect, so a repeat failure on that REQ will not open a duplicate. Two questions, two predicates; making them agree would break one of them. <code>deferred</code> stays open, because postponed work is still work.</p>
|
|
1786
|
-
|
|
1787
|
-
<h3>Which <em>practice</em> failed — <code>why_missed</code></h3>
|
|
1788
|
-
|
|
1789
|
-
<p><code>miss_class</code> names the defect. <strong><code>why_missed</code> names the practice that let it through</strong>, and it is the more decision-changing of the two: it says whether your <em>specification</em> or your <em>verification</em> is the weak one. Ported from the AI-First-Playbook on 2026-08-28, whose <code>/analyze-fix</code> phase has always produced exactly this judgement in prose and then thrown it away.</p>
|
|
1790
|
-
|
|
1791
|
-
<table>
|
|
1792
|
-
<thead><tr><th>Value</th><th>The practice that failed</th></tr></thead>
|
|
1793
|
-
<tbody>
|
|
1794
|
-
<tr><td><code>missing-checklist-item</code></td><td>No REQ or acceptance bullet covered the behaviour. The spec had a hole.</td></tr>
|
|
1795
|
-
<tr><td><code>insufficient-verify-method</code></td><td>Acceptance existed; the gate that ran could not catch this class of defect. The spec was fine, the test was too weak.</td></tr>
|
|
1796
|
-
<tr><td><code>code-audit-limitation</code></td><td><code>⚠ STATIC-ONLY</code> — no runtime bridge, so it was never observable.</td></tr>
|
|
1797
|
-
<tr><td><code>ambiguous-acceptance</code></td><td>Two honest readings; build and verifier took different ones.</td></tr>
|
|
1798
|
-
<tr><td><code>dependency-not-declared</code></td><td>The REQ depended on something no document stated.</td></tr>
|
|
1799
|
-
<tr><td><code>instruction-ignored</code></td><td><strong>A written framework rule existed and was not followed.</strong> TechieFlow's own addition — not a spec gap, not a weak gate, and no gate change fixes it.</td></tr>
|
|
1800
|
-
<tr><td><code>other</code></td><td>Nothing above fits. Do not stretch a label to avoid this.</td></tr>
|
|
1801
|
-
</tbody>
|
|
1802
|
-
</table>
|
|
1803
|
-
|
|
1804
|
-
<div class="panel"><strong>Optional, and <code>null</code> is honest</strong> — many misses have no clear answer and a forced one is noise. <strong>But an escape without one wastes the most valuable record in the stream:</strong> something got past every gate, and <em>why nothing caught it</em> is the entire question. <code>--report</code> warns when an <code>owner</code> or <code>production</code> miss arrives with the field empty, and reports the distribution against <em>records that carry it</em>, never against all misses.</div>
|
|
1805
|
-
|
|
1806
|
-
<h3>Completing a record without editing it — <code>miss-amend</code></h3>
|
|
1807
|
-
|
|
1808
|
-
<p>A stream is append-only, so “the correction is a new record, never an edit” is the rule. That rule needs a record kind to name, and until 2026-08-28 this stream had none: a field left empty — most sharply a <code>why_missed</code> on a record written before the field existed — was unreachable. <strong>Reported by the TfLens team as TF-005</strong>, and fixed with a third kind rather than a licence to edit.</p>
|
|
1809
|
-
|
|
1810
|
-
<pre><code>bash .tfcore/utils/tf-emit.sh --amend MISS-App-20260828-01 why_missed missing-checklist-item</code></pre>
|
|
1811
|
-
|
|
1812
|
-
<ul>
|
|
1813
|
-
<li>It may fill a field that is <code>null</code>. It may <strong>never</strong> overwrite one that is not — including a value set by an earlier amend. So it <em>completes</em> a record rather than altering a fact, and a reader that ignores amendments entirely still sees nothing false, only less.</li>
|
|
1814
|
-
<li>Only closed-vocabulary <strong>judgements</strong> are amendable (<code>why_missed</code> today). Nothing the emitter derives — <code>origin_model</code>, <code>origin_confidence</code>, <code>cost_attribution</code>, tokens, dollars — ever is, and an <em>observation</em> about a finished run is never backfilled.</li>
|
|
1815
|
-
<li>It prints its refusal rather than failing quietly, and still exits 0: telemetry has no veto, and neither does a refused amend. A hand-written amend piped onto the stream faces the identical checks.</li>
|
|
1816
|
-
<li><strong>Never hand-edit a <code>.jsonl</code> stream.</strong> If no record kind can carry the correction you need, report it as a framework defect — which is exactly how this one arrived.</li>
|
|
1817
|
-
</ul>
|
|
1818
|
-
|
|
1819
|
-
<div class="panel"><strong>A record written before a field existed is not “unassessed”.</strong> <code>why_missed</code> arrived on 2026-08-28; misses older than that had no field to fill, so they leave that field’s denominator and <code>--report</code> states how many did. Same rule as a gate added mid-stream (§3.5 of the schema): never backfill a record with a verdict nobody made at the time.</div>
|
|
1820
|
-
|
|
1821
|
-
<h3>What a miss costs — the honest version</h3>
|
|
1822
|
-
|
|
1823
|
-
<table>
|
|
1824
|
-
<thead><tr><th>Harness</th><th>Tokens</th><th>Dollars</th></tr></thead>
|
|
1825
|
-
<tbody>
|
|
1826
|
-
<tr><td>OpenCode</td><td>yes</td><td><strong>real, measured</strong> — the provider's own per-message cost</td></tr>
|
|
1827
|
-
<tr><td>Claude Code</td><td>yes</td><td><strong>none — <code>cost_usd</code> is <code>null</code>, permanently</strong>: transcripts carry no cost</td></tr>
|
|
1828
|
-
<tr><td>Codex</td><td>yes</td><td>none — ChatGPT credits are never fabricated as <code>cost_usd</code></td></tr>
|
|
1829
|
-
</tbody>
|
|
1830
|
-
</table>
|
|
1831
|
-
|
|
1832
|
-
<p>So “how much money did that miss cost” has a real answer only on OpenCode; elsewhere the answer is a token count. <strong>No rate card is ever applied to make a dollar figure appear.</strong> An estimate presented as a measurement poisons every comparison built on it.</p>
|
|
1833
|
-
|
|
1834
|
-
<div class="panel warn"><strong>Two exclusions, both applied AND displayed.</strong><br>
|
|
1835
|
-
<strong>(1) Attribution.</strong> A miss's <code>origin_model</code> is <em>looked up</em> from <code>runs.jsonl</code>, never typed by an agent — and when the lookup fails, the model is forced to <code>null</code> and the record marked <code>inferred</code>. Only <code>linked</code> records feed a per-phase / per-agent / per-model figure. A per-model miss rate computed partly from guesses is a routing decision made on invented evidence, and nothing in the output would reveal it.<br><br>
|
|
1836
|
-
<strong>(2) Cost.</strong> A fix run that repaired three misses has <em>one</em> token window; dividing it three ways is arithmetic, not measurement. <code>cost_attribution</code> marks each record <code>sole</code>, <code>shared:n</code> or <code>none</code>, and the report shows measured and apportioned as separate columns — never one blended number. A miss fixed inline with no distinct run cannot be costed at all, and is printed as such rather than dropped.<br><br>
|
|
1837
|
-
Both exclusions are reported <em>with</em> the figures they bound: an exclusion you cannot see is indistinguishable from a bug.</div>
|
|
1838
|
-
|
|
1839
|
-
<p>Escape rate keeps its existing definition and its existing source (<code>gates.jsonl</code> <code>gate:"escaped"</code>). The miss stream's own “found by a human” share sits <em>beside</em> it, never merged into it — one word cannot mean two things on one page.</p>
|
|
1840
|
-
|
|
1841
|
-
<h3 id="telemetry-gotchas">Two things that trip people up</h3>
|
|
1842
|
-
|
|
1843
|
-
<div class="panel ok"><strong>You do not need the commit hook to get metrics.</strong> Four of the five streams need <em>no</em> version-control hook at all: <code>runs</code>, <code>gates</code> and <code>misses</code> come from <code>tf-emit.sh</code> inside the phase tasks, and <code>sessions</code> from the Claude Code <code>SessionEnd</code> hook (or the OpenCode plugin) — neither of which is a version-control hook. Only <code>commits.jsonl</code> uses <code>.git/hooks/pre-commit</code>, and only for commit volume and cadence: nothing about <em>what was missed, who missed it, or what the fix cost</em> depends on it.<br><br>
|
|
1844
|
-
And even that hook is optional. <code>.tfcore/telemetry/tf-metrics.sh --backfill-commits .</code> reconstructs the identical records <em>perfectly</em> from the commit log at any time — that log is itself append-only, which is why commit records are the one backfill exempt from the live-vs-backfilled separation. The hook only makes it automatic.</div>
|
|
1845
|
-
|
|
1846
|
-
<div class="panel warn"><strong>A greenfield project is born labelled <code>docs</code>, and that used to stick.</strong> The greenfield scaffold classifies the repo at scaffold time, when it genuinely <em>is</em> docs-only — the day-1 documents exist and <code>src/</code> does not — and the old “auto-detected once, then never re-guessed” rule froze it there. TfLens accumulated <strong>225 gate records, visual gates included, under a <code>project_type</code> whose own definition says gates cannot fire</strong>, and whose figures never pool with the apps it belongs beside.<br><br>
|
|
1847
|
-
Since <strong>2026-08-28</strong> a later <code>update-framework.sh</code> re-examines <code>docs</code> <em>alone</em> and <strong>only upgrades</strong>: once real heads or a published package appear, the tree has answered a question that was unanswerable at scaffold time. <code>app</code> / <code>library</code> / <code>framework</code> are never re-guessed, an owner's <code>--type</code> always wins, and a genuine docs repo never grows a head so it is never touched. Correct one by hand at any time:
|
|
1848
|
-
<pre><code>.tfcore/telemetry/install-metrics.sh . --type app</code></pre>
|
|
1849
|
-
<strong>Records written before a correction keep the old value.</strong> The streams are append-only and corrections happen at <em>read</em> time, never by rewriting history — so a reclassified project appears under <strong>both</strong> segments, which the provenance rule forbids pooling. <code>--report</code> states the split explicitly rather than letting one project look like two; read each segment as a <em>period</em> of the project, not the whole of it.</div>
|
|
1850
|
-
|
|
1851
|
-
<div class="panel"><strong>Why some figures are never combined.</strong> The report will not print a single first-pass rate, gate catch distribution, or escape rate that pools <em>live</em> with <em>backfilled</em> records, or pools <code>app</code> with <code>library</code>/<code>docs</code> — not as a total row, not as an "overall" line. A backfilled attempt count is inferred from a status table that never recorded attempts, so a merged first-pass rate cannot be defended when someone asks how attempts were counted. A pooled gate distribution understates the visual gate, because library and docs projects never had screens to fail on. One indefensible figure contaminates every other number on the page. Commit-derived metrics are exempt — the commit log is a real append-only log, and commit volume is comparable across project types.</div>
|
|
1852
|
-
|
|
1853
|
-
<div class="panel"><strong>The one-commit lag.</strong> At <code>pre-commit</code> time HEAD is still the <em>previous</em> commit, so the record for the commit you are making ships inside the <em>next</em> one. Metrics lag reality by a commit, and that is unavoidable in either direction — a record of commit N cannot predate N. What changed on 2026-08-11 is that the record is now <em>committed</em> rather than left <em>pending</em>: writing after the commit was sealed (the original <code>post-commit</code> design) left <code>commits.jsonl</code> permanently dirty with no reachable clean state. Because the hook <em>reconciles</em> from the log rather than appending a single line, the lag never becomes a <em>loss</em> either: whichever machine commits next writes the missing record.
|
|
1854
|
-
|
|
1855
|
-
<br><br><strong>What it costs, stated plainly:</strong> the hook stages one file — <code>docs/metrics/commits.jsonl</code>, never a directory, never <code>-A</code> — into the commit you are making. On a partial commit (<code>git commit -- <paths></code>) it writes the record but does <em>not</em> stage, so it cannot add a file to a commit you deliberately scoped down, and it can never fail your commit (every path exits 0). <a href="#permissions">Agents still never run git</a>: this is your own <code>git commit</code>, no agent path reaches it, and <code>block-git.sh</code> is unchanged.</div>
|
|
1856
|
-
|
|
1857
|
-
<div class="panel"><strong>Several machines, one repo.</strong> The streams are tracked files, so they travel with push/pull. <code>.gitattributes</code> (managed by the scaffold/update scripts) gives <code>docs/metrics/*.jsonl</code> <code>merge=union</code> so two machines appending never conflict — hand-resolving a conflict in an append-only log is how records get silently dropped — and <code>eol=lf</code> so a machine-appended log never acquires mixed line endings. The <code>pre-commit</code> hook records every commit reachable from <code>HEAD</code> that the file lacks and stages it into the commit, so after a pull, your next commit picks up the other machine's history as well. The hook itself lives in <code>.git/hooks/</code> and therefore does <em>not</em> travel: run <code>update-framework.sh</code> once per clone, or <code>tf-metrics.sh --backfill-commits .</code> to fill that machine's history straight away.</div>
|
|
1858
|
-
|
|
1859
|
-
<div class="panel"><strong>Privacy — assume every record could become public.</strong> Records carry IDs, counts, durations, verdicts and file paths <em>at most</em>. Never requirement text, prompt text, file contents, or commit subjects — only a commit's conventional-commit prefix (<code>feat</code>/<code>fix</code>/…) is kept, and the subject is discarded on the spot. <code>failure_class</code> is a closed vocabulary for exactly this reason. This framework is used on employer projects, and these files are append-only: a leaked field is not something you fix later.</div>
|
|
1860
|
-
|
|
1861
|
-
<div class="panel"><strong>Telemetry has no veto.</strong> No metrics write can fail a build, block a tool call, abort a phase, or print an error. <code>tf-emit.sh</code> exits 0 unconditionally — missing directory, malformed JSON, absent <code>python3</code>, full disk — and the event is simply dropped. Same fail-open posture as the <code>guard-status</code> / <code>guard-verify</code> hooks. A telemetry bug must never cost you a working session.</div>
|
|
1862
|
-
|
|
1863
|
-
<h2 id="model-routing">17b. Model routing — run cheap phases on cheap models<span class="anchor-link"><a href="#model-routing">#</a></span></h2>
|
|
1864
|
-
|
|
1865
|
-
<div class="panel ok"><strong>Full guide</strong> — the complete phase AND persona/subagent tier tables, per-tier change recipes with examples, the TUI walkthrough, what gets generated under the hood, and troubleshooting: <code>docs/TechieFlow-Routing-Guide.md</code> (+ rendered <code>.html</code>) <em>in the TechieFlow framework repo</em>.</div>
|
|
1866
|
-
|
|
1867
|
-
<p><strong>What it is, in one example.</strong> Without routing, day-1 architecture and re-rendering HTML cost the same per token. With routing ON, each phase gets a <strong>tier</strong>, each tier maps to a real model:</p>
|
|
1868
|
-
|
|
1869
|
-
<table>
|
|
1870
|
-
<tr><th>Tier</th><th>Meant for</th><th>Claude</th><th>OpenCode (defaults — yours to change)</th><th>Codex</th></tr>
|
|
1871
|
-
<tr><td><code>frontier</code></td><td>expensive thinking: day-1, author-brd, amend-docs, fix-issues</td><td><code>opus</code></td><td><code>opencode-go/kimi-k3</code></td><td><code>gpt-5.6</code></td></tr>
|
|
1872
|
-
<tr><td><code>standard</code></td><td>everyday building: build, verify, mockups, split-brd, triage, devguide + builder subagents</td><td><code>sonnet</code></td><td><code>opencode-go/kimi-k2.7-code</code></td><td><code>gpt-5.6-terra</code></td></tr>
|
|
1873
|
-
<tr><td><code>economy</code></td><td>mechanical: metrics, renders, refresh-status, productguide, handoff</td><td><code>haiku</code></td><td><code>opencode-go/deepseek-v4-flash</code></td><td><code>gpt-5.6-luna</code></td></tr>
|
|
1874
|
-
</table>
|
|
1875
|
-
|
|
1876
|
-
<p>Measured example (TechieBlog pilot): a complete <code>metrics-report</code> phase on economy — 14k output tokens, full report — cost <strong>$0.036</strong>. Builders stay on <code>standard</code> deliberately: a cheap builder that ships a blank table costs an entire verify-and-fix cycle.</p>
|
|
1877
|
-
|
|
1878
|
-
<h3>Turn it on / off — one command</h3>
|
|
1879
|
-
<pre><code class="lang-bash">cd /path/to/YourApp
|
|
1880
|
-
bash .tfcore/utils/tf-routing.sh status # read-only: the live tier/model/phase table
|
|
1881
|
-
bash .tfcore/utils/tf-routing.sh on # enable — generates ~23 binding files
|
|
1882
|
-
bash .tfcore/utils/tf-routing.sh off # disable — removes exactly those files</code></pre>
|
|
1883
|
-
|
|
1884
|
-
<div class="panel warn"><strong>IMPORTANT — what you will (and won't) see in the TUI.</strong> Opening OpenCode looks <em>exactly the same as before</em>. That is deliberate: your normal chat runs on the default <code>build</code> agent, and routing never touches it — your conversation stays on the model YOU picked. Routing becomes visible in three places only: <strong>(1)</strong> run a phase command — <code>/techieflow:tasks:metrics-report YourApp</code> executes on the tier model and the footer shows it; <strong>(2)</strong> press <strong>Tab</strong> to a persona (<code>flow-master</code>, <code>flow-verifier</code>, …) — each carries its bound model; <strong>(3)</strong> the telemetry — every run lands in <code>docs/metrics/runs.jsonl</code> with declared tier, observed model, <code>routed: true/false</code>, tokens and (OpenCode) real cost.</div>
|
|
1885
|
-
|
|
1886
|
-
<div class="panel warn"><strong>Verified gotcha:</strong> after a routed command, that TUI session <em>stays on the phase's model</em> — it does not bounce back. Pick your model from the model list or start a new session if you keep chatting. Claude Code is the mirror image: a <code>/tf:<phase></code> wrapper's model lasts exactly one turn, then reverts automatically.</div>
|
|
1887
|
-
|
|
1888
|
-
<h3>A concrete first run (safe even mid-UAT)</h3>
|
|
1889
|
-
<p><code>metrics-report</code> reads the telemetry streams and writes only <code>docs/metrics/METRICS.md</code> + <code>.html</code> — no code, no status, no checklist:</p>
|
|
1890
|
-
<pre><code>1. bash .tfcore/utils/tf-routing.sh on
|
|
1891
|
-
2. opencode
|
|
1892
|
-
3. /techieflow:tasks:metrics-report YourApp
|
|
1893
|
-
4. watch the footer: it runs on deepseek-v4-flash, not your chat model
|
|
1894
|
-
5. tail -1 docs/metrics/sessions.jsonl → "model":"opencode-go/deepseek-v4-flash","cost_usd":0.03…</code></pre>
|
|
1895
|
-
|
|
1896
|
-
<h3>Changing the map — one command per change</h3>
|
|
1897
|
-
<pre><code class="lang-bash">bash .tfcore/utils/tf-routing.sh set-tier mockups frontier # promote a phase
|
|
1898
|
-
bash .tfcore/utils/tf-routing.sh set-tier verify-phase economy # demote a phase
|
|
1899
|
-
bash .tfcore/utils/tf-routing.sh set-model standard opencode opencode-go/qwen3.7-max
|
|
1900
|
-
bash .tfcore/utils/tf-routing.sh set-model economy claude haiku
|
|
1901
|
-
bash .tfcore/utils/tf-routing.sh set-model standard codex gpt-5.6-terra
|
|
1902
|
-
bash .tfcore/utils/tf-routing.sh bind # re-apply after hand-editing routing.yaml</code></pre>
|
|
1903
|
-
<p>Claude takes aliases or full ids; OpenCode takes <code>provider/model</code> ids; Codex takes model slugs available to the installed Codex CLI. A skill in the main Codex conversation inherits the active model; generated custom agents and <code>tf-goal.sh --harness codex</code> are the pinned-model path.</p>
|
|
1904
|
-
|
|
1905
|
-
<h3>Escalation — advisory, applied by you at launch</h3>
|
|
1906
|
-
<p><code>routing.yaml</code> also carries an <code>escalation:</code> block, shipped as <code>fix-issues: after_attempts: 2, tier: frontier</code> — "if the same REQs have been through <code>fix-issues</code> twice without reaching <code>Verified</code>, launch the third run on frontier". It is <strong>advisory</strong>: <code>bash .tfcore/utils/tf-emit.sh --next-run-attempt fix-issues <REQ-IDs></code> reads the attempt history (the <code>attempt</code> field now stamped on every <code>runs.jsonl</code> record that touches REQs), <code>tf-routing.sh status</code> prints the policy, and <code>tf-routing.sh set-escalation <phase> <attempts> <tier></code> tunes it. If the number exceeds the threshold, <em>you</em> launch the next run on the escalation tier (Claude: <code>/model opus</code> then the command; OpenCode: pick the model, then the command). Nothing ever switches a running phase's model — neither harness can (DECISIONS.md 2026-08-21; Routing Guide §6.4).</p>
|
|
1907
|
-
|
|
1908
|
-
<h3>Reading the results</h3>
|
|
1909
|
-
<p>Each run's record shows declared vs observed: <code>"tier":"standard", "model":"opencode-go/kimi-k2.7-code", "routed":true, "tokens_out":42310, "cost_usd":0.41</code>. The deciding question after a couple of weeks: <strong>does the rework ratio rise on cheaper tiers?</strong> If standard builders hold the first-pass rate, demote more; if <code>mode:"fix"</code> re-entries climb, promote. Data corrects the map, not opinion.</p>
|
|
1910
|
-
|
|
1911
|
-
<h3>FAQ</h3>
|
|
1912
|
-
<ul>
|
|
1913
|
-
<li><strong>"I turned it on and the TUI looks the same."</strong> Expected — see the IMPORTANT panel. Run a phase command or Tab to a persona.</li>
|
|
1914
|
-
<li><strong>"How do I make my normal chat cheaper too?"</strong> Not routing's job — pick a cheaper model in the TUI model list, or set <code>"model"</code> in <code>~/.config/opencode/opencode.jsonc</code>.</li>
|
|
1915
|
-
<li><strong>"status says flag and bindings disagree."</strong> <code>bash .tfcore/utils/tf-routing.sh bind</code>.</li>
|
|
1916
|
-
<li><strong>"Does update-framework.sh wipe my routing?"</strong> No — <code>routing.yaml</code> is preserved forever; refreshes re-generate your bindings from YOUR map (verified in the pilot).</li>
|
|
1917
|
-
<li><strong>"What gets generated?"</strong> OpenCode: <code>.opencode/opencode.json</code>. Claude: <code>.claude/commands/tf/*.md</code> + <code>.claude/agents/tf-*.md</code>. Codex: <code>.codex/agents/*.toml</code> + <code>.agents/skills/techieflow-*/</code>. All are gitignored and regenerated from the preserved routing map.</li>
|
|
1918
|
-
</ul>
|
|
1919
|
-
|
|
1920
|
-
<h2 id="team-edition">18. Team edition — the AI-First Playbook<span class="anchor-link"><a href="#team-edition">#</a></span></h2>
|
|
1921
|
-
|
|
1922
|
-
<p>TechieFlow is the <strong>solo edition</strong>. Its team-scale sibling is the
|
|
1923
|
-
<strong><a href="https://github.com/techierathore/AI-First-Playbook">AI-First Development Playbook</a></strong> —
|
|
1924
|
-
the same philosophy (<em>spec-driven, independently verified, execution-proven AI development</em>), sized for
|
|
1925
|
-
an engineering team with QA, BA and business stakeholders instead of one developer and a portfolio.</p>
|
|
1926
|
-
|
|
1927
|
-
<table>
|
|
1928
|
-
<thead><tr><th></th><th><strong>TechieFlow</strong> (this framework — solo edition)</th><th><strong><a href="https://github.com/techierathore/AI-First-Playbook">AI-First Playbook</a></strong> (team edition)</th></tr></thead>
|
|
1929
|
-
<tbody>
|
|
1930
|
-
<tr><td>Optimized for</td><td>One developer + AI, portfolio of ~8–10 apps</td><td>A team (~5–50 devs) on one large product</td></tr>
|
|
1931
|
-
<tr><td>Lifecycle</td><td>Compressed 5 phases — Day-1 → Split → Build → Verify → Handoff</td><td>10 steps, 4 gates, per-feature loop</td></tr>
|
|
1932
|
-
<tr><td>Unit of work</td><td>The <strong>run</strong> (hand a phase a checklist and go)</td><td>The <strong>feature</strong> (one living implementation checklist each)</td></tr>
|
|
1933
|
-
<tr><td>Checklist</td><td>One per app, all <code>REQ-UI/FN/NFR/RAG-*</code> rows in one table</td><td>One per feature</td></tr>
|
|
1934
|
-
<tr><td>Verifier</td><td>Playwright + Appium + <code>dotnet test</code>; data-render + visual-truth gates; hook-enforced verify ledger</td><td>Fresh-context verifier agent; execution-proven verdicts written inline</td></tr>
|
|
1935
|
-
<tr><td>Harness</td><td>Claude Code (<code>.tfcore/</code> + <code>.claude/</code>), OpenCode mirror</td><td>OpenCode + BMAD v4 personas</td></tr>
|
|
1936
|
-
<tr><td>Human docs</td><td>DevGuide, UsageGuide, ProductGuide</td><td>Developer-Flow-Guide, Business-Verification-Reference</td></tr>
|
|
1937
|
-
<tr><td>Also has</td><td>Telemetry (<a href="#telemetry">§17</a>), git ban + guard hooks, MAUI/Appium bridge, <code>*fix-issues</code> / <code>*triage-issues</code></td><td>Jira/Confluence integration, post-verification bug loop, team enablement & onboarding material</td></tr>
|
|
1938
|
-
</tbody>
|
|
1939
|
-
</table>
|
|
1940
|
-
|
|
1941
|
-
<p>Shared by both: markdown as the source of truth, Mermaid-only diagrams, HTML for human docs only,
|
|
1942
|
-
single-source-of-truth checklists, and <strong>"verify by executing, not by reading."</strong></p>
|
|
1943
|
-
|
|
1944
|
-
<div class="panel"><strong>Which one do you want?</strong> If you are one person driving agents across several apps, stay here. If you are rolling a process out to a team — where the hard parts are onboarding, review gates and shared standards rather than raw throughput — start with the Playbook; it ships enablement and onboarding material this framework deliberately does not carry. The two are independent repos: nothing here depends on the Playbook, and nothing there depends on this.</div>
|
|
1945
|
-
|
|
1946
|
-
<hr>
|
|
1947
|
-
<p class="small">Last revised 2026-08-28 (rev 2). Edit freely. When the workflow changes, update <code>README.md</code> and <code>WorkFlow-Context.md</code> (the durable cross-harness context document) too.</p>
|
|
1948
|
-
|
|
1949
|
-
</main>
|
|
1950
|
-
</div>
|
|
1951
|
-
|
|
1952
|
-
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
1953
|
-
<script>
|
|
1954
|
-
if (window.mermaid) {
|
|
1955
|
-
mermaid.initialize({ startOnLoad: true, theme: 'dark', securityLevel: 'loose', flowchart: { useMaxWidth: true, htmlLabels: true } });
|
|
1956
|
-
}
|
|
1957
|
-
</script>
|
|
1958
|
-
<script>
|
|
1959
|
-
document.querySelectorAll('.tabs').forEach(group => {
|
|
1960
|
-
const buttons = group.querySelectorAll('button');
|
|
1961
|
-
const panels = group.parentElement.querySelectorAll('.tabpanel');
|
|
1962
|
-
buttons.forEach(btn => {
|
|
1963
|
-
btn.addEventListener('click', () => {
|
|
1964
|
-
buttons.forEach(b => b.classList.remove('active'));
|
|
1965
|
-
panels.forEach(p => p.classList.remove('active'));
|
|
1966
|
-
btn.classList.add('active');
|
|
1967
|
-
document.getElementById('tab-' + btn.dataset.tab).classList.add('active');
|
|
1968
|
-
});
|
|
1969
|
-
});
|
|
1970
|
-
});
|
|
1971
|
-
document.querySelectorAll('pre:not(.mermaid)').forEach(pre => {
|
|
1972
|
-
const btn = document.createElement('button');
|
|
1973
|
-
btn.className = 'copy';
|
|
1974
|
-
btn.textContent = 'copy';
|
|
1975
|
-
btn.addEventListener('click', () => {
|
|
1976
|
-
const text = pre.querySelector('code') ? pre.querySelector('code').innerText : pre.innerText;
|
|
1977
|
-
navigator.clipboard.writeText(text).then(() => {
|
|
1978
|
-
btn.textContent = 'copied';
|
|
1979
|
-
setTimeout(() => { btn.textContent = 'copy'; }, 1200);
|
|
1980
|
-
});
|
|
1981
|
-
});
|
|
1982
|
-
pre.appendChild(btn);
|
|
1983
|
-
});
|
|
1984
|
-
</script>
|
|
1985
|
-
</body>
|
|
1986
|
-
</html>
|