@tyroneross/build-loop 0.30.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/.agents/plugins/marketplace.json +10 -0
- package/.claude-plugin/marketplace.json +38 -0
- package/.claude-plugin/plugin.json +30 -0
- package/.codex-plugin/plugin.json +41 -0
- package/.cursor/rules/build-loop-surface.mdc +22 -0
- package/AGENTS.md +498 -0
- package/LICENSE +202 -0
- package/README.md +403 -0
- package/agents/alignment-checker.md +124 -0
- package/agents/api-assessor.md +136 -0
- package/agents/architecture-scout.md +185 -0
- package/agents/assessment-orchestrator.md +163 -0
- package/agents/build-orchestrator.md +198 -0
- package/agents/database-assessor.md +133 -0
- package/agents/design-contract-specialist.md +239 -0
- package/agents/fact-checker.md +69 -0
- package/agents/fix-critique.md +161 -0
- package/agents/frontend-assessor.md +136 -0
- package/agents/implementer.md +185 -0
- package/agents/independent-auditor.md +143 -0
- package/agents/mock-scanner.md +78 -0
- package/agents/optimize-runner.md +112 -0
- package/agents/overfitting-reviewer.md +96 -0
- package/agents/performance-assessor.md +159 -0
- package/agents/plan-critic.md +85 -0
- package/agents/promotion-reviewer.md +121 -0
- package/agents/recurring-pattern-detector.md +248 -0
- package/agents/retrospective-synthesizer.md +109 -0
- package/agents/root-cause-investigator.md +285 -0
- package/agents/scope-auditor.md +121 -0
- package/agents/security-reviewer.md +151 -0
- package/agents/self-improvement-architect.md +125 -0
- package/agents/synthesis-critic.md +99 -0
- package/agents/transcript-pattern-miner.md +165 -0
- package/agents/ui-validator.md +193 -0
- package/codex-skills/build-loop/SKILL.md +20 -0
- package/codex-skills/debug-loop/SKILL.md +18 -0
- package/codex-skills/handoff/SKILL.md +22 -0
- package/codex-skills/knowledge/SKILL.md +21 -0
- package/codex-skills/optimize/SKILL.md +18 -0
- package/codex-skills/research/SKILL.md +18 -0
- package/commands/agent-rally-point.md +301 -0
- package/commands/assess.md +41 -0
- package/commands/debug.md +20 -0
- package/commands/debugger-detail.md +34 -0
- package/commands/debugger-scan.md +15 -0
- package/commands/debugger-status.md +20 -0
- package/commands/debugger.md +32 -0
- package/commands/handoff.md +113 -0
- package/commands/knowledge-review.md +16 -0
- package/commands/optimize.md +31 -0
- package/commands/plan-verify.md +39 -0
- package/commands/promote-experiment.md +129 -0
- package/commands/research.md +22 -0
- package/commands/run.md +12 -0
- package/commands/self-review.md +51 -0
- package/commands/start-prd.md +57 -0
- package/commands/test.md +34 -0
- package/dist/src/assessment-orchestrator.d.ts +78 -0
- package/dist/src/assessment-orchestrator.d.ts.map +1 -0
- package/dist/src/assessment-orchestrator.js +304 -0
- package/dist/src/assessment-orchestrator.js.map +1 -0
- package/dist/src/audit-miner.d.ts +21 -0
- package/dist/src/audit-miner.d.ts.map +1 -0
- package/dist/src/audit-miner.js +421 -0
- package/dist/src/audit-miner.js.map +1 -0
- package/dist/src/batch-operations.d.ts +30 -0
- package/dist/src/batch-operations.d.ts.map +1 -0
- package/dist/src/batch-operations.js +339 -0
- package/dist/src/batch-operations.js.map +1 -0
- package/dist/src/config.d.ts +83 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +176 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/context-engine.d.ts +45 -0
- package/dist/src/context-engine.d.ts.map +1 -0
- package/dist/src/context-engine.js +135 -0
- package/dist/src/context-engine.js.map +1 -0
- package/dist/src/debug-wrapper.d.ts +58 -0
- package/dist/src/debug-wrapper.d.ts.map +1 -0
- package/dist/src/debug-wrapper.js +285 -0
- package/dist/src/debug-wrapper.js.map +1 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +149 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interactive-verifier.d.ts +26 -0
- package/dist/src/interactive-verifier.d.ts.map +1 -0
- package/dist/src/interactive-verifier.js +435 -0
- package/dist/src/interactive-verifier.js.map +1 -0
- package/dist/src/lessons.d.ts +59 -0
- package/dist/src/lessons.d.ts.map +1 -0
- package/dist/src/lessons.js +172 -0
- package/dist/src/lessons.js.map +1 -0
- package/dist/src/log-reader.d.ts +39 -0
- package/dist/src/log-reader.d.ts.map +1 -0
- package/dist/src/log-reader.js +291 -0
- package/dist/src/log-reader.js.map +1 -0
- package/dist/src/logger.d.ts +59 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +328 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/parallel-retrieval.d.ts +52 -0
- package/dist/src/parallel-retrieval.d.ts.map +1 -0
- package/dist/src/parallel-retrieval.js +309 -0
- package/dist/src/parallel-retrieval.js.map +1 -0
- package/dist/src/pattern-extractor.d.ts +30 -0
- package/dist/src/pattern-extractor.d.ts.map +1 -0
- package/dist/src/pattern-extractor.js +386 -0
- package/dist/src/pattern-extractor.js.map +1 -0
- package/dist/src/result-aggregator.d.ts +44 -0
- package/dist/src/result-aggregator.d.ts.map +1 -0
- package/dist/src/result-aggregator.js +315 -0
- package/dist/src/result-aggregator.js.map +1 -0
- package/dist/src/retrieval.d.ts +139 -0
- package/dist/src/retrieval.d.ts.map +1 -0
- package/dist/src/retrieval.js +724 -0
- package/dist/src/retrieval.js.map +1 -0
- package/dist/src/setup/auto-setup.d.ts +15 -0
- package/dist/src/setup/auto-setup.d.ts.map +1 -0
- package/dist/src/setup/auto-setup.js +157 -0
- package/dist/src/setup/auto-setup.js.map +1 -0
- package/dist/src/setup/configure-hooks.d.ts +8 -0
- package/dist/src/setup/configure-hooks.d.ts.map +1 -0
- package/dist/src/setup/configure-hooks.js +16 -0
- package/dist/src/setup/configure-hooks.js.map +1 -0
- package/dist/src/setup/create-slash-commands.d.ts +8 -0
- package/dist/src/setup/create-slash-commands.d.ts.map +1 -0
- package/dist/src/setup/create-slash-commands.js +101 -0
- package/dist/src/setup/create-slash-commands.js.map +1 -0
- package/dist/src/setup/index.d.ts +8 -0
- package/dist/src/setup/index.d.ts.map +1 -0
- package/dist/src/setup/index.js +17 -0
- package/dist/src/setup/index.js.map +1 -0
- package/dist/src/setup/inject-claude-md.d.ts +10 -0
- package/dist/src/setup/inject-claude-md.d.ts.map +1 -0
- package/dist/src/setup/inject-claude-md.js +150 -0
- package/dist/src/setup/inject-claude-md.js.map +1 -0
- package/dist/src/setup/uninstall.d.ts +22 -0
- package/dist/src/setup/uninstall.d.ts.map +1 -0
- package/dist/src/setup/uninstall.js +235 -0
- package/dist/src/setup/uninstall.js.map +1 -0
- package/dist/src/storage.d.ts +192 -0
- package/dist/src/storage.d.ts.map +1 -0
- package/dist/src/storage.js +1037 -0
- package/dist/src/storage.js.map +1 -0
- package/dist/src/string-similarity.d.ts +8 -0
- package/dist/src/string-similarity.d.ts.map +1 -0
- package/dist/src/string-similarity.js +57 -0
- package/dist/src/string-similarity.js.map +1 -0
- package/dist/src/traces/adapters/browser.d.ts +69 -0
- package/dist/src/traces/adapters/browser.d.ts.map +1 -0
- package/dist/src/traces/adapters/browser.js +280 -0
- package/dist/src/traces/adapters/browser.js.map +1 -0
- package/dist/src/traces/adapters/index.d.ts +23 -0
- package/dist/src/traces/adapters/index.d.ts.map +1 -0
- package/dist/src/traces/adapters/index.js +67 -0
- package/dist/src/traces/adapters/index.js.map +1 -0
- package/dist/src/traces/adapters/langchain.d.ts +42 -0
- package/dist/src/traces/adapters/langchain.d.ts.map +1 -0
- package/dist/src/traces/adapters/langchain.js +151 -0
- package/dist/src/traces/adapters/langchain.js.map +1 -0
- package/dist/src/traces/adapters/opentelemetry.d.ts +46 -0
- package/dist/src/traces/adapters/opentelemetry.d.ts.map +1 -0
- package/dist/src/traces/adapters/opentelemetry.js +164 -0
- package/dist/src/traces/adapters/opentelemetry.js.map +1 -0
- package/dist/src/traces/adapters/sentry.d.ts +58 -0
- package/dist/src/traces/adapters/sentry.d.ts.map +1 -0
- package/dist/src/traces/adapters/sentry.js +212 -0
- package/dist/src/traces/adapters/sentry.js.map +1 -0
- package/dist/src/traces/index.d.ts +10 -0
- package/dist/src/traces/index.d.ts.map +1 -0
- package/dist/src/traces/index.js +45 -0
- package/dist/src/traces/index.js.map +1 -0
- package/dist/src/traces/storage.d.ts +78 -0
- package/dist/src/traces/storage.d.ts.map +1 -0
- package/dist/src/traces/storage.js +399 -0
- package/dist/src/traces/storage.js.map +1 -0
- package/dist/src/traces/summarizer.d.ts +83 -0
- package/dist/src/traces/summarizer.d.ts.map +1 -0
- package/dist/src/traces/summarizer.js +247 -0
- package/dist/src/traces/summarizer.js.map +1 -0
- package/dist/src/traces/types.d.ts +365 -0
- package/dist/src/traces/types.d.ts.map +1 -0
- package/dist/src/traces/types.js +14 -0
- package/dist/src/traces/types.js.map +1 -0
- package/dist/src/types.d.ts +495 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +27 -0
- package/dist/src/types.js.map +1 -0
- package/docs/agent-surface-policy.md +45 -0
- package/docs/memory-setup.md +226 -0
- package/hooks/_arch_scan_bg.py +88 -0
- package/hooks/_plugin_drift_check_bg.py +85 -0
- package/hooks/_session_start_lib.sh +42 -0
- package/hooks/git/pre-push +141 -0
- package/hooks/hooks.json +126 -0
- package/hooks/post-commit +30 -0
- package/hooks/pre-commit +29 -0
- package/hooks/pre-edit-apppulse.sh +6 -0
- package/hooks/pre-edit-architecture.sh +106 -0
- package/hooks/pre-edit-rally-point.sh +92 -0
- package/hooks/session-start-apppulse.sh +6 -0
- package/hooks/session-start-architecture.sh +10 -0
- package/hooks/session-start-git-hooks.sh +12 -0
- package/hooks/session-start-plugin-drift.sh +27 -0
- package/hooks/session-start-rally-point.sh +44 -0
- package/hooks/session-start-retrieval.sh +24 -0
- package/hooks/session-start-worktree-gc.sh +105 -0
- package/hooks/test_apppulse_hooks.sh +6 -0
- package/hooks/test_rally_point_hooks.sh +388 -0
- package/hooks/test_sec008_hooks.sh +66 -0
- package/package.json +111 -0
- package/scripts/README.md +301 -0
- package/scripts/_db_url.py +61 -0
- package/scripts/_paths.py +445 -0
- package/scripts/blm.py +162 -0
- package/scripts/blm_api.py +263 -0
- package/scripts/check_cache_sync.py +490 -0
- package/scripts/embed_backend.py +475 -0
- package/scripts/install_memory.py +556 -0
- package/scripts/lessons_index/__init__.py +77 -0
- package/scripts/lessons_index/__main__.py +135 -0
- package/scripts/lessons_index/ingest.py +288 -0
- package/scripts/lessons_index/query.py +285 -0
- package/scripts/lessons_index/schema.py +114 -0
- package/scripts/memory_context/__init__.py +610 -0
- package/scripts/memory_graph/__init__.py +393 -0
- package/scripts/project_resolver.py +172 -0
- package/scripts/prune_codex_plugin_cache.py +23 -0
- package/scripts/prune_plugin_cache.py +359 -0
- package/scripts/semantic_index/__init__.py +482 -0
- package/scripts/semantic_index/_bench_hybrid.py +175 -0
- package/scripts/semantic_index/backfill.py +263 -0
- package/scripts/semantic_index/hybrid.py +174 -0
- package/scripts/semantic_index/test_backfill.py +292 -0
- package/scripts/semantic_index/test_hybrid.py +541 -0
- package/scripts/sync_navgator_lessons.py +666 -0
- package/scripts/sync_plugin_cache.py +388 -0
- package/skills/agent-rally-point/SKILL.md +165 -0
- package/skills/agent-rally-watcher/SKILL.md +83 -0
- package/skills/api-registry-bridge/SKILL.md +59 -0
- package/skills/architecture/dead/SKILL.md +56 -0
- package/skills/architecture/impact/SKILL.md +88 -0
- package/skills/architecture/review/SKILL.md +227 -0
- package/skills/architecture/rules/SKILL.md +72 -0
- package/skills/architecture/scan/SKILL.md +79 -0
- package/skills/architecture/trace/SKILL.md +65 -0
- package/skills/attribution-standard/SKILL.md +122 -0
- package/skills/authentication/SKILL.md +81 -0
- package/skills/authentication/references/better-auth-magic-link.md +135 -0
- package/skills/authentication/references/better-auth-setup.md +224 -0
- package/skills/authentication/references/google-calendar-sync.md +278 -0
- package/skills/authentication/references/google-cloud-console.md +159 -0
- package/skills/authentication/references/google-geocoding-directions.md +126 -0
- package/skills/authentication/references/google-lessons-example-web-app.md +177 -0
- package/skills/authentication/references/google-maps.md +162 -0
- package/skills/authentication/references/google-oauth-setup.md +343 -0
- package/skills/authentication/references/google-places.md +173 -0
- package/skills/authentication/references/lessons-example-web-app-better-auth.md +126 -0
- package/skills/authentication/references/resend-email.md +227 -0
- package/skills/authentication/references/resend-otp-magic-link.md +153 -0
- package/skills/authentication/references/supabase-auth.md +172 -0
- package/skills/auto-decision-capture/SKILL.md +419 -0
- package/skills/build-loop/SKILL.md +516 -0
- package/skills/build-loop/detect-plugins.mjs +82 -0
- package/skills/build-loop/eval-guide.md +65 -0
- package/skills/build-loop/fallbacks.md +549 -0
- package/skills/build-loop/phases/fact-check.md +42 -0
- package/skills/build-loop/phases/ui-validation.md +267 -0
- package/skills/build-loop/references/apple-native-planning.md +439 -0
- package/skills/build-loop/references/capability-routing.md +181 -0
- package/skills/build-loop/references/codex-subagents.md +98 -0
- package/skills/build-loop/references/coordination.md +161 -0
- package/skills/build-loop/references/correction-aware-capture.md +177 -0
- package/skills/build-loop/references/independent-auditor.md +72 -0
- package/skills/build-loop/references/intent-capability-pack.md +170 -0
- package/skills/build-loop/references/intent-exploration-prompts.md +96 -0
- package/skills/build-loop/references/leadership.md +72 -0
- package/skills/build-loop/references/memory.md +284 -0
- package/skills/build-loop/references/modular-systems-pack.md +96 -0
- package/skills/build-loop/references/output-style.md +129 -0
- package/skills/build-loop/references/pay-it-forward-arch.md +98 -0
- package/skills/build-loop/references/phase-1-assess.md +218 -0
- package/skills/build-loop/references/phase-2-plan.md +77 -0
- package/skills/build-loop/references/phase-3-execute.md +47 -0
- package/skills/build-loop/references/phase-4-review.md +310 -0
- package/skills/build-loop/references/phase-5-iterate.md +71 -0
- package/skills/build-loop/references/phase-6-learn.md +56 -0
- package/skills/build-loop/references/recent-design-structures.md +274 -0
- package/skills/build-loop/references/refactor-history/ASSESSMENT.md +85 -0
- package/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +149 -0
- package/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +32 -0
- package/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +48 -0
- package/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +60 -0
- package/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +51 -0
- package/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +71 -0
- package/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +52 -0
- package/skills/build-loop/references/refactor-history/trace-comparison.md +202 -0
- package/skills/build-loop/references/self-recursive-dev.md +77 -0
- package/skills/build-loop/references/self-review.md +232 -0
- package/skills/build-loop/references/ui-io-contract.md +116 -0
- package/skills/build-loop/scanners/audit-design-rules.mjs +476 -0
- package/skills/build-loop/scanners/require-visual-evidence.mjs +239 -0
- package/skills/build-loop/templates/backlog-item.md +35 -0
- package/skills/build-loop/templates/codex-worker-prompt.md +89 -0
- package/skills/build-loop/templates/ui-subagent-prompt.md +179 -0
- package/skills/build-loop/templates/ux-fix-plan.md +40 -0
- package/skills/building-with-deepagents/SKILL.md +195 -0
- package/skills/building-with-deepagents/references/anti-patterns.md +141 -0
- package/skills/building-with-deepagents/references/api-quick-reference.md +184 -0
- package/skills/capabilities/SKILL.md +91 -0
- package/skills/debug-loop/SKILL.md +278 -0
- package/skills/debug-loop/references/convergence-rules.md +145 -0
- package/skills/debug-loop/references/swiftui-macos-clunky-ui-debugger.html +823 -0
- package/skills/debugging/assess/SKILL.md +111 -0
- package/skills/debugging/debug-loop/SKILL.md +231 -0
- package/skills/debugging/memory/SKILL.md +147 -0
- package/skills/debugging/store/SKILL.md +153 -0
- package/skills/debugging-memory/SKILL.md +440 -0
- package/skills/debugging-memory/examples/incident-example.json +67 -0
- package/skills/debugging-memory/references/incident-documentation.md +280 -0
- package/skills/debugging-memory/references/ios-notification-alarm-playbook.md +300 -0
- package/skills/debugging-memory/references/pattern-extraction.md +163 -0
- package/skills/debugging-memory/references/subagent-integration.md +312 -0
- package/skills/defenseclaw-bridge/SKILL.md +156 -0
- package/skills/defenseclaw-bridge/references/dc-config-mapping.md +162 -0
- package/skills/defenseclaw-bridge/references/output-format.md +108 -0
- package/skills/handoff/SKILL.md +94 -0
- package/skills/ibr-bridge/SKILL.md +68 -0
- package/skills/knowledge/SKILL.md +127 -0
- package/skills/knowledge/references/recall-integration.md +83 -0
- package/skills/knowledge/templates/madr-minimal.md +56 -0
- package/skills/knowledge-review/SKILL.md +112 -0
- package/skills/logging-tracer/SKILL.md +202 -0
- package/skills/logging-tracer/references/log-analysis.md +128 -0
- package/skills/logging-tracer/references/stack-templates.md +274 -0
- package/skills/logging-tracer-bridge/SKILL.md +70 -0
- package/skills/mcp-builder/SKILL.md +278 -0
- package/skills/mcp-builder/references/mcp-security.md +106 -0
- package/skills/model-tiering/SKILL.md +216 -0
- package/skills/native-ax-driver/SKILL.md +220 -0
- package/skills/native-ax-driver/scripts/layout_fill.py +222 -0
- package/skills/native-ax-driver/scripts/native_driver.py +495 -0
- package/skills/native-ax-driver/swift/bl-ax-driver/Package.swift +20 -0
- package/skills/native-ax-driver/swift/bl-ax-driver/Sources/main.swift +542 -0
- package/skills/optimize/SKILL.md +202 -0
- package/skills/optimize/profiles.md +61 -0
- package/skills/plan-verify/SKILL.md +115 -0
- package/skills/plan-verify/test-fixtures/example-app-v20-findings.json +27 -0
- package/skills/plan-verify/test-fixtures/example-app-v20.md +42 -0
- package/skills/plan-verify/test-fixtures/example-app-v22-findings.json +15 -0
- package/skills/plan-verify/test-fixtures/example-app-v22.md +1608 -0
- package/skills/plan-verify/test-fixtures/unrelated-good-plan-findings.json +15 -0
- package/skills/plan-verify/test-fixtures/unrelated-good-plan.md +55 -0
- package/skills/plugin-builder/SKILL.md +329 -0
- package/skills/plugin-builder/references/authoritative-sources.md +104 -0
- package/skills/plugin-builder/references/build-loop-phase-guidance.md +94 -0
- package/skills/plugin-builder/references/components-guide.md +221 -0
- package/skills/plugin-builder/references/distribution.md +317 -0
- package/skills/plugin-builder/references/dual-host-claude-codex.md +220 -0
- package/skills/plugin-builder/references/hooks-reference.md +210 -0
- package/skills/plugin-builder/references/manifest-schema.md +111 -0
- package/skills/plugin-builder/references/plugin-hygiene-lessons.md +307 -0
- package/skills/plugin-tests/SKILL.md +94 -0
- package/skills/prd-bridge/SKILL.md +135 -0
- package/skills/research/SKILL.md +80 -0
- package/skills/security-methodology/SKILL.md +105 -0
- package/skills/security-methodology/references/cross-source-matrix.md +77 -0
- package/skills/security-methodology/references/mitre-atlas-starter.md +83 -0
- package/skills/security-methodology/references/nist-600-1-mapping.md +119 -0
- package/skills/security-methodology/references/owasp-agentic-top-10.md +157 -0
- package/skills/security-methodology/references/owasp-llm-top-10.md +144 -0
- package/skills/security-methodology/references/owasp-web-top-10.md +65 -0
- package/skills/self-improve/SKILL.md +298 -0
- package/skills/spec-writing/SKILL.md +548 -0
- package/skills/spec-writing/scripts/check_checklist.py +478 -0
- package/skills/sync-skills/SKILL.md +132 -0
- package/skills/telemetry/SKILL.md +66 -0
- package/skills/ui-design/SKILL.md +75 -0
- package/skills/ui-design/references/design-patterns-multi.md +165 -0
- package/skills/ui-design/references/design-preferences-from-owned-apps.md +150 -0
- package/skills/ui-design/references/evidence-capture-policy.md +55 -0
- package/skills/ui-design/references/ui-guidance-sources.md +330 -0
- package/skills/ui-design/references/universal-design-principles.alt.md +182 -0
- package/skills/ui-design/references/universal-design-principles.md +419 -0
- package/templates/memory/MEMORY.md.template +55 -0
- package/templates/memory/constitution.md.template +64 -0
- package/templates/memory/manifest.json +47 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// require-visual-evidence.mjs — BL-1 gate
|
|
6
|
+
//
|
|
7
|
+
// Rejects UI-touching chunks whose only verification evidence is symbol/string
|
|
8
|
+
// presence (nm / strings / grep over compiled binaries / `git grep` over source).
|
|
9
|
+
//
|
|
10
|
+
// Trigger surfaces (called by build-orchestrator):
|
|
11
|
+
// - Phase 3 chunk-close (commit step) when `uiTouched: true`
|
|
12
|
+
// - Phase 4 sub-step B (Validate) when `uiTarget != null` and any changed
|
|
13
|
+
// file matches the UI-file globs below
|
|
14
|
+
//
|
|
15
|
+
// Input (--envelope-file <path>): a JSON file with the implementer/chunk
|
|
16
|
+
// return envelope, at minimum:
|
|
17
|
+
// {
|
|
18
|
+
// "uiTarget": "macos" | "mobile" | "web" | null,
|
|
19
|
+
// "files_changed": ["...", "..."],
|
|
20
|
+
// "verification": "<freeform string describing how the implementer verified>",
|
|
21
|
+
// "evidence_paths": ["screenshots/foo.png", ...] // optional
|
|
22
|
+
// }
|
|
23
|
+
// Extra fields are ignored. Missing fields are treated conservatively
|
|
24
|
+
// (no claim => no evidence).
|
|
25
|
+
//
|
|
26
|
+
// Exit codes:
|
|
27
|
+
// 0 pass — non-UI diff OR genuine visual/AX evidence present
|
|
28
|
+
// 1 warn — UI diff + ambiguous evidence; agent should clarify
|
|
29
|
+
// 2 reject — UI diff + ONLY symbol/string evidence; BLOCK chunk-close
|
|
30
|
+
// 3 malformed — envelope unreadable / invalid JSON
|
|
31
|
+
//
|
|
32
|
+
// Always writes a JSON object to stdout:
|
|
33
|
+
// { verdict, reason, ui_changed, ui_files, symbol_only, accepted_evidence }
|
|
34
|
+
//
|
|
35
|
+
// Stdlib-only. No dependencies. Mirrors the shape of audit-design-rules.mjs.
|
|
36
|
+
|
|
37
|
+
import fs from 'node:fs';
|
|
38
|
+
import path from 'node:path';
|
|
39
|
+
|
|
40
|
+
// --- UI file detection ------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
const UI_FILE_PATTERNS = [
|
|
43
|
+
/(^|\/)Views\//, // Apple-platform convention
|
|
44
|
+
/\.swift$/, // any Swift source (heuristic — paired w/ uiTarget)
|
|
45
|
+
/\.tsx$/,
|
|
46
|
+
/\.jsx$/,
|
|
47
|
+
/\.vue$/,
|
|
48
|
+
/\.svelte$/,
|
|
49
|
+
/(^|\/)components?\/.+\.(ts|js)$/,
|
|
50
|
+
/(^|\/)pages?\/.+\.(ts|js)$/,
|
|
51
|
+
/(^|\/)app\/.+\.(ts|js)$/,
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
function isUiFile(p) {
|
|
55
|
+
return UI_FILE_PATTERNS.some((rx) => rx.test(p));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// --- Evidence classification ------------------------------------------------
|
|
59
|
+
|
|
60
|
+
// Accepted visual/AX evidence — any one of these in the verification text
|
|
61
|
+
// or as an evidence path is enough to clear the gate.
|
|
62
|
+
const ACCEPTED_EVIDENCE_TOKENS = [
|
|
63
|
+
// Screenshot / image artifacts
|
|
64
|
+
/screenshot/i,
|
|
65
|
+
/\.png\b/i,
|
|
66
|
+
/\.jpe?g\b/i,
|
|
67
|
+
// AX tree dumps
|
|
68
|
+
/\bax[-_ ]?tree\b/i,
|
|
69
|
+
/accessibility[-_ ]?tree/i,
|
|
70
|
+
// macOS / iOS native verification
|
|
71
|
+
/native[-_ ]?ax[-_ ]?driver/i,
|
|
72
|
+
/\bxcrun simctl io booted screenshot\b/i,
|
|
73
|
+
/\bidb ui\b/i,
|
|
74
|
+
// IBR + scan
|
|
75
|
+
/\bscan_macos\b/i,
|
|
76
|
+
/\bibr\b[^a-z]*scan/i,
|
|
77
|
+
/ssim/i,
|
|
78
|
+
// Web rendering
|
|
79
|
+
/\bplaywright\b/i,
|
|
80
|
+
/\bpuppeteer\b/i,
|
|
81
|
+
/\bui[-_ ]?validator\b/i,
|
|
82
|
+
/dev[-_ ]?server.*(?:screenshot|render)/i,
|
|
83
|
+
// PID-anchored verification (the running app was actually looked at)
|
|
84
|
+
/\bpid[:= ]\s*\d+/i,
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
// Symbol-only evidence — `nm`, `strings`, `grep` over compiled output, or
|
|
88
|
+
// a "the identifier exists therefore the UI is correct" claim. These DO NOT
|
|
89
|
+
// satisfy the gate on their own.
|
|
90
|
+
const SYMBOL_ONLY_TOKENS = [
|
|
91
|
+
/\bnm\s+[^\n]*\.(?:app|dylib|framework|so|exe|dll|o|a|bundle)/i,
|
|
92
|
+
/\bstrings\s+/i,
|
|
93
|
+
/\botool\s+-[lL]\b/i,
|
|
94
|
+
/\bgit grep\b/i,
|
|
95
|
+
/\bgrep\b.*(?:Sources|Views|src)\//i,
|
|
96
|
+
/\bsymbol(?:s)?\s+(?:present|exist|found)/i,
|
|
97
|
+
/\bidentifier(?:s)?\s+(?:present|exist|found)/i,
|
|
98
|
+
/\bcompiles?\s+(?:cleanly|successfully)/i, // build-only claim
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
function classifyEvidence(verificationText, evidencePaths) {
|
|
102
|
+
const acceptedHits = [];
|
|
103
|
+
const symbolHits = [];
|
|
104
|
+
|
|
105
|
+
const haystacks = [verificationText, ...(evidencePaths || [])];
|
|
106
|
+
for (const text of haystacks) {
|
|
107
|
+
if (typeof text !== 'string') continue;
|
|
108
|
+
for (const rx of ACCEPTED_EVIDENCE_TOKENS) {
|
|
109
|
+
if (rx.test(text)) acceptedHits.push(rx.source);
|
|
110
|
+
}
|
|
111
|
+
for (const rx of SYMBOL_ONLY_TOKENS) {
|
|
112
|
+
if (rx.test(text)) symbolHits.push(rx.source);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
accepted_evidence: [...new Set(acceptedHits)],
|
|
117
|
+
symbol_signals: [...new Set(symbolHits)],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// --- Main -------------------------------------------------------------------
|
|
122
|
+
|
|
123
|
+
function parseArgs(argv) {
|
|
124
|
+
const args = { envelopeFile: null, root: '.' };
|
|
125
|
+
for (let i = 2; i < argv.length; i++) {
|
|
126
|
+
const a = argv[i];
|
|
127
|
+
if (a === '--envelope-file') args.envelopeFile = argv[++i];
|
|
128
|
+
else if (a === '--root') args.root = argv[++i];
|
|
129
|
+
else if (a === '--help' || a === '-h') {
|
|
130
|
+
// Embedded usage so stdlib-only -- no separate help file
|
|
131
|
+
process.stdout.write(
|
|
132
|
+
'Usage: require-visual-evidence.mjs --envelope-file <path> [--root <project-root>]\n'
|
|
133
|
+
);
|
|
134
|
+
process.exit(0);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return args;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function emit(verdict, reason, extras) {
|
|
141
|
+
const out = { verdict, reason, ...extras };
|
|
142
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
143
|
+
if (verdict === 'pass') process.exit(0);
|
|
144
|
+
if (verdict === 'warn') process.exit(1);
|
|
145
|
+
if (verdict === 'reject') process.exit(2);
|
|
146
|
+
process.exit(3);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function main() {
|
|
150
|
+
const args = parseArgs(process.argv);
|
|
151
|
+
if (!args.envelopeFile) {
|
|
152
|
+
emit('malformed', '--envelope-file is required', {});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
let raw;
|
|
156
|
+
try {
|
|
157
|
+
raw = fs.readFileSync(args.envelopeFile, 'utf8');
|
|
158
|
+
} catch (err) {
|
|
159
|
+
emit('malformed', `cannot read envelope: ${err.message}`, {});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let env;
|
|
163
|
+
try {
|
|
164
|
+
env = JSON.parse(raw);
|
|
165
|
+
} catch (err) {
|
|
166
|
+
emit('malformed', `invalid JSON: ${err.message}`, {});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const uiTarget = env.uiTarget ?? null;
|
|
170
|
+
const filesChanged = Array.isArray(env.files_changed) ? env.files_changed : [];
|
|
171
|
+
const verification = typeof env.verification === 'string' ? env.verification : '';
|
|
172
|
+
const evidencePaths = Array.isArray(env.evidence_paths) ? env.evidence_paths : [];
|
|
173
|
+
|
|
174
|
+
// Skip when no UI target is configured for this build.
|
|
175
|
+
if (uiTarget === null || uiTarget === undefined) {
|
|
176
|
+
emit('pass', 'uiTarget is null; gate does not apply', {
|
|
177
|
+
ui_changed: false,
|
|
178
|
+
ui_files: [],
|
|
179
|
+
symbol_only: false,
|
|
180
|
+
accepted_evidence: [],
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Skip when this chunk didn't touch any UI file.
|
|
185
|
+
const uiFiles = filesChanged.filter(isUiFile);
|
|
186
|
+
if (uiFiles.length === 0) {
|
|
187
|
+
emit('pass', 'no UI files changed in this chunk', {
|
|
188
|
+
ui_changed: false,
|
|
189
|
+
ui_files: [],
|
|
190
|
+
symbol_only: false,
|
|
191
|
+
accepted_evidence: [],
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// UI was touched — evidence is required.
|
|
196
|
+
const { accepted_evidence, symbol_signals } = classifyEvidence(verification, evidencePaths);
|
|
197
|
+
|
|
198
|
+
if (accepted_evidence.length > 0) {
|
|
199
|
+
emit('pass', 'visual/AX evidence present', {
|
|
200
|
+
ui_changed: true,
|
|
201
|
+
ui_files: uiFiles,
|
|
202
|
+
symbol_only: false,
|
|
203
|
+
accepted_evidence,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (symbol_signals.length > 0) {
|
|
208
|
+
emit(
|
|
209
|
+
'reject',
|
|
210
|
+
'symbol/string-only evidence is NOT a substitute for visual/AX verification. ' +
|
|
211
|
+
'Required: render the running app (pid-anchored) and capture a screenshot, AX-tree dump, ' +
|
|
212
|
+
'or scan result. See skills/build-loop/phases/ui-validation.md §"Visual validation".',
|
|
213
|
+
{
|
|
214
|
+
ui_changed: true,
|
|
215
|
+
ui_files: uiFiles,
|
|
216
|
+
symbol_only: true,
|
|
217
|
+
accepted_evidence: [],
|
|
218
|
+
symbol_signals,
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// No accepted evidence AND no symbol-only signal — verification text is
|
|
224
|
+
// ambiguous (empty, unrelated, or in an unknown shape). Surface a warning
|
|
225
|
+
// and let the orchestrator decide whether to re-prompt the implementer.
|
|
226
|
+
emit(
|
|
227
|
+
'warn',
|
|
228
|
+
'no recognized visual/AX evidence in the envelope and no symbol-only signal either; ' +
|
|
229
|
+
're-prompt the implementer to attach a screenshot, AX-tree dump, or scan result.',
|
|
230
|
+
{
|
|
231
|
+
ui_changed: true,
|
|
232
|
+
ui_files: uiFiles,
|
|
233
|
+
symbol_only: false,
|
|
234
|
+
accepted_evidence: [],
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
main();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: {title}
|
|
3
|
+
created: {created}
|
|
4
|
+
source: {source}
|
|
5
|
+
classify: {classify}
|
|
6
|
+
effort: {effort}
|
|
7
|
+
status: {status}
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
11
|
+
|
|
12
|
+
# {title}
|
|
13
|
+
|
|
14
|
+
## Problem
|
|
15
|
+
|
|
16
|
+
{problem}
|
|
17
|
+
|
|
18
|
+
## Proposed approach
|
|
19
|
+
|
|
20
|
+
{proposed_approach}
|
|
21
|
+
|
|
22
|
+
## Why deferred
|
|
23
|
+
|
|
24
|
+
{why_deferred}
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
**Field reference:**
|
|
29
|
+
|
|
30
|
+
- `classify`: SAFE (no side-effects) | RISKY (touches infra/schema/auth) | DECISION (needs user confirmation) | PRODUCTION (live-traffic impact)
|
|
31
|
+
- `effort`: XS (<1h) | S (1–4h) | M (half-day) | L (1–2 days) | XL (>2 days). No dollar costs — t-shirt sizing only.
|
|
32
|
+
- `status`: open | in-progress | done
|
|
33
|
+
- `source`: free-form — who/what surfaced this item (e.g. "user steering 2026-05-30", "Phase 6 Learn run-abc", "self-review")
|
|
34
|
+
|
|
35
|
+
Backlog items are **longer-lived** than `issues/` (current-run bugs). They survive across runs and are only drained when status becomes `done` or the item is explicitly removed.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# Codex Worker Prompt Template
|
|
4
|
+
|
|
5
|
+
You are a Codex worker inside a Build Loop run. You are not alone in the codebase. Do not revert edits made by others; adapt around them and report conflicts.
|
|
6
|
+
|
|
7
|
+
## Task
|
|
8
|
+
|
|
9
|
+
<one concrete outcome>
|
|
10
|
+
|
|
11
|
+
## Ownership
|
|
12
|
+
|
|
13
|
+
Owns:
|
|
14
|
+
- <exact files/directories this worker may edit>
|
|
15
|
+
|
|
16
|
+
Does not own:
|
|
17
|
+
- <files/directories/responsibilities this worker must not edit>
|
|
18
|
+
|
|
19
|
+
## Context
|
|
20
|
+
|
|
21
|
+
- Goal: <goal from .build-loop/goal.md>
|
|
22
|
+
- Intent: <north star/update intent relevant to this task>
|
|
23
|
+
- Current state: <short facts from assessment>
|
|
24
|
+
- Dependencies: <upstream tasks or known constraints>
|
|
25
|
+
|
|
26
|
+
## Interface Contract
|
|
27
|
+
|
|
28
|
+
- <function/route/schema/component/CLI/doc contract to preserve or expose>
|
|
29
|
+
|
|
30
|
+
## Implementation Rules
|
|
31
|
+
|
|
32
|
+
- Keep the change scoped to owned files.
|
|
33
|
+
- Prefer the repo's existing patterns over new abstractions.
|
|
34
|
+
- Do not add dependencies unless the lead explicitly assigned that.
|
|
35
|
+
- Surface pre-existing issues separately from task changes.
|
|
36
|
+
- If ownership is unclear, stop and report the conflict instead of broadening scope.
|
|
37
|
+
|
|
38
|
+
## Validation
|
|
39
|
+
|
|
40
|
+
Run if feasible:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
<validation command>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If validation is not feasible, explain why and what the lead should run.
|
|
47
|
+
|
|
48
|
+
## Return Format
|
|
49
|
+
|
|
50
|
+
Changed files:
|
|
51
|
+
- <path>: <what changed>
|
|
52
|
+
|
|
53
|
+
Validation:
|
|
54
|
+
- <command or "not run">: <result or reason>
|
|
55
|
+
|
|
56
|
+
Integration notes:
|
|
57
|
+
- <contract, migration, or ordering notes>
|
|
58
|
+
|
|
59
|
+
Unresolved risks:
|
|
60
|
+
- <risk or "none known">
|
|
61
|
+
|
|
62
|
+
## decision_ledger (REQUIRED when plan has synthesis_dimensions)
|
|
63
|
+
|
|
64
|
+
When the originating plan includes a `synthesis_dimensions:` block, your return envelope MUST include a `decision_ledger` array with one entry per dimension. Each entry documents *why* the chosen value was selected — not just *what* was applied. Empty array `[]` is only valid when the plan has no `synthesis_dimensions` block.
|
|
65
|
+
|
|
66
|
+
Example (two entries for placement and cta_tier dimensions):
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
"decision_ledger": [
|
|
70
|
+
{
|
|
71
|
+
"dimension": "placement_MyComponent",
|
|
72
|
+
"owner": "plan",
|
|
73
|
+
"locked_value": "after `<ParentRow>` in path/to/Component.tsx",
|
|
74
|
+
"alternatives_rejected": ["before `<ParentRow>` — plan specified after"],
|
|
75
|
+
"evidence_file": "path/to/Component.tsx",
|
|
76
|
+
"on_new_decision": "flag"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"dimension": "cta_tier_save_button",
|
|
80
|
+
"owner": "plan",
|
|
81
|
+
"locked_value": "primary",
|
|
82
|
+
"alternatives_rejected": ["secondary — insufficient weight for primary conversion action"],
|
|
83
|
+
"evidence_file": "path/to/Component.tsx",
|
|
84
|
+
"on_new_decision": "flag"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Full schema: `references/implementer-envelope-schema.md` §"decision_ledger in detail".
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# UI Subagent Prompt — Design Rule Preamble
|
|
4
|
+
|
|
5
|
+
> Prepended verbatim to every build-loop subagent prompt that touches UI files. Do NOT replace with a link — agents miss links.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Required reading BEFORE you touch any UI file
|
|
10
|
+
|
|
11
|
+
Load these skills and follow them. Not optional.
|
|
12
|
+
|
|
13
|
+
- **All UI work**: `calm-precision`
|
|
14
|
+
- **All non-trivial UI work**: read `.build-loop/app-contract/ui.md` when present. The `## Design Direction` and `## Design Hierarchy Registry` sections are the binding build-loop-owned style source. If it names a `selected_structure` from `recent-design-structures.md`, implement that structure through the app contract; do not re-pick a different one.
|
|
15
|
+
- **SwiftUI / Apple platforms**: use `apple-dev` only when the task needs Apple implementation or deployment details.
|
|
16
|
+
- **React / Vue / web**: use `frontend-design` only when the user or orchestrator explicitly requests that external guidance.
|
|
17
|
+
|
|
18
|
+
If a skill is unavailable, proceed but note it in your output.
|
|
19
|
+
|
|
20
|
+
Calm Precision is the structural baseline and a required design consideration gate: hierarchy, grouping, action weight, disclosure, motion, accessibility, copy clarity, functional integrity, and their perceptual-science foundations. The app contract decides the selected structure and surface treatment on top of that baseline.
|
|
21
|
+
|
|
22
|
+
Before editing UI, identify which Calm Precision principles are relevant to this change and how they constrain the implementation. Do not treat Calm Precision as background reference or taste language. If `.build-loop/app-contract/ui.md` contains `## Calm Precision Core Considerations`, apply that section as binding guidance. If the section is missing for non-trivial UI work, still run the consideration pass locally and report it in your return envelope as `CALM PRECISION CHECK: <principles> -> <implementation effect>`.
|
|
23
|
+
|
|
24
|
+
## UI input/output contract
|
|
25
|
+
|
|
26
|
+
Before editing, read the task's `## UI Input/Output Contract` section. If it is missing and the task is not copy-only, return `status: blocked` and name the missing contract.
|
|
27
|
+
|
|
28
|
+
For every changed screen/component, apply the contract exactly:
|
|
29
|
+
|
|
30
|
+
1. Every user input has a named structural type, content format, persistence intent, validation rule, and input control.
|
|
31
|
+
2. Every system output has a named source, content format, renderer, loading/error/empty state, and overflow/copy/fallback behavior.
|
|
32
|
+
3. Domain actions are named as verbs (submit, approve, publish, reorder, export), not hidden inside generic update language.
|
|
33
|
+
4. Voice, file, image, chart, map, AI-generated, and streaming surfaces include a modality-specific fallback.
|
|
34
|
+
5. Rich text, Markdown, HTML, JSON, and AI output include sanitization/rendering rules.
|
|
35
|
+
6. Create/update/delete/domain actions include auth/authz behavior for denied users: hidden, disabled, or 403/empty view.
|
|
36
|
+
|
|
37
|
+
If you need to deviate from the contract, report `CONTRACT DEVIATION: <surface> — <reason> — <replacement>`.
|
|
38
|
+
|
|
39
|
+
## Mockup-vs-rule conflict policy
|
|
40
|
+
|
|
41
|
+
Mockups are **intent**. Design rules are **law**. When they conflict, the rule wins. No exceptions, no judgment calls — replicate the rule, not the pixel.
|
|
42
|
+
|
|
43
|
+
Required behavior on conflict:
|
|
44
|
+
1. Implement per the rule.
|
|
45
|
+
2. Add a line to your output: `RULE BEATS MOCKUP: <rule-id> overrides <mockup-element>. Reason: <one sentence>.`
|
|
46
|
+
|
|
47
|
+
Skipping this line means the orchestrator can't audit your decisions. Don't skip.
|
|
48
|
+
|
|
49
|
+
## Anti-pattern checklist (zero tolerance)
|
|
50
|
+
|
|
51
|
+
Every UI file you write or modify must pass this checklist before you return.
|
|
52
|
+
|
|
53
|
+
1. **No status pills.** Status indicators use text color only. Never `.background(opacity).clipShape(Capsule())` (SwiftUI) or `bg-X-500 rounded-full` (Tailwind) near a chip / badge / status / trend / score identifier. Color and weight create hierarchy, not boxes.
|
|
54
|
+
|
|
55
|
+
2. **Reduce Motion gates every animation.** No `.repeatForever`, `withAnimation`, `.easeInOut(duration:)`, `animate-pulse`, `animate-spin` without the platform-correct guard.
|
|
56
|
+
- SwiftUI: `@Environment(\.accessibilityReduceMotion) private var reduceMotion`, then `if !reduceMotion { withAnimation(...) }`
|
|
57
|
+
- Web: pair every animation utility with its `motion-reduce:` variant or media-query equivalent
|
|
58
|
+
|
|
59
|
+
3. **Theme tokens, not literals.**
|
|
60
|
+
- SwiftUI: no raw `UIColor(red:green:blue:)` outside `Theme/`. No literal `.cornerRadius(N)` — use `Theme.cornerSmall/Medium/Large/XL`.
|
|
61
|
+
- Web: no `#hex` outside theme/tokens files. No `text-[Npx]` arbitrary sizes.
|
|
62
|
+
|
|
63
|
+
4. **Dynamic Type / responsive type.** Body copy uses theme tokens (`Theme.fontBody`, `Theme.fontCaption`), not `.font(.system(size: N))`. Numeric chips and tabular layouts may use fixed sizes.
|
|
64
|
+
|
|
65
|
+
5. **Every icon has a label.** Icon-only `Image(systemName: "...")` (SwiftUI) or `<Icon />` (web) gets an explicit `accessibilityLabel` / `aria-label`, OR is wrapped in a `Button` whose label covers it.
|
|
66
|
+
|
|
67
|
+
6. **Touch targets.** Mobile: 44pt minimum. Primary thumb-zone actions (record, submit during capture): 88pt minimum.
|
|
68
|
+
|
|
69
|
+
7. **VoiceOver matches visible text.** Don't strip signs (`abs()`) for one but not the other. Keep numeric conventions consistent across visible label and accessibility label.
|
|
70
|
+
|
|
71
|
+
8. **No fake buttons.** Every interactive element has a working backend handler. No placeholder onTap, no "Coming soon" without the affordance being hidden or marked.
|
|
72
|
+
|
|
73
|
+
9. **Floating tab bar / system overlays don't clip your content.** iOS 26's floating tab bar overlays the bottom ~92pt of the window. Android navigation gesture inset is similar. Web bottom-fixed nav same idea. **Every scrollable surface needs an explicit bottom inset** so the last row clears the bar at scroll-end:
|
|
74
|
+
- SwiftUI ScrollView: append `Color.clear.frame(height: 100)` as the last child of the inner VStack, OR use `.contentMargins(.bottom, 100, for: .scrollContent)`
|
|
75
|
+
- SwiftUI List: `.safeAreaInset(edge: .bottom) { Color.clear.frame(height: 100) }`
|
|
76
|
+
- Web: equivalent `pb-24` / `padding-block-end: 6rem` on the scrollable container
|
|
77
|
+
`safeAreaPadding` alone is not sufficient — it pushes the ScrollView frame, not the scrollable content area. This shipped broken in a real build (build 53) because the rule wasn't on the checklist.
|
|
78
|
+
|
|
79
|
+
10. **Numeric/text fields constrain width.** Long dim names ("Engagement", "Conciseness") wrap or squeeze adjacent columns when no width policy is set. For row layouts where label + score columns coexist:
|
|
80
|
+
- Labels: `.lineLimit(1).minimumScaleFactor(0.75)` — shrink, don't wrap
|
|
81
|
+
- Right-side numeric column: `.fixedSize(horizontal: true, vertical: false)` — never sacrifice the timestamp/score for label width
|
|
82
|
+
|
|
83
|
+
11. **Custom-drawn arcs / charts: render the half you mean.** SwiftUI's `Path.addArc` `clockwise:` flag is counter-intuitive in the user-space (y-flipped) coordinate system. `clockwise: false` from 180° to 360° draws the TOP half. `clockwise: true` draws the BOTTOM half. Use `Circle().trim(from:to:).rotationEffect(_:)` for predictable results. Track strokes against dark backgrounds need at least `Theme.textMuted.opacity(0.25)` contrast — not `surfacePrimary` (which is too close to background luminance). This shipped a literal upside-down semicircle (build 53/55) before being caught visually.
|
|
84
|
+
|
|
85
|
+
## Required SwiftUI environment hooks
|
|
86
|
+
|
|
87
|
+
When your file contains any animation:
|
|
88
|
+
|
|
89
|
+
```swift
|
|
90
|
+
@Environment(\.accessibilityReduceMotion) private var reduceMotion
|
|
91
|
+
|
|
92
|
+
// Then everywhere you animate:
|
|
93
|
+
if !reduceMotion {
|
|
94
|
+
withAnimation(...) { ... }
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Verification before you return
|
|
99
|
+
|
|
100
|
+
Mandatory pre-return steps:
|
|
101
|
+
|
|
102
|
+
1. **Build.** Platform default — SwiftUI: `xcodegen generate && xcodebuild build`. Web: `pnpm build` or project equivalent.
|
|
103
|
+
|
|
104
|
+
2. **UI input/output contract check.** Verify the changed files still satisfy the task's contract. Confirm all inputs, outputs, states, modality fallbacks, validation/security rules, and traceability entries are implemented or explicitly marked not applicable.
|
|
105
|
+
|
|
106
|
+
3. **Design-rule scan.** If `${CLAUDE_PLUGIN_ROOT}/skills/build-loop/scanners/audit-design-rules.mjs` exists, run:
|
|
107
|
+
```
|
|
108
|
+
node "${CLAUDE_PLUGIN_ROOT}/skills/build-loop/scanners/audit-design-rules.mjs" --root=<project> --platform=<swiftui|react|web>
|
|
109
|
+
```
|
|
110
|
+
**Zero must-fix findings.** Must-fix blocks return.
|
|
111
|
+
|
|
112
|
+
**No "out of scope" framing for warnings.** Drift from a rule in any user-facing file is drift, regardless of whether this commit "owns" that file. If your task changes one screen and the scanner shows warnings on adjacent screens, fix the warnings too — the user lives in the app, they don't see commit boundaries. The only acceptable warning is one you explicitly justify in your output (e.g. "fixed font size on numeric chip — Dynamic Type would break tabular alignment"). "Pre-existing" is not a reason; it's a backlog.
|
|
113
|
+
|
|
114
|
+
4. **Visual validation (REQUIRED for UI work; enforced gate, not prose).** The scanner catches static anti-patterns. It cannot catch rendering bugs — an upside-down arc, an invisible track, a clipped row, a chip that wraps. **If you touched a Views/ file, you must render the actual screen and look at it.** The orchestrator runs `scanners/require-visual-evidence.mjs` (BL-1 gate) at chunk-close and at Phase 4-B Validate: symbol/string-only evidence (`nm`, `strings`, `git grep`, "identifier present", "compiles cleanly") is automatically rejected with exit 2 and the chunk is routed back to Iterate. Required artifacts are a screenshot path anchored to the running app's pid, an AX-tree dump, or a scan/SSIM/ui-validator result.
|
|
115
|
+
|
|
116
|
+
- **macOS (`uiTarget: "macos"`)**: macOS has no simulator. Prefer the built-in `native-ax-driver` against the running `.app` (pid-anchored AX-tree dump + element actions) OR — if the IBR plugin is installed in this project — IBR `scan_macos`. Capture a screenshot via `screencapture -l <window-id>` or the AX driver's screenshot helper; do NOT use `xcrun simctl` (it does not target macOS). If neither verifier is reachable, return `status: blocked` naming the unreachable tool — do NOT fall back to `nm`/`strings`.
|
|
117
|
+
- **iOS / watchOS (`uiTarget: "mobile"`)**: install on simulator, launch, capture via `xcrun simctl io booted screenshot` or `idb ui` for interaction. If your change is in a returning-user code path, seed test data first (see "DebugSeeder pattern" below).
|
|
118
|
+
- **Web (`uiTarget: "web"`)**: open the changed route with the host's available browser/screenshot tooling against the dev server URL — `ui-validator` is the primary surface; Playwright/Puppeteer/showcase capture are acceptable alternatives.
|
|
119
|
+
|
|
120
|
+
Compare against the mockup if one exists. Look for: arc/chart geometry rendering correctly, score values positioned where the mockup shows them, no rows clipped behind floating bars / tab bars / safe areas, no text wrapping unexpectedly, no overlapping elements. Real shipped bugs (build 53–55: gauge upside-down with stray ticks; multiple tabs clipping last row behind iOS 26 floating bar) were only caught by visual inspection.
|
|
121
|
+
|
|
122
|
+
If browser/simulator tooling is unavailable, document this in your output as a known gap rather than skipping the step silently.
|
|
123
|
+
|
|
124
|
+
5. If the scanner doesn't exist (older build-loop install), you still must self-audit against the checklist above before returning.
|
|
125
|
+
|
|
126
|
+
## DebugSeeder pattern (testability for returning-user views)
|
|
127
|
+
|
|
128
|
+
Many UI states are only reachable after the user has done something — completed N drills, set a name, joined a streak. Manually doing 7 drills before you can verify a Home returning-user view is not a sustainable verification path. **Add a debug-only seeder so any subagent (or a human reviewer) can verify these states in seconds.**
|
|
129
|
+
|
|
130
|
+
Pattern (SwiftUI/SwiftData example):
|
|
131
|
+
|
|
132
|
+
```swift
|
|
133
|
+
// ExampleApp/Services/DebugSeeder.swift
|
|
134
|
+
#if DEBUG
|
|
135
|
+
import Foundation
|
|
136
|
+
import SwiftData
|
|
137
|
+
|
|
138
|
+
enum DebugSeeder {
|
|
139
|
+
static func seedIfEmpty(context: ModelContext) {
|
|
140
|
+
let existing = (try? context.fetch(FetchDescriptor<Session>())) ?? []
|
|
141
|
+
guard existing.isEmpty else { return }
|
|
142
|
+
// ... insert representative test data spanning a meaningful range
|
|
143
|
+
try? context.save()
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
#endif
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```swift
|
|
150
|
+
// ExampleApp.swift init()
|
|
151
|
+
#if DEBUG
|
|
152
|
+
if CommandLine.arguments.contains("-SeedDebugSessions") {
|
|
153
|
+
DebugSeeder.seedIfEmpty(context: container.mainContext)
|
|
154
|
+
}
|
|
155
|
+
#endif
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Then launch:
|
|
159
|
+
```
|
|
160
|
+
xcrun simctl launch booted <bundle-id> -SeedDebugSessions YES
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For multi-tab apps, also add a `-SelectedTab N` launch arg so any tab can be opened directly without taps. Both are gated by `#if DEBUG` and compile out of release builds — zero production cost.
|
|
164
|
+
|
|
165
|
+
**Use the seeder.** Subagents that report "I trust the math, ship it" without rendering the actual screen will miss visual bugs. Build 55 shipped a broken gauge because no one rendered it. Build 56 caught it because the seeder existed. The seeder pays for itself the first time it catches a bug.
|
|
166
|
+
|
|
167
|
+
## Output requirements
|
|
168
|
+
|
|
169
|
+
Your output to the orchestrator must include:
|
|
170
|
+
|
|
171
|
+
- Files created / modified
|
|
172
|
+
- Build result (✅ / ❌)
|
|
173
|
+
- UI input/output contract result: covered surfaces, deviations, and any N/A entries
|
|
174
|
+
- Scanner result on changed files: must-fix count (must be 0), warn count
|
|
175
|
+
- Every `RULE BEATS MOCKUP:` decision (one line each)
|
|
176
|
+
- Every `CONTRACT DEVIATION:` decision (one line each)
|
|
177
|
+
- Any anti-pattern you intentionally left in place + why (must be explicitly justified, not silently shipped)
|
|
178
|
+
|
|
179
|
+
Returning without these sections forces the orchestrator to re-prompt you. Don't skip.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: {id}
|
|
3
|
+
dimension: {dimension}
|
|
4
|
+
severity: {severity}
|
|
5
|
+
label: {label}
|
|
6
|
+
architecture_impact: {architecture_impact}
|
|
7
|
+
files_touched:
|
|
8
|
+
{files_touched_yaml}
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
12
|
+
|
|
13
|
+
# UX Fix Plan: {label}
|
|
14
|
+
|
|
15
|
+
**Hint**: {hint}
|
|
16
|
+
|
|
17
|
+
## Evidence
|
|
18
|
+
|
|
19
|
+
{evidence}
|
|
20
|
+
|
|
21
|
+
## Proposed fix
|
|
22
|
+
|
|
23
|
+
{proposed_fix}
|
|
24
|
+
|
|
25
|
+
## Rollback
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
{rollback}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Notes
|
|
32
|
+
|
|
33
|
+
- `architecture_impact: true` means this fix introduces a new component, data
|
|
34
|
+
flow, navigation graph, schema migration, or auth provider change. The
|
|
35
|
+
orchestrator must surface it in Review-F for explicit user confirmation
|
|
36
|
+
before Iterate dequeues it.
|
|
37
|
+
- `architecture_impact: false` entries are auto-fixable in the next Iterate
|
|
38
|
+
cycle, parallelized when independent (`files_touched` disjoint).
|
|
39
|
+
- `severity: minor` entries never reach this template — they live in the
|
|
40
|
+
Review-F report only.
|