-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
317 lines (273 loc) · 25.5 KB
/
Copy pathMakefile
File metadata and controls
317 lines (273 loc) · 25.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
.PHONY: validate demo validate-demo smoke-local-plugins validate-forgeflow-loop validate-full-loop-e2e validate-behavior-guardrails validate-json validate-no-python validate-slim-surface validate-ci-workflows validate-skills validate-skill-frontmatter validate-skill-modularity validate-agent-docs validate-templates validate-template-refs validate-template-fields validate-stage-handoff validate-versions validate-changelog-links validate-route-scoring-parity validate-route-policy validate-plugin-prompts validate-evals validate-evals-json validate-eval-files validate-evals-fixtures validate-workflow-vocab validate-ship-safety validate-dogfooding-docs validate-context-resume validate-stage-tool-boundaries validate-adapter-config validate-advisory-contract validate-markdown-links validate-guard-checks telemetry telemetry-collect telemetry-aggregate usage-audit
PYTHON ?= python3
PLUGIN_JSON := \
.agents/plugins/marketplace.json \
.claude-plugin/plugin.json \
.claude-plugin/marketplace.json \
TEMPLATES := \
brief.md \
project-draft.md \
plan.md \
review-report.md \
implementation-notes.md \
input-source.md \
normalized-input.md \
eval-record.md \
roadmap.md \
checkpoint.md \
run-state.json \
ledger.md \
evolution-rule.md \
ship-summary.md \
fact-extraction.md \
telemetry-event.md \
metrics-dashboard.md \
evidence-manifest.md \
re-execution-conditions.md
validate: validate-no-python validate-slim-surface validate-ci-workflows validate-json validate-versions validate-changelog-links validate-route-scoring-parity validate-route-policy validate-skills validate-skill-modularity validate-agent-docs validate-templates validate-template-refs validate-template-fields validate-demo validate-forgeflow-loop validate-full-loop-e2e validate-plugin-prompts validate-evals validate-workflow-vocab validate-ship-safety validate-dogfooding-docs validate-context-resume validate-stage-tool-boundaries validate-adapter-config validate-advisory-contract validate-behavior-guardrails validate-markdown-links validate-guard-checks
@echo "OK: local validation passed"
validate-evals: validate-evals-json validate-eval-files validate-evals-fixtures
@echo "OK: eval fixture validation bundle passed"
smoke-local-plugins:
@$(PYTHON) scripts/smoke_local_plugins.py
CODEX_LOCAL_PLUGIN_DIR ?= .codex/plugins/forgeflow
install-codex-local:
demo:
@tmp="$$(mktemp -d)"; \
task_dir="$$tmp/.forgeflow/tasks/demo-small"; \
mkdir -p "$$task_dir"; \
cp templates/brief.md "$$task_dir/brief.md"; \
cp templates/plan.md "$$task_dir/plan.md"; \
cp templates/ledger.md "$$task_dir/ledger.md"; \
cp templates/checkpoint.md "$$task_dir/checkpoint.md"; \
cp templates/run-state.json "$$task_dir/run-state.json"; \
cp templates/implementation-notes.md "$$task_dir/implementation-notes.md"; \
cp templates/review-report.md "$$task_dir/review-report.md"; \
cp templates/ship-summary.md "$$task_dir/ship-summary.md"; \
printf 'ForgeFlow demo workspace: %s\n' "$$tmp"; \
printf 'Mode: local template/artifact smoke only (not provider/plugin E2E).\n'; \
printf 'Task artifacts:\n'; \
find "$$task_dir" -maxdepth 1 -type f | sort; \
printf '\nNext: open the temp workspace and run /forgeflow:clarify for a real task.\n'
validate-demo:
@tmp="$$(mktemp -d)"; \
trap 'rm -rf "$$tmp"' EXIT; \
task_dir="$$tmp/.forgeflow/tasks/demo-small"; \
mkdir -p "$$task_dir"; \
for artifact in brief.md plan.md ledger.md checkpoint.md run-state.json implementation-notes.md review-report.md ship-summary.md; do \
cp "templates/$$artifact" "$$task_dir/$$artifact"; \
test -s "$$task_dir/$$artifact" || { echo "ERROR: demo artifact missing or empty: $$artifact"; exit 1; }; \
grep -Fq "$$artifact" README.md || { echo "ERROR: README first-run demo docs must mention $$artifact"; exit 1; }; \
done; \
grep -Fq "make demo" README.md || { echo "ERROR: README must document make demo"; exit 1; }; \
grep -Fq "make validate-demo" README.md || { echo "ERROR: README must document focused demo validation target"; exit 1; }; \
grep -Fq ".forgeflow/tasks/demo-small/" README.md || { echo "ERROR: README must document demo task path"; exit 1; }; \
grep -Fq "실제 provider/plugin E2E가 아니라" README.md || { echo "ERROR: README first-run demo docs must not overclaim provider/plugin E2E"; exit 1; }; \
grep -Fq "live provider/plugin E2E를 실행하지 않습니다" README.md || { echo "ERROR: README local validation docs must not overclaim provider/plugin E2E"; exit 1; }; \
grep -Fq "추적 파일을 수정하지 않으므로" README.md || { echo "ERROR: README demo docs must state repo-local artifacts are not mutated"; exit 1; }; \
grep -Fq "not provider/plugin E2E" Makefile || { echo "ERROR: make demo output must not overclaim provider/plugin E2E"; exit 1; }; \
count="$$(find "$$task_dir" -maxdepth 1 -type f | wc -l)"; \
if [ "$$count" -ne 8 ]; then \
echo "ERROR: demo workspace expected 8 artifacts, got $$count"; \
exit 1; \
fi
@echo "OK: demo workspace creates and documents first-run artifacts"
validate-forgeflow-loop:
@$(PYTHON) scripts/validate_forgeflow_loop.py
@grep -Fq "scripts/forgeflow_loop.py" README.md || { echo "ERROR: README must document the minimal forgeflow-loop CLI script"; exit 1; }
@grep -Fq "make validate-forgeflow-loop" README.md || { echo "ERROR: README local validation docs must include focused forgeflow-loop validation"; exit 1; }
validate-full-loop-e2e:
@$(PYTHON) scripts/validate_full_loop_e2e.py
@grep -Fq "make validate-full-loop-e2e" README.md || { echo "ERROR: README local validation docs must include disposable full-loop E2E validation"; exit 1; }
@grep -Fq "credential-free disposable full-loop E2E" README.md || { echo "ERROR: README must document credential-free disposable full-loop E2E scope"; exit 1; }
validate-no-python:
@count=$$(find . -name '*.py' -not -path './.git/*' -not -path './.venv/*' -not -path './scripts/*' | wc -l); \
if [ "$$count" -gt 0 ]; then \
echo "ERROR: Found $$count Python files outside scripts/ (should be 0)"; \
find . -name '*.py' -not -path './.git/*' -not -path './.venv/*' -not -path './scripts/*'; \
exit 1; \
fi
@echo "OK: No Python files found outside scripts/"
validate-slim-surface:
@tracked_legacy="$$(git ls-files 'forgeflow_runtime/**' 'schemas/**' 'tests/**')"; \
if [ -n "$$tracked_legacy" ]; then \
echo "ERROR: v1.x slim surface must not track legacy runtime/schema/test paths"; \
printf '%s\n' "$$tracked_legacy"; \
exit 1; \
fi
@matches="$$(git grep -nE 'forgeflow_runtime/|schemas/|tests/runtime|`tests/`' -- '*.md' ':!AGENTS.md' ':!CHANGELOG.md' || true)"; \
if [ -n "$$matches" ]; then \
echo "ERROR: Active v1.x docs must not reference removed runtime/schema/test trees"; \
printf '%s\n' "$$matches"; \
exit 1; \
fi
@grep -Fq "make validate-slim-surface" README.md || { echo "ERROR: README local validation docs must include focused slim-surface validation"; exit 1; }
@grep -Fq "tracked legacy runtime/schema/test directories are absent" README.md || { echo "ERROR: README local validation docs must mention slim-surface tracked directory absence"; exit 1; }
@echo "OK: Slim surface has no legacy runtime/schema/test directories or active-doc references"
validate-ci-workflows:
@$(PYTHON) scripts/validate_ci_workflows.py
validate-json:
@for f in $(PLUGIN_JSON); do \
$(PYTHON) -m json.tool "$$f" >/dev/null || exit 1; \
done
@echo "OK: Plugin configs are valid JSON"
validate-versions:
@$(PYTHON) scripts/validate_release_contract.py
validate-changelog-links:
@$(PYTHON) scripts/validate_changelog_links.py
@grep -Fq "make validate-versions validate-changelog-links" README.md || { echo "ERROR: README local validation docs must include focused release/version validation bundle"; exit 1; }
validate-route-scoring-parity:
@$(PYTHON) scripts/validate_route_scoring_parity.py
@grep -Fq "make validate-route-scoring-parity" README.md || { echo "ERROR: README local validation docs must include focused route-scoring parity validation"; exit 1; }
validate-route-policy:
@$(PYTHON) scripts/validate_route_policy.py
validate-skill-frontmatter:
@bash scripts/validate-skill-frontmatter.sh
validate-skill-modularity:
@$(PYTHON) scripts/validate_skill_modularity.py
@grep -Fq "make validate-skill-modularity" README.md || { echo "ERROR: README local validation docs must include focused skill modularity validation"; exit 1; }
@grep -Fq "docs/skill-modularization.md" README.md || { echo "ERROR: README must document the skill modularization policy"; exit 1; }
validate-skills: validate-skill-frontmatter
@$(PYTHON) scripts/validate_skills_structure.py
validate-agent-docs:
@$(PYTHON) scripts/validate_agent_docs.py
validate-templates:
@$(PYTHON) scripts/validate_templates_structure.py
validate-template-refs:
@$(PYTHON) scripts/validate_template_refs.py
validate-template-fields:
@$(PYTHON) scripts/validate_template_fields.py
validate-stage-handoff:
@$(PYTHON) scripts/validate_template_fields.py
@echo "OK: stage-to-stage handoff checks passed"
validate-plugin-prompts:
@$(PYTHON) scripts/validate_plugin_prompts.py
validate-evals-json:
@$(PYTHON) scripts/validate_evals_json.py
validate-eval-files:
@$(PYTHON) scripts/validate_eval_files.py
validate-workflow-vocab:
@$(PYTHON) scripts/validate_workflow_vocab.py
@grep -Fq "같은 \`/forgeflow:ff-review\`" README.md || { echo "ERROR: README must clarify high/epic spec/quality passes use the same review command"; exit 1; }
@grep -Fq "observe" README.md || { echo "ERROR: README evolution lifecycle must describe ship-based observe stage"; exit 1; }
@grep -Fq "extract" README.md || { echo "ERROR: README evolution lifecycle must describe ship-based extract stage"; exit 1; }
@if grep -Fq 'proposed' README.md; then grep -Fq '별도 `proposed`' README.md || { echo "ERROR: README evolution lifecycle must not reference old proposed stage without explaining it was replaced"; exit 1; }; fi
validate-ship-safety:
@$(PYTHON) scripts/validate_safety_docs.py --ship-safety
validate-dogfooding-docs:
@$(PYTHON) scripts/validate_safety_docs.py --dogfooding
validate-context-resume:
@$(PYTHON) scripts/validate_context_resume.py
validate-stage-tool-boundaries:
@for stage in clarify plan execute ff-review ship; do \
grep -Fq "| $$stage |" docs/stage-tool-boundaries.md || { echo "ERROR: stage tool boundaries must catalog $$stage"; exit 1; }; \
done
@grep -Fq "Stage artifacts are the handoff boundary" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must keep artifact handoff as the boundary"; exit 1; }
@grep -Fq "Use the smallest tool surface" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must require minimal tool surface"; exit 1; }
@grep -Fq "record the need in the current artifact and hand off to the stage that owns it" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must require forbidden-action handoff"; exit 1; }
@grep -Fq "current owner" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must name current owner for escalations"; exit 1; }
@grep -Fq "next owner" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must name next owner for escalations"; exit 1; }
@grep -Fq "requested/forbidden action" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must name requested/forbidden action for escalations"; exit 1; }
@grep -Fq "evidence or artifact trigger" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must name evidence/artifact trigger for escalations"; exit 1; }
@grep -Fq "explicit stop condition" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must require explicit stop condition for escalations"; exit 1; }
@grep -Fq "exact artifact update location" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must require exact artifact update location for escalations"; exit 1; }
@grep -Fq "same escalation field set as the checkpoint boundary" skills/_shared/automation.md || { echo "ERROR: automation stage catalog must mirror escalation handoff fields"; exit 1; }
@grep -Fq "must not change artifact names, route semantics, review verdicts, or human-gate rules" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must keep adapter exceptions from changing canonical semantics"; exit 1; }
@grep -Fq "review-report.md" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must require review-report.md for ff-review"; exit 1; }
@grep -Fq "input-source.md" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must include standalone review provenance artifacts"; exit 1; }
@grep -Fq "normalized-input.md" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must include standalone review normalized input artifacts"; exit 1; }
@grep -Fq "mutate PR/issues/CI/deploys" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must forbid review-side external mutations"; exit 1; }
@grep -Fq "approve from implementer self-report only" docs/stage-tool-boundaries.md || { echo "ERROR: stage boundary docs must forbid self-report-only review approval"; exit 1; }
@grep -Fq "make validate-stage-tool-boundaries" README.md || { echo "ERROR: README local validation docs must include focused stage boundary validation"; exit 1; }
@echo "OK: Stage tool boundary catalog preserves adapter-neutral artifact ownership and review read-only posture"
validate-adapter-config:
@$(PYTHON) scripts/validate_adapter_config.py
@grep -Fq "historical reference" docs/adapter-config.md || { echo "ERROR: adapter performance docs must not overclaim current live provider SLA"; exit 1; }
@grep -Fq "설치 위치와 작업 위치를 분리하세요" README.md || { echo "ERROR: README quickstart must separate plugin/extension install location from target project workflow location"; exit 1; }
@grep -Fq "make validate-adapter-config" README.md || { echo "ERROR: README local validation docs must include focused adapter config validation"; exit 1; }
@grep -Fq "**작업 위치 원칙:**" docs/adapter-config.md || { echo "ERROR: adapter config must state the shared workflow location principle"; exit 1; }
@grep -Fq "\`<task-dir>/brief.md\`, \`plan.md\`, \`implementation-notes.md\`, \`review-report.md\`, \`ledger.md\`, \`checkpoint.md\`, \`run-state.json\`" README.md || { echo "ERROR: README installed plugin smoke criteria must include the plan.md artifact"; exit 1; }
@grep -Fq "plugin/extension 설치·cache 위치" docs/adapter-config.md || { echo "ERROR: adapter config must distinguish plugin/extension cache from target projects"; exit 1; }
@grep -Fq -- "--task-dir ~/.forgeflow/projects/<project-slug>/tasks/<task-id>" docs/adapter-config.md || { echo "ERROR: adapter config must document explicit global task-dir fallback from cache contexts"; exit 1; }
@grep -Fq "Multi-harness routing invariants" docs/adapter-config.md || { echo "ERROR: adapter config must document multi-harness routing invariants"; exit 1; }
@grep -Fq "Canonical stage contract first" docs/adapter-config.md || { echo "ERROR: adapter config must keep canonical stage contract ahead of adapter exceptions"; exit 1; }
@grep -Fq "Harness-specific code paths stay shallow" docs/adapter-config.md || { echo "ERROR: adapter config must keep harness-specific code paths shallow"; exit 1; }
@grep -Fq "Artifact handoff is the boundary" docs/adapter-config.md || { echo "ERROR: adapter config must require markdown artifact handoff boundaries"; exit 1; }
@grep -Fq "Review adapters normalize before judging" docs/adapter-config.md || { echo "ERROR: adapter config must require review adapters to normalize before judging"; exit 1; }
@grep -Fq "Multi-harness 원칙" README.md || { echo "ERROR: README must expose multi-harness invariants to users"; exit 1; }
@grep -Fq "adapter-neutral core contract" README.md || { echo "ERROR: README must state adapter-neutral core contract boundaries"; exit 1; }
@grep -Fq "역할 경계 원칙" README.md || { echo "ERROR: README must expose stage-owned role boundary principles"; exit 1; }
@grep -Fq "Stage-owned role boundaries" docs/stage-tool-boundaries.md || { echo "ERROR: stage tool boundary docs must document role boundaries"; exit 1; }
@grep -Fq "not a license to create a parallel runtime" docs/stage-tool-boundaries.md || { echo "ERROR: role boundary docs must prevent parallel runtime drift"; exit 1; }
@grep -Fq "Members must not spawn unmanaged child work" docs/stage-tool-boundaries.md || { echo "ERROR: role boundary docs must block unmanaged member child-work"; exit 1; }
@grep -Fq "lead-owned artifact update before work continues" docs/stage-tool-boundaries.md || { echo "ERROR: role boundary docs must require lead-owned artifact updates for member scope changes"; exit 1; }
validate-evals-fixtures:
@$(PYTHON) scripts/validate_evals_fixtures.py
@grep -Fq "not a live provider benchmark" evals/README.md || { echo "ERROR: evals README must not overclaim live provider benchmarking"; exit 1; }
@grep -Fq "make validate-evals-json validate-eval-files validate-evals-fixtures" evals/README.md || { echo "ERROR: evals README must document the local eval validation bundle"; exit 1; }
@grep -Fq "next sequential" evals/README.md || { echo "ERROR: evals README must document sequential fixture IDs"; exit 1; }
@grep -Fq "fixture text avoids stale workflow vocabulary" evals/README.md || { echo "ERROR: evals README must document stale-vocabulary fixture guard"; exit 1; }
@grep -Fq "remains the public bootstrap skill" evals/README.md || { echo "ERROR: evals README must clarify forgeflow-init is bootstrap, not removed workflow stage"; exit 1; }
@grep -Fq "ship-stage fixture names use \`ship-*\` slugs" evals/README.md || { echo "ERROR: evals README must document ship-stage fixture slug naming"; exit 1; }
@! grep -Fq '"name": "finish-' evals/evals.json || { echo "ERROR: ship-stage eval fixture names must not use removed finish-stage slugs"; exit 1; }
@grep -Fq "These are benchmark fixture sizes, not ForgeFlow route labels" skills/benchmark/SKILL.md || { echo "ERROR: benchmark skill must distinguish benchmark sizes from workflow route labels"; exit 1; }
@grep -Fq "Do not report \`large\` as a workflow route" skills/benchmark/SKILL.md || { echo "ERROR: benchmark skill must forbid treating large as a workflow route"; exit 1; }
@grep -Fq "Benchmark output lives under a disposable benchmark root" skills/benchmark/SKILL.md || { echo "ERROR: benchmark skill must keep reports/logs under disposable benchmark root"; exit 1; }
@grep -Fq "Do not write benchmark reports, logs, metrics, prompts, or generated app projects into this ForgeFlow source checkout" skills/benchmark/SKILL.md || { echo "ERROR: benchmark skill must protect the ForgeFlow source checkout during benchmarks"; exit 1; }
@grep -Fq "eval names use kebab-case" evals/README.md || { echo "ERROR: evals README must document kebab-case eval names"; exit 1; }
@grep -Fq "is not duplicated within the same eval case" evals/README.md || { echo "ERROR: evals README must document unique file reference rules"; exit 1; }
@grep -Fq "assertion \`value\` / \`values\` entries are non-blank strings" evals/README.md || { echo "ERROR: evals README must document non-blank assertion value rules"; exit 1; }
@grep -Fq "multi-value assertion \`values\` entries are unique" evals/README.md || { echo "ERROR: evals README must document unique multi-value assertion rules"; exit 1; }
@grep -Fq "assertion \`text\` entries are unique within each eval case" evals/README.md || { echo "ERROR: evals README must document per-case unique assertion text rules"; exit 1; }
@grep -Fq "every machine-checkable requirement must be mirrored in \`assertions\`" evals/README.md || { echo "ERROR: evals README must document expected_output/assertions separation"; exit 1; }
@grep -Fq "benchmark fixtures must use \`/forgeflow:benchmark\`" evals/README.md || { echo "ERROR: evals README must document benchmark fixture command scope"; exit 1; }
@grep -Fq "long-run evolution fixtures record candidate notes" evals/README.md || { echo "ERROR: evals README must document long-run candidate-note scope"; exit 1; }
@grep -Fq "git push origin HEAD:refs/heads/main" evals/README.md || { echo "ERROR: evals README must document explicit branch push for autonomous maintainer fixtures"; exit 1; }
@grep -Fq "without writing .forgeflow/evolution/proposed/ files directly" evals/evals.json || { echo "ERROR: long-run eval fixture must not ask long-run to write evolution-rule files directly"; exit 1; }
@grep -Fq "Evolution rule materialization is handled by the **ship** stage" skills/long-run/SKILL.md || { echo "ERROR: long-run skill must leave evolution rule materialization to ship"; exit 1; }
@grep -Fq "별도 \`proposed\`" README.md || { echo "ERROR: README evolution lifecycle must state proposed/review intermediate steps were removed"; exit 1; }
@grep -Fq "evolution rule 생성은 ship 단계에서 직접" README.md || { echo "ERROR: README must say ship creates evolution rules directly"; exit 1; }
@grep -Fq "\`.github/workflows/evals.yml\`" README.md || { echo "ERROR: README must name the evals workflow file for eval fixture checks"; exit 1; }
@grep -Fq "make validate-markdown-links" README.md || { echo "ERROR: README local validation docs must include focused markdown link validation"; exit 1; }
@grep -Fq "HTML href/src" README.md || { echo "ERROR: README local validation docs must mention HTML href/src link coverage"; exit 1; }
@echo "OK: eval README documents deterministic scope and local validation"
validate-advisory-contract:
@$(PYTHON) scripts/validate_advisory_contract.py
@grep -Fq "Evidence requirements by role" skills/ff-review/references/role-checklists.md || { echo "ERROR: review role checklists must document evidence requirements by role"; exit 1; }
@grep -Fq "normalization gate" skills/ff-review/SKILL.md || { echo "ERROR: review skill must require a standalone normalization gate before role passes"; exit 1; }
@grep -Fq "normalization gate" skills/ff-review/references/role-checklists.md || { echo "ERROR: role checklists must block on incomplete normalized input"; exit 1; }
@grep -Fq "normalization gate" templates/normalized-input.md || { echo "ERROR: normalized input template must expose a reviewer preflight gate"; exit 1; }
@grep -Fq "Normalization Gate" templates/review-report.md || { echo "ERROR: review report template must surface standalone normalization gate status"; exit 1; }
@grep -Fq "Evidence requirements source" templates/review-report.md || { echo "ERROR: review report template must point to role evidence requirements"; exit 1; }
@grep -Fq "Role capability hints" templates/review-report.md || { echo "ERROR: review report template must expose advisory role capability hints"; exit 1; }
@grep -Fq "must not affect routing, evidence IDs, evidence levels, verdict enums, approval rules, or Human Review Gate" templates/review-report.md || { echo "ERROR: review report role capability hints must stay advisory-only"; exit 1; }
@grep -Fq "Review tool posture" skills/ff-review/SKILL.md || { echo "ERROR: review skill must document inspection-only tool posture"; exit 1; }
@grep -Fq "role_reassignment_policy" templates/normalized-input.md || { echo "ERROR: normalized input template must guard delegated reviewer role reassignment"; exit 1; }
@grep -Fq "members cannot create additional reviewer roles" skills/ff-review/SKILL.md skills/ff-review/references/*.md || { echo "ERROR: review skill must keep delegated reviewer role creation lead-only"; exit 1; }
@grep -Fq "fetching declared review input through read-only commands" skills/ff-review/SKILL.md || { echo "ERROR: review skill must keep external evidence fetches read-only"; exit 1; }
@grep -Fq "issue comments, PR reviews, approvals, labels, CI dispatch, deploys" skills/ff-review/SKILL.md || { echo "ERROR: review skill must forbid remote review-side mutations"; exit 1; }
@grep -Fq "hand it back to execute" skills/ff-review/SKILL.md || { echo "ERROR: review skill must hand code/product fixes back to execute"; exit 1; }
@grep -Fq "role별 evidence requirement" README.md || { echo "ERROR: README standalone review docs must mention role-specific evidence requirements"; exit 1; }
@grep -Fq "external-system access to read-only evidence fetching" README.md || { echo "ERROR: README standalone review docs must expose read-only external-system posture"; exit 1; }
@grep -Fq "Evidence Gap Register" docs/review-runtime-contract.md || { echo "ERROR: review runtime contract must require standalone evidence gap registration"; exit 1; }
@grep -Fq "scope_source_map" docs/review-runtime-contract.md || { echo "ERROR: review runtime contract must require scope-to-evidence mapping"; exit 1; }
@grep -Fq "Evidence Gap Register" templates/normalized-input.md || { echo "ERROR: normalized input template must expose evidence gap registration"; exit 1; }
@grep -Fq "scope_source_map" templates/normalized-input.md || { echo "ERROR: normalized input template must expose scope-to-evidence mapping"; exit 1; }
@grep -Fq "Evidence Gap Register" templates/review-report.md || { echo "ERROR: review report template must cite standalone evidence gap registration"; exit 1; }
validate-behavior-guardrails:
@$(PYTHON) scripts/validate_behavior_guardrails.py
validate-markdown-links:
@PYTHON="$(PYTHON)" bash scripts/validate-markdown-links.sh
validate-guard-checks:
@$(PYTHON) scripts/validate_guard_checks.py
@$(PYTHON) scripts/validate_stage_guard_checks.py
# ---------------------------------------------------------------------------
# Telemetry
# ---------------------------------------------------------------------------
telemetry: telemetry-collect telemetry-aggregate
telemetry-collect:
@$(PYTHON) scripts/telemetry_collect.py
telemetry-aggregate:
@$(PYTHON) scripts/telemetry_aggregate.py
usage-audit:
@$(PYTHON) scripts/surface_usage_audit.py --days 28