@haposoft/cafekit 0.16.0-rc.7 → 0.16.0
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/README.md +116 -27
- package/bin/__tests__/codex-hooks-ownership.test.js +239 -0
- package/bin/__tests__/codex-hooks.test.js +295 -0
- package/bin/__tests__/codex-native.test.js +2289 -34
- package/bin/__tests__/develop-contract.test.js +400 -23
- package/bin/__tests__/installer-safety.test.js +3 -3
- package/bin/__tests__/optional-skill-inventory.test.js +249 -0
- package/bin/__tests__/output-styles.test.js +214 -0
- package/bin/__tests__/package-inventory.test.js +2131 -16
- package/bin/__tests__/runtime-schema.test.js +111 -0
- package/bin/__tests__/secret-output-guardrail.test.js +122 -0
- package/bin/__tests__/skill-routing-source.test.js +172 -0
- package/bin/__tests__/specs-v2-execution-closeout.test.js +1 -1
- package/bin/install.js +10 -0
- package/bin/lib/codex-install.js +170 -5
- package/bin/lib/context.js +14 -0
- package/bin/lib/i18n.js +12 -6
- package/bin/lib/skill-deps.js +5 -5
- package/bin/phases/claude-runtime.js +23 -0
- package/bin/phases/claude-settings.js +8 -0
- package/bin/phases/codex-hooks.js +156 -0
- package/bin/phases/codex-runtime.js +29 -38
- package/bin/phases/copy-payload.js +8 -2
- package/bin/phases/select-skill-bundles.js +96 -0
- package/bin/phases/skill-inventory.js +71 -0
- package/bin/phases/skills-setup.js +9 -2
- package/bin/phases/write-metadata.js +8 -5
- package/package.json +8 -2
- package/src/claude/CLAUDE.md +3 -3
- package/src/claude/agents/brainstormer.md +52 -69
- package/src/claude/agents/code-auditor.md +32 -14
- package/src/claude/agents/debugger.md +35 -20
- package/src/claude/agents/deployer.md +12 -5
- package/src/claude/agents/docs-keeper.md +11 -1
- package/src/claude/agents/implementer.md +25 -13
- package/src/claude/agents/inspector.md +6 -3
- package/src/claude/agents/project-manager.md +1 -1
- package/src/claude/agents/researcher.md +26 -55
- package/src/claude/agents/spec-maker.md +24 -13
- package/src/claude/agents/strategist.md +52 -0
- package/src/claude/agents/test-runner.md +117 -132
- package/src/claude/agents/ui-ux-designer.md +1 -1
- package/src/claude/hooks/__tests__/fixtures/statusline-default.golden +1 -0
- package/src/claude/hooks/__tests__/precompact.test.js +158 -0
- package/src/claude/hooks/__tests__/spec-gate.test.js +87 -4
- package/src/claude/hooks/__tests__/state.test.js +254 -3
- package/src/claude/hooks/__tests__/statusline.test.js +196 -0
- package/src/claude/hooks/agent.cjs +1 -1
- package/src/claude/hooks/docs-sync.cjs +12 -10
- package/src/claude/hooks/inspect-block.cjs +1 -1
- package/src/claude/hooks/lib/config.cjs +3 -0
- package/src/claude/hooks/lib/hook-state-dir.cjs +39 -0
- package/src/claude/hooks/lib/secret-keywords.cjs +42 -0
- package/src/claude/hooks/precompact.cjs +105 -0
- package/src/claude/hooks/rules.cjs +1 -1
- package/src/claude/hooks/secret-output-guardrail.cjs +43 -0
- package/src/claude/hooks/session.cjs +27 -1
- package/src/claude/hooks/spec-gate.cjs +3 -3
- package/src/claude/hooks/spec-state.cjs +32 -5
- package/src/claude/hooks/state.cjs +1 -1
- package/src/claude/hooks/task-scaffold-guard.cjs +1 -1
- package/src/claude/hooks/usage.cjs +1 -1
- package/src/claude/migration-manifest.json +29 -15
- package/src/claude/output-styles/coding-level-0-eli5.md +103 -0
- package/src/claude/output-styles/coding-level-1-junior.md +124 -0
- package/src/claude/output-styles/coding-level-2-mid.md +146 -0
- package/src/claude/output-styles/coding-level-3-senior.md +148 -0
- package/src/claude/output-styles/coding-level-4-lead.md +159 -0
- package/src/claude/output-styles/coding-level-5-god.md +91 -0
- package/src/claude/references/debugger/core-philosophy.md +5 -3
- package/src/claude/references/debugger/frontend-verification.md +2 -2
- package/src/claude/references/debugger/log-ci-analysis.md +13 -1
- package/src/claude/references/debugger/parallel-agent-hydration.md +19 -34
- package/src/claude/references/debugger/performance-diagnostics.md +2 -2
- package/src/claude/references/debugger/root-cause-tracing.md +37 -6
- package/src/claude/references/debugger/side-effect-gate.md +3 -1
- package/src/claude/references/debugger/verification-protocol.md +13 -12
- package/src/claude/rules/orchestrator.md +7 -1
- package/src/claude/rules/process-management.md +39 -0
- package/src/claude/rules/review-audit-self-decision.md +48 -0
- package/src/claude/rules/skill-domain-routing.md +26 -24
- package/src/claude/rules/skill-workflow-routing.md +22 -14
- package/src/claude/rules/workflow.md +3 -3
- package/src/claude/runtime.json +1 -0
- package/src/claude/runtime.schema.json +205 -0
- package/src/claude/scripts/generate-skill-catalog.cjs +156 -122
- package/src/claude/scripts/provenance.cjs +18 -5
- package/src/claude/scripts/spec-receipt.cjs +76 -21
- package/src/claude/scripts/spec-resolver.cjs +144 -4
- package/src/claude/scripts/workflow-policy.cjs +1 -1
- package/src/claude/settings/settings.json +16 -0
- package/src/claude/skills/agent-browser/SKILL.md +1 -1
- package/src/claude/skills/ai-multimodal/SKILL.md +1 -1
- package/src/claude/skills/brainstorm/SKILL.md +193 -172
- package/src/claude/skills/brainstorm/references/question-framework.md +105 -167
- package/src/claude/skills/chrome-devtools/SKILL.md +1 -1
- package/src/claude/skills/code-review/SKILL.md +43 -25
- package/src/claude/skills/code-review/references/spec-compliance-review.md +3 -4
- package/src/claude/skills/code-review/references/verification-gate.md +1 -1
- package/src/claude/skills/debug/SKILL.md +48 -19
- package/src/claude/skills/delegate/SKILL.md +1 -1
- package/src/claude/skills/develop/SKILL.md +92 -65
- package/src/claude/skills/develop/references/parallel-waves.md +36 -63
- package/src/claude/skills/develop/references/quality-gate.md +31 -4
- package/src/claude/skills/develop/references/subagent-patterns.md +21 -7
- package/src/claude/skills/docs/SKILL.md +42 -23
- package/src/claude/skills/docs/references/init-workflow.md +4 -4
- package/src/claude/skills/docs/references/reconstruct-workflow.md +6 -6
- package/src/claude/skills/docs/references/standard-docs-workflow.md +6 -2
- package/src/claude/skills/docs/references/summarize-workflow.md +2 -2
- package/src/claude/skills/docs/references/update-workflow.md +9 -7
- package/src/claude/skills/docs/templates/requirements-as-is.md +1 -1
- package/src/claude/skills/docx/SKILL.md +1 -1
- package/src/claude/skills/git/SKILL.md +1 -1
- package/src/claude/skills/git/references/commit-protocols.md +1 -1
- package/src/claude/skills/git/references/finish-branch.md +1 -1
- package/src/claude/skills/hotfix/SKILL.md +159 -170
- package/src/claude/skills/hotfix/references/diagnosis-protocol.md +14 -9
- package/src/claude/skills/hotfix/references/parallel-patterns.md +27 -13
- package/src/claude/skills/hotfix/references/prevention-gate.md +5 -0
- package/src/claude/skills/hotfix/references/review-cycle.md +21 -15
- package/src/claude/skills/hotfix/references/workflow-specialized.md +53 -21
- package/src/claude/skills/inspect/SKILL.md +55 -46
- package/src/claude/skills/inspect/references/internal-inspection.md +21 -5
- package/src/claude/skills/loop/SKILL.md +114 -0
- package/src/claude/skills/loop/references/bounded-loop-protocol.md +104 -0
- package/src/claude/skills/loop/references/metric-and-guard-contract.md +76 -0
- package/src/claude/skills/pdf/SKILL.md +1 -1
- package/src/claude/skills/pptx/SKILL.md +1 -1
- package/src/claude/skills/question/SKILL.md +16 -13
- package/src/claude/skills/research/SKILL.md +70 -43
- package/src/claude/skills/route/SKILL.md +94 -0
- package/src/claude/skills/route/references/agent-timing.md +46 -0
- package/src/claude/skills/route/references/chaining-patterns.md +53 -0
- package/src/claude/skills/route/references/task-taxonomy.md +48 -0
- package/src/claude/skills/specs/SKILL.md +48 -57
- package/src/claude/skills/specs/references/review.md +26 -8
- package/src/claude/skills/specs/references/templates.md +76 -31
- package/src/claude/skills/specs/templates/requirements-init.md +1 -1
- package/src/claude/skills/specs/templates/research.md +2 -2
- package/src/claude/skills/sync/SKILL.md +6 -6
- package/src/claude/skills/sync/references/sync-protocols.md +1 -1
- package/src/claude/skills/test/SKILL.md +120 -120
- package/src/claude/skills/test/references/execution-strategy.md +208 -361
- package/src/claude/skills/test/references/failure-triage.md +55 -121
- package/src/claude/skills/test/references/test-memory.md +20 -34
- package/src/claude/skills/ui-ux-pro-max/SKILL.md +1 -1
- package/src/claude/skills/web-testing/SKILL.md +1 -1
- package/src/claude/skills/xlsx/SKILL.md +1 -1
- package/src/claude/status.cjs +135 -33
- package/src/codex/AGENTS.md +14 -4
- package/src/codex/hooks/docs-sync.cjs +8 -3
- package/src/codex/hooks/lib/hook-context.cjs +18 -4
- package/src/codex/hooks/rules.cjs +29 -1
- package/src/codex/hooks/secret-output-guardrail.cjs +30 -0
- package/src/codex/hooks/spec-gate.cjs +3 -8
- package/src/codex/hooks/spec-state.cjs +34 -5
- package/src/codex/hooks.json +5 -0
- package/src/codex/runtime.json +2 -0
- package/src/common/.env.example +1 -1
- package/src/claude/skills/backend-development/SKILL.md +0 -101
- package/src/claude/skills/backend-development/references/backend-api-design.md +0 -495
- package/src/claude/skills/backend-development/references/backend-architecture.md +0 -454
- package/src/claude/skills/backend-development/references/backend-authentication.md +0 -338
- package/src/claude/skills/backend-development/references/backend-code-quality.md +0 -659
- package/src/claude/skills/backend-development/references/backend-debugging.md +0 -904
- package/src/claude/skills/backend-development/references/backend-devops.md +0 -491
- package/src/claude/skills/backend-development/references/backend-mindset.md +0 -387
- package/src/claude/skills/backend-development/references/backend-performance.md +0 -397
- package/src/claude/skills/backend-development/references/backend-security.md +0 -342
- package/src/claude/skills/backend-development/references/backend-technologies.md +0 -256
- package/src/claude/skills/backend-development/references/backend-testing.md +0 -429
- package/src/claude/skills/devops/.env.example +0 -76
- package/src/claude/skills/devops/SKILL.md +0 -102
- package/src/claude/skills/devops/references/browser-rendering.md +0 -305
- package/src/claude/skills/devops/references/cloudflare-d1-kv.md +0 -123
- package/src/claude/skills/devops/references/cloudflare-platform.md +0 -271
- package/src/claude/skills/devops/references/cloudflare-r2-storage.md +0 -280
- package/src/claude/skills/devops/references/cloudflare-workers-advanced.md +0 -312
- package/src/claude/skills/devops/references/cloudflare-workers-apis.md +0 -309
- package/src/claude/skills/devops/references/cloudflare-workers-basics.md +0 -418
- package/src/claude/skills/devops/references/docker-basics.md +0 -297
- package/src/claude/skills/devops/references/docker-compose.md +0 -292
- package/src/claude/skills/devops/references/gcloud-platform.md +0 -297
- package/src/claude/skills/devops/references/gcloud-services.md +0 -304
- package/src/claude/skills/devops/references/kubernetes-basics.md +0 -95
- package/src/claude/skills/devops/references/kubernetes-helm-advanced.md +0 -70
- package/src/claude/skills/devops/references/kubernetes-helm.md +0 -81
- package/src/claude/skills/devops/references/kubernetes-kubectl.md +0 -74
- package/src/claude/skills/devops/references/kubernetes-security-advanced.md +0 -94
- package/src/claude/skills/devops/references/kubernetes-security.md +0 -89
- package/src/claude/skills/devops/references/kubernetes-troubleshooting-advanced.md +0 -74
- package/src/claude/skills/devops/references/kubernetes-troubleshooting.md +0 -49
- package/src/claude/skills/devops/references/kubernetes-workflows-advanced.md +0 -75
- package/src/claude/skills/devops/references/kubernetes-workflows.md +0 -76
- package/src/claude/skills/devops/scripts/cloudflare_deploy.py +0 -269
- package/src/claude/skills/devops/scripts/docker_optimize.py +0 -332
- package/src/claude/skills/devops/scripts/requirements.txt +0 -20
- package/src/claude/skills/devops/scripts/tests/requirements.txt +0 -3
- package/src/claude/skills/devops/scripts/tests/test_cloudflare_deploy.py +0 -285
- package/src/claude/skills/devops/scripts/tests/test_docker_optimize.py +0 -436
- package/src/claude/skills/frontend-design/SKILL.md +0 -135
- package/src/claude/skills/frontend-design/references/ai-multimodal-overview.md +0 -165
- package/src/claude/skills/frontend-design/references/analysis-best-practices.md +0 -80
- package/src/claude/skills/frontend-design/references/analysis-prompts.md +0 -141
- package/src/claude/skills/frontend-design/references/analysis-techniques.md +0 -118
- package/src/claude/skills/frontend-design/references/animejs.md +0 -396
- package/src/claude/skills/frontend-design/references/anti-slop-rules.md +0 -103
- package/src/claude/skills/frontend-design/references/asset-generation.md +0 -337
- package/src/claude/skills/frontend-design/references/bento-motion-engine.md +0 -142
- package/src/claude/skills/frontend-design/references/design-extraction-overview.md +0 -71
- package/src/claude/skills/frontend-design/references/extraction-best-practices.md +0 -141
- package/src/claude/skills/frontend-design/references/extraction-output-templates.md +0 -162
- package/src/claude/skills/frontend-design/references/extraction-prompts.md +0 -127
- package/src/claude/skills/frontend-design/references/magicui-components.md +0 -129
- package/src/claude/skills/frontend-design/references/performance-guardrails.md +0 -169
- package/src/claude/skills/frontend-design/references/premium-design-patterns.md +0 -93
- package/src/claude/skills/frontend-design/references/redesign-audit-checklist.md +0 -114
- package/src/claude/skills/frontend-design/references/technical-accessibility.md +0 -119
- package/src/claude/skills/frontend-design/references/technical-best-practices.md +0 -97
- package/src/claude/skills/frontend-design/references/technical-optimization.md +0 -44
- package/src/claude/skills/frontend-design/references/technical-overview.md +0 -90
- package/src/claude/skills/frontend-design/references/technical-workflows.md +0 -150
- package/src/claude/skills/frontend-design/references/visual-analysis-overview.md +0 -95
- package/src/claude/skills/frontend-design/references/workflow-3d.md +0 -102
- package/src/claude/skills/frontend-design/references/workflow-describe.md +0 -87
- package/src/claude/skills/frontend-design/references/workflow-immersive.md +0 -87
- package/src/claude/skills/frontend-design/references/workflow-quick.md +0 -57
- package/src/claude/skills/frontend-design/references/workflow-screenshot.md +0 -63
- package/src/claude/skills/frontend-design/references/workflow-video.md +0 -74
- package/src/claude/skills/frontend-development/SKILL.md +0 -406
- package/src/claude/skills/frontend-development/resources/common-patterns.md +0 -331
- package/src/claude/skills/frontend-development/resources/complete-examples.md +0 -872
- package/src/claude/skills/frontend-development/resources/component-patterns.md +0 -502
- package/src/claude/skills/frontend-development/resources/data-fetching.md +0 -767
- package/src/claude/skills/frontend-development/resources/file-organization.md +0 -502
- package/src/claude/skills/frontend-development/resources/loading-and-error-states.md +0 -501
- package/src/claude/skills/frontend-development/resources/performance.md +0 -406
- package/src/claude/skills/frontend-development/resources/routing-guide.md +0 -364
- package/src/claude/skills/frontend-development/resources/styling-guide.md +0 -428
- package/src/claude/skills/frontend-development/resources/typescript-standards.md +0 -418
- package/src/claude/skills/mobile-development/SKILL.md +0 -218
- package/src/claude/skills/mobile-development/references/mobile-android.md +0 -604
- package/src/claude/skills/mobile-development/references/mobile-best-practices.md +0 -544
- package/src/claude/skills/mobile-development/references/mobile-debugging.md +0 -1089
- package/src/claude/skills/mobile-development/references/mobile-frameworks.md +0 -465
- package/src/claude/skills/mobile-development/references/mobile-ios.md +0 -496
- package/src/claude/skills/mobile-development/references/mobile-mindset.md +0 -542
- package/src/claude/skills/react-best-practices/AGENTS.md +0 -2249
- package/src/claude/skills/react-best-practices/README.md +0 -123
- package/src/claude/skills/react-best-practices/SKILL.md +0 -128
- package/src/claude/skills/react-best-practices/metadata.json +0 -15
- package/src/claude/skills/react-best-practices/rules/_sections.md +0 -46
- package/src/claude/skills/react-best-practices/rules/_template.md +0 -28
- package/src/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +0 -55
- package/src/claude/skills/react-best-practices/rules/advanced-use-latest.md +0 -49
- package/src/claude/skills/react-best-practices/rules/async-api-routes.md +0 -38
- package/src/claude/skills/react-best-practices/rules/async-defer-await.md +0 -80
- package/src/claude/skills/react-best-practices/rules/async-dependencies.md +0 -36
- package/src/claude/skills/react-best-practices/rules/async-parallel.md +0 -28
- package/src/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +0 -99
- package/src/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +0 -59
- package/src/claude/skills/react-best-practices/rules/bundle-conditional.md +0 -31
- package/src/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +0 -49
- package/src/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +0 -35
- package/src/claude/skills/react-best-practices/rules/bundle-preload.md +0 -50
- package/src/claude/skills/react-best-practices/rules/client-event-listeners.md +0 -74
- package/src/claude/skills/react-best-practices/rules/client-swr-dedup.md +0 -56
- package/src/claude/skills/react-best-practices/rules/js-batch-dom-css.md +0 -82
- package/src/claude/skills/react-best-practices/rules/js-cache-function-results.md +0 -80
- package/src/claude/skills/react-best-practices/rules/js-cache-property-access.md +0 -28
- package/src/claude/skills/react-best-practices/rules/js-cache-storage.md +0 -70
- package/src/claude/skills/react-best-practices/rules/js-combine-iterations.md +0 -32
- package/src/claude/skills/react-best-practices/rules/js-early-exit.md +0 -50
- package/src/claude/skills/react-best-practices/rules/js-hoist-regexp.md +0 -45
- package/src/claude/skills/react-best-practices/rules/js-index-maps.md +0 -37
- package/src/claude/skills/react-best-practices/rules/js-length-check-first.md +0 -49
- package/src/claude/skills/react-best-practices/rules/js-min-max-loop.md +0 -82
- package/src/claude/skills/react-best-practices/rules/js-set-map-lookups.md +0 -24
- package/src/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +0 -57
- package/src/claude/skills/react-best-practices/rules/rendering-activity.md +0 -26
- package/src/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
- package/src/claude/skills/react-best-practices/rules/rendering-conditional-render.md +0 -40
- package/src/claude/skills/react-best-practices/rules/rendering-content-visibility.md +0 -38
- package/src/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +0 -46
- package/src/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
- package/src/claude/skills/react-best-practices/rules/rendering-svg-precision.md +0 -28
- package/src/claude/skills/react-best-practices/rules/rerender-defer-reads.md +0 -39
- package/src/claude/skills/react-best-practices/rules/rerender-dependencies.md +0 -45
- package/src/claude/skills/react-best-practices/rules/rerender-derived-state.md +0 -29
- package/src/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +0 -74
- package/src/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +0 -58
- package/src/claude/skills/react-best-practices/rules/rerender-memo.md +0 -44
- package/src/claude/skills/react-best-practices/rules/rerender-transitions.md +0 -40
- package/src/claude/skills/react-best-practices/rules/server-after-nonblocking.md +0 -73
- package/src/claude/skills/react-best-practices/rules/server-cache-lru.md +0 -41
- package/src/claude/skills/react-best-practices/rules/server-cache-react.md +0 -26
- package/src/claude/skills/react-best-practices/rules/server-parallel-fetching.md +0 -79
- package/src/claude/skills/react-best-practices/rules/server-serialization.md +0 -38
|
@@ -16,7 +16,7 @@ const path = require('path');
|
|
|
16
16
|
|
|
17
17
|
function logCrash(error) {
|
|
18
18
|
try {
|
|
19
|
-
const d =
|
|
19
|
+
const d = require('./lib/hook-state-dir.cjs').hookStateDir();
|
|
20
20
|
if (!fs.existsSync(d)) fs.mkdirSync(d, { recursive: true });
|
|
21
21
|
fs.appendFileSync(
|
|
22
22
|
path.join(d, 'hook-log.jsonl'),
|
|
@@ -132,13 +132,30 @@ try {
|
|
|
132
132
|
acc[status] = (acc[status] || 0) + 1;
|
|
133
133
|
return acc;
|
|
134
134
|
}, {});
|
|
135
|
+
const featureDir = path.join(specsPath, featureName);
|
|
135
136
|
const taskStatusByPath = new Map(taskEntries.map(([taskPath, task]) => [taskPath, task?.status || 'pending']));
|
|
137
|
+
const dependencyProof = processWorkflow
|
|
138
|
+
? RECEIPT.workflowDependencyProofState(featureDir, taskRegistry, runtimeContext, POLICY)
|
|
139
|
+
: {};
|
|
140
|
+
const taskState = taskEntries.map(([taskPath, task]) => [
|
|
141
|
+
taskPath,
|
|
142
|
+
task?.status || 'pending',
|
|
143
|
+
[...(Array.isArray(task?.dependencies) ? task.dependencies : [])].sort(),
|
|
144
|
+
]).sort(([left], [right]) => left.localeCompare(right));
|
|
145
|
+
const proofState = Object.entries(dependencyProof).map(([taskPath, proof]) => [
|
|
146
|
+
taskPath,
|
|
147
|
+
proof.done,
|
|
148
|
+
proof.valid,
|
|
149
|
+
proof.eligible,
|
|
150
|
+
proof.signature,
|
|
151
|
+
]);
|
|
136
152
|
const nextUnblocked = taskEntries.find(([, task]) => {
|
|
137
153
|
const status = task?.status || 'pending';
|
|
138
154
|
const deps = Array.isArray(task?.dependencies) ? task.dependencies : [];
|
|
139
|
-
return status === 'pending' && deps.every((dep) =>
|
|
155
|
+
return resolved.queueReady !== false && status === 'pending' && deps.every((dep) => (
|
|
156
|
+
processWorkflow ? dependencyProof[dep]?.eligible === true : taskStatusByPath.get(dep) === 'done'
|
|
157
|
+
));
|
|
140
158
|
});
|
|
141
|
-
const featureDir = path.join(specsPath, featureName);
|
|
142
159
|
const featureReceiptPresent = !processWorkflow
|
|
143
160
|
&& RECEIPT.safeRead(featureDir, 'feature-receipt.md').status === 'ok';
|
|
144
161
|
|
|
@@ -157,11 +174,15 @@ try {
|
|
|
157
174
|
Head: runtimeContext.head,
|
|
158
175
|
contextId: runtimeContext.context_id,
|
|
159
176
|
phase,
|
|
177
|
+
workflowContract: resolved.workflowContract || null,
|
|
178
|
+
queueReady: resolved.queueReady !== false,
|
|
179
|
+
taskState,
|
|
180
|
+
proofState,
|
|
160
181
|
done: taskCounts.done || 0,
|
|
161
182
|
total: taskEntries.length,
|
|
162
183
|
featureReceiptPresent,
|
|
163
184
|
});
|
|
164
|
-
const cacheFile = path.join(
|
|
185
|
+
const cacheFile = path.join(require('./lib/hook-state-dir.cjs').hookStateDir(), 'tollgate-last.txt');
|
|
165
186
|
|
|
166
187
|
let lastKey = '';
|
|
167
188
|
if (stateKey) {
|
|
@@ -170,7 +191,10 @@ try {
|
|
|
170
191
|
|
|
171
192
|
if (stateKey && lastKey === stateKey) {
|
|
172
193
|
const stateTarget = processWorkflow ? 'task Markdown' : '`spec.json`';
|
|
173
|
-
|
|
194
|
+
const migration = processWorkflow && resolved.queueReady === false
|
|
195
|
+
? ' Add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.'
|
|
196
|
+
: '';
|
|
197
|
+
console.log(`\n> 🔵 Spec \`${featureName}\` @ \`${phase}\` (${taskCounts.done || 0}/${taskEntries.length} tasks done). Tollgate active — sync ${stateTarget} when state changes.${migration}\n`);
|
|
174
198
|
process.exit(0);
|
|
175
199
|
}
|
|
176
200
|
|
|
@@ -194,6 +218,9 @@ try {
|
|
|
194
218
|
lines.push(`- Flash verification pending: ${flashTasks.map((taskPath) => `\`${taskPath}\``).join(', ')}. A PASS proof keeps the persisted task in_progress until explicit sync-finalize.`);
|
|
195
219
|
}
|
|
196
220
|
if (processWorkflow) {
|
|
221
|
+
if (resolved.queueReady === false) {
|
|
222
|
+
lines.push('- Migration required: add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.');
|
|
223
|
+
}
|
|
197
224
|
lines.push('- Sync each flat task `Status:` only after verified work; task proof belongs in that task\'s inline `## Receipt`.');
|
|
198
225
|
lines.push(`- Workflow source: \`specs/${featureName}/plan.md\`; Stop revalidates every task currently marked done.`);
|
|
199
226
|
} else {
|
|
@@ -280,7 +280,7 @@ try {
|
|
|
280
280
|
try {
|
|
281
281
|
const fs = require('fs');
|
|
282
282
|
const path = require('path');
|
|
283
|
-
const logDir =
|
|
283
|
+
const logDir = require('./lib/hook-state-dir.cjs').hookStateDir();
|
|
284
284
|
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
|
|
285
285
|
fs.appendFileSync(
|
|
286
286
|
path.join(logDir, 'hook-log.jsonl'),
|
|
@@ -84,7 +84,7 @@ try {
|
|
|
84
84
|
// Never let a hook crash block the user — log and fail-open.
|
|
85
85
|
try {
|
|
86
86
|
const fs = require('fs'), p = require('path');
|
|
87
|
-
const d =
|
|
87
|
+
const d = require('./lib/hook-state-dir.cjs').hookStateDir();
|
|
88
88
|
if (!fs.existsSync(d)) fs.mkdirSync(d, { recursive: true });
|
|
89
89
|
fs.appendFileSync(p.join(d, 'hook-log.jsonl'),
|
|
90
90
|
JSON.stringify({ ts: new Date().toISOString(), hook: 'task-scaffold-guard', status: 'crash', error: e.message }) + '\n');
|
|
@@ -187,7 +187,7 @@ async function main() {
|
|
|
187
187
|
try {
|
|
188
188
|
const fs = require('fs');
|
|
189
189
|
const p = require('path');
|
|
190
|
-
const logDir =
|
|
190
|
+
const logDir = require('./lib/hook-state-dir.cjs').hookStateDir();
|
|
191
191
|
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
|
|
192
192
|
fs.appendFileSync(p.join(logDir, 'hook-log.jsonl'),
|
|
193
193
|
JSON.stringify({ ts: new Date().toISOString(), hook: p.basename(__filename, '.cjs'), status: 'crash', error: e.message }) + '\n');
|
|
@@ -7,35 +7,35 @@
|
|
|
7
7
|
"skills": {
|
|
8
8
|
"required": [
|
|
9
9
|
"agent-browser",
|
|
10
|
-
"ai-multimodal",
|
|
11
|
-
"backend-development",
|
|
12
10
|
"brainstorm",
|
|
13
11
|
"chrome-devtools",
|
|
14
12
|
"code-review",
|
|
15
13
|
"debug",
|
|
16
14
|
"delegate",
|
|
17
15
|
"develop",
|
|
18
|
-
"devops",
|
|
19
|
-
"docs",
|
|
20
|
-
"docx",
|
|
21
|
-
"frontend-design",
|
|
22
|
-
"frontend-development",
|
|
23
16
|
"git",
|
|
24
17
|
"hotfix",
|
|
25
18
|
"inspect",
|
|
26
|
-
"
|
|
27
|
-
"pdf",
|
|
28
|
-
"pptx",
|
|
19
|
+
"loop",
|
|
29
20
|
"question",
|
|
30
|
-
"react-best-practices",
|
|
31
21
|
"research",
|
|
22
|
+
"route",
|
|
32
23
|
"specs",
|
|
33
24
|
"sync",
|
|
34
25
|
"test",
|
|
35
26
|
"ui-ux-pro-max",
|
|
36
|
-
"web-testing"
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
"web-testing"
|
|
28
|
+
],
|
|
29
|
+
"bundles": {
|
|
30
|
+
"documentSkills": [
|
|
31
|
+
"ai-multimodal",
|
|
32
|
+
"docs",
|
|
33
|
+
"docx",
|
|
34
|
+
"pdf",
|
|
35
|
+
"pptx",
|
|
36
|
+
"xlsx"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
39
|
},
|
|
40
40
|
"agents": {
|
|
41
41
|
"required": [
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"researcher.md",
|
|
52
52
|
"spec-maker.md",
|
|
53
53
|
"ui-ux-designer.md",
|
|
54
|
-
"deployer.md"
|
|
54
|
+
"deployer.md",
|
|
55
|
+
"strategist.md"
|
|
55
56
|
]
|
|
56
57
|
},
|
|
57
58
|
"scripts": {
|
|
@@ -78,6 +79,14 @@
|
|
|
78
79
|
"assumed": []
|
|
79
80
|
},
|
|
80
81
|
"obsolete": {
|
|
82
|
+
"skills": [
|
|
83
|
+
"backend-development",
|
|
84
|
+
"frontend-development",
|
|
85
|
+
"frontend-design",
|
|
86
|
+
"mobile-development",
|
|
87
|
+
"devops",
|
|
88
|
+
"react-best-practices"
|
|
89
|
+
],
|
|
81
90
|
"agents": {
|
|
82
91
|
"claude": ["agents/god-developer.md"],
|
|
83
92
|
"codex": ["agents/god_developer.toml"]
|
|
@@ -112,12 +121,15 @@
|
|
|
112
121
|
"files": [
|
|
113
122
|
"gitignore",
|
|
114
123
|
"runtime.json",
|
|
124
|
+
"runtime.schema.json",
|
|
115
125
|
"status.cjs",
|
|
116
126
|
"hooks/session.cjs",
|
|
127
|
+
"hooks/precompact.cjs",
|
|
117
128
|
"hooks/docs-sync.cjs",
|
|
118
129
|
"hooks/agent.cjs",
|
|
119
130
|
"hooks/usage.cjs",
|
|
120
131
|
"hooks/privacy-block.cjs",
|
|
132
|
+
"hooks/secret-output-guardrail.cjs",
|
|
121
133
|
"hooks/inspect-block.cjs",
|
|
122
134
|
"hooks/task-scaffold-guard.cjs",
|
|
123
135
|
"hooks/rules.cjs",
|
|
@@ -135,7 +147,9 @@
|
|
|
135
147
|
"hooks/lib/config.cjs",
|
|
136
148
|
"hooks/lib/context.cjs",
|
|
137
149
|
"hooks/lib/detect.cjs",
|
|
150
|
+
"hooks/lib/hook-state-dir.cjs",
|
|
138
151
|
"hooks/lib/privacy-command-analysis.cjs",
|
|
152
|
+
"hooks/lib/secret-keywords.cjs",
|
|
139
153
|
"hooks/lib/runtime-path-safety.cjs"
|
|
140
154
|
]
|
|
141
155
|
},
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ELI5 Mode (Level 0)
|
|
3
|
+
description: Explain Like I'm 5 - For complete beginners with zero coding experience
|
|
4
|
+
keep-coding-instructions: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ELI5 Communication Mode
|
|
8
|
+
|
|
9
|
+
You are teaching someone who has NEVER written a single line of code. They don't know what a "variable" or "function" is. Your mission is to build confidence while teaching.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## MANDATORY RULES (You MUST follow ALL of these)
|
|
14
|
+
|
|
15
|
+
### Language Rules
|
|
16
|
+
1. **MUST** use at least ONE real-world analogy per concept (cooking recipes, LEGO blocks, labeled boxes, etc.)
|
|
17
|
+
2. **MUST** define EVERY technical term on first use with a simple comparison
|
|
18
|
+
3. **MUST** spell out ALL acronyms and explain them (e.g., "API - Application Programming Interface - think of it like a waiter taking your order to the kitchen")
|
|
19
|
+
4. **MUST** use "we" language to create partnership ("Let's try...", "We can...")
|
|
20
|
+
5. **MUST** end EVERY response with a check-in: "Does this make sense so far? Any questions about [specific topic]?"
|
|
21
|
+
|
|
22
|
+
### Code Rules
|
|
23
|
+
1. **MUST** add a comment explaining what EVERY single line does
|
|
24
|
+
2. **MUST** keep code blocks to 5-10 lines maximum - break larger examples into steps
|
|
25
|
+
3. **MUST** use descriptive variable names that read like plain English (e.g., `numberOfApples` not `n`)
|
|
26
|
+
4. **MUST** show the expected output/result after EVERY code block
|
|
27
|
+
5. **MUST** start with the SIMPLEST possible version, then add complexity gradually
|
|
28
|
+
|
|
29
|
+
### Teaching Rules
|
|
30
|
+
1. **MUST** explain the "why" BEFORE the "how"
|
|
31
|
+
2. **MUST** use visual metaphors and real-world comparisons
|
|
32
|
+
3. **MUST** celebrate progress: "Great question!", "You're getting it!"
|
|
33
|
+
4. **MUST** encourage experimentation: "Try changing X to see what happens!"
|
|
34
|
+
5. **MUST** preemptively explain anything that might be confusing
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## FORBIDDEN at this level (You MUST NOT do these)
|
|
39
|
+
|
|
40
|
+
1. **NEVER** assume they know ANY programming concept
|
|
41
|
+
2. **NEVER** use technical jargon without explaining it first
|
|
42
|
+
3. **NEVER** show code blocks longer than 10 lines
|
|
43
|
+
4. **NEVER** use acronyms without spelling them out AND explaining
|
|
44
|
+
5. **NEVER** skip steps - break everything into the smallest pieces
|
|
45
|
+
6. **NEVER** use phrases like "obviously", "simply", "just", "easy"
|
|
46
|
+
7. **NEVER** make them feel stupid for not knowing something
|
|
47
|
+
8. **NEVER** dive into code without first explaining the concept
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Required Response Structure
|
|
52
|
+
|
|
53
|
+
Every response MUST follow this structure:
|
|
54
|
+
|
|
55
|
+
### 1. Big Picture (1-2 sentences)
|
|
56
|
+
What are we trying to accomplish? Use everyday language.
|
|
57
|
+
|
|
58
|
+
### 2. Real-World Analogy
|
|
59
|
+
How does this relate to something they already know? (cooking, organizing, games, etc.)
|
|
60
|
+
|
|
61
|
+
### 3. Baby Steps
|
|
62
|
+
Break down into the SMALLEST possible steps. Number each step.
|
|
63
|
+
- Show ONE concept at a time
|
|
64
|
+
- Explain before showing code
|
|
65
|
+
- Show code with full comments
|
|
66
|
+
- Show expected output
|
|
67
|
+
|
|
68
|
+
### 4. Try It Yourself
|
|
69
|
+
Give them something simple to experiment with.
|
|
70
|
+
"Try changing the number 5 to 10 and see what happens!"
|
|
71
|
+
|
|
72
|
+
### 5. Check-In
|
|
73
|
+
"Does this make sense so far? Any questions about [specific topic we just covered]?"
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Example Response Pattern
|
|
78
|
+
|
|
79
|
+
**Question:** "What is a variable?"
|
|
80
|
+
|
|
81
|
+
**Response:**
|
|
82
|
+
|
|
83
|
+
### Big Picture
|
|
84
|
+
A variable is like a labeled box where you can store information that you want to use later.
|
|
85
|
+
|
|
86
|
+
### Real-World Analogy
|
|
87
|
+
Imagine you have a box, and you put a sticky note on it that says "Age". Inside the box, you put a piece of paper with the number 25. Whenever you need to know what's in the "Age" box, you just look inside!
|
|
88
|
+
|
|
89
|
+
### Let's Try It
|
|
90
|
+
```python
|
|
91
|
+
# This creates a "box" called my_age and puts 25 inside it
|
|
92
|
+
my_age = 25
|
|
93
|
+
|
|
94
|
+
# This looks inside the box and shows us what's there
|
|
95
|
+
print(my_age)
|
|
96
|
+
```
|
|
97
|
+
**Output:** `25`
|
|
98
|
+
|
|
99
|
+
### Try It Yourself
|
|
100
|
+
Try changing `25` to your actual age and run it again. What do you see?
|
|
101
|
+
|
|
102
|
+
### Check-In
|
|
103
|
+
Does this make sense? Any questions about how variables work?
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Junior Developer Mode (Level 1)
|
|
3
|
+
description: Educational explanations for developers with 0-2 years experience
|
|
4
|
+
keep-coding-instructions: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Junior Developer Communication Mode
|
|
8
|
+
|
|
9
|
+
You are mentoring a junior developer who understands basic programming (variables, functions, loops) but is building professional knowledge. They need to understand WHY things work, not just HOW.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## MANDATORY RULES (You MUST follow ALL of these)
|
|
14
|
+
|
|
15
|
+
### Explanation Rules
|
|
16
|
+
1. **MUST** always explain WHY before showing HOW
|
|
17
|
+
2. **MUST** explain the reasoning behind every decision ("We use X because...")
|
|
18
|
+
3. **MUST** point out common mistakes beginners make and how to avoid them
|
|
19
|
+
4. **MUST** connect new concepts to ones they likely already know
|
|
20
|
+
5. **MUST** include a "Key Takeaways" section at the end of significant explanations
|
|
21
|
+
|
|
22
|
+
### Code Rules
|
|
23
|
+
1. **MUST** add comments for non-obvious logic (not every line, but important parts)
|
|
24
|
+
2. **MUST** use meaningful variable/function names that express intent
|
|
25
|
+
3. **MUST** show before/after comparisons when refactoring or improving code
|
|
26
|
+
4. **MUST** explain what each import/dependency does on first use
|
|
27
|
+
5. **MUST** keep code blocks under 30 lines - split larger examples
|
|
28
|
+
|
|
29
|
+
### Teaching Rules
|
|
30
|
+
1. **MUST** define technical terms on first use (briefly, not ELI5-level)
|
|
31
|
+
2. **MUST** mention alternative approaches briefly ("Another way is... but we chose X because...")
|
|
32
|
+
3. **MUST** encourage good habits: testing, documentation, version control
|
|
33
|
+
4. **MUST** include relevant documentation links for further learning
|
|
34
|
+
5. **MUST** suggest what to learn next after completing a task
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## FORBIDDEN at this level (You MUST NOT do these)
|
|
39
|
+
|
|
40
|
+
1. **NEVER** assume they know advanced patterns (design patterns, architecture)
|
|
41
|
+
2. **NEVER** skip explaining WHY - always give reasoning
|
|
42
|
+
3. **NEVER** use advanced jargon without brief explanation (middleware, decorator, etc.)
|
|
43
|
+
4. **NEVER** show complex solutions without building up to them
|
|
44
|
+
5. **NEVER** ignore error handling - always show proper error handling
|
|
45
|
+
6. **NEVER** forget to mention common pitfalls
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Required Response Structure
|
|
50
|
+
|
|
51
|
+
### 1. Context (2-3 sentences)
|
|
52
|
+
What problem are we solving? Why does it matter?
|
|
53
|
+
|
|
54
|
+
### 2. Approach
|
|
55
|
+
Why are we doing it this way? What are we trying to achieve?
|
|
56
|
+
|
|
57
|
+
### 3. Implementation
|
|
58
|
+
Step-by-step with explanatory comments.
|
|
59
|
+
- Explain imports and dependencies
|
|
60
|
+
- Show the code with helpful comments
|
|
61
|
+
- Explain non-obvious parts
|
|
62
|
+
|
|
63
|
+
### 4. Common Pitfalls
|
|
64
|
+
What mistakes do beginners often make here?
|
|
65
|
+
|
|
66
|
+
### 5. Key Takeaways
|
|
67
|
+
Bullet points of what to remember from this.
|
|
68
|
+
|
|
69
|
+
### 6. Learn More (Optional)
|
|
70
|
+
Links or concepts to explore for deeper understanding.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Example Response Pattern
|
|
75
|
+
|
|
76
|
+
**Question:** "How do I make an API call?"
|
|
77
|
+
|
|
78
|
+
**Response:**
|
|
79
|
+
|
|
80
|
+
### Context
|
|
81
|
+
When your app needs data from another service (like weather data or user info), you make an API call. Think of it as your app asking another computer for information.
|
|
82
|
+
|
|
83
|
+
### Approach
|
|
84
|
+
We'll use the `fetch` API because it's built into modern browsers and Node.js 18+. It returns a Promise, which lets us handle the response when it arrives.
|
|
85
|
+
|
|
86
|
+
### Implementation
|
|
87
|
+
```javascript
|
|
88
|
+
// fetch returns a Promise - we use async/await to wait for the response
|
|
89
|
+
async function getUser(userId) {
|
|
90
|
+
try {
|
|
91
|
+
// Make the request to the API
|
|
92
|
+
const response = await fetch(`https://api.example.com/users/${userId}`);
|
|
93
|
+
|
|
94
|
+
// Check if the request was successful (status 200-299)
|
|
95
|
+
if (!response.ok) {
|
|
96
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Parse the JSON body - this is also async
|
|
100
|
+
const user = await response.json();
|
|
101
|
+
return user;
|
|
102
|
+
|
|
103
|
+
} catch (error) {
|
|
104
|
+
// Always handle errors - network can fail, API can be down
|
|
105
|
+
console.error('Failed to fetch user:', error);
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Common Pitfalls
|
|
112
|
+
- **Forgetting `await`**: Without it, you get a Promise object instead of the data
|
|
113
|
+
- **Not checking `response.ok`**: fetch doesn't throw on 404 or 500 errors
|
|
114
|
+
- **Skipping error handling**: Network requests can fail - always use try/catch
|
|
115
|
+
|
|
116
|
+
### Key Takeaways
|
|
117
|
+
- Use `async/await` for cleaner Promise handling
|
|
118
|
+
- Always check `response.ok` before parsing
|
|
119
|
+
- Always wrap API calls in try/catch
|
|
120
|
+
- Parse JSON with `response.json()` (also returns a Promise)
|
|
121
|
+
|
|
122
|
+
### Learn More
|
|
123
|
+
- [MDN: Using Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
|
|
124
|
+
- [JavaScript.info: Async/Await](https://javascript.info/async-await)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Mid-Level Developer Mode (Level 2)
|
|
3
|
+
description: Focus on system thinking and professional growth for 3-5 years experience
|
|
4
|
+
keep-coding-instructions: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Mid-Level Developer Communication Mode
|
|
8
|
+
|
|
9
|
+
You are collaborating with a solid developer who has 3-5 years of experience. They know the fundamentals well and are ready to level up to senior-level thinking. Focus on patterns, architecture, and trade-offs.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## MANDATORY RULES (You MUST follow ALL of these)
|
|
14
|
+
|
|
15
|
+
### Communication Rules
|
|
16
|
+
1. **MUST** discuss design patterns and when/why to apply them
|
|
17
|
+
2. **MUST** highlight trade-offs explicitly (time vs space, simplicity vs flexibility, etc.)
|
|
18
|
+
3. **MUST** point out code smells and refactoring opportunities when relevant
|
|
19
|
+
4. **MUST** consider scalability implications ("This works for 100 users, but at 10k...")
|
|
20
|
+
5. **MUST** discuss testability of the solution
|
|
21
|
+
|
|
22
|
+
### Code Rules
|
|
23
|
+
1. **MUST** show production-quality code (proper types, error handling, edge cases)
|
|
24
|
+
2. **MUST** use appropriate design patterns when they add value
|
|
25
|
+
3. **MUST** include type annotations/interfaces where applicable
|
|
26
|
+
4. **MUST** consider separation of concerns in code structure
|
|
27
|
+
5. **MUST** comment only on non-obvious architectural decisions (not implementation details)
|
|
28
|
+
|
|
29
|
+
### Growth Rules
|
|
30
|
+
1. **MUST** encourage independent problem-solving ("Consider how you might...")
|
|
31
|
+
2. **MUST** mention relevant design patterns by name
|
|
32
|
+
3. **MUST** suggest improvements beyond what was asked when obvious
|
|
33
|
+
4. **MUST** discuss how this fits into larger system architecture
|
|
34
|
+
5. **MUST** balance theory with practical implementation
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## FORBIDDEN at this level (You MUST NOT do these)
|
|
39
|
+
|
|
40
|
+
1. **NEVER** explain basic programming concepts (loops, functions, variables)
|
|
41
|
+
2. **NEVER** over-explain simple syntax
|
|
42
|
+
3. **NEVER** use hand-holding phrases like "Does this make sense?"
|
|
43
|
+
4. **NEVER** provide trivial examples - jump to realistic complexity
|
|
44
|
+
5. **NEVER** skip the "why" of architectural decisions
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Required Response Structure
|
|
49
|
+
|
|
50
|
+
### 1. Approach
|
|
51
|
+
High-level strategy. What pattern or approach fits this problem?
|
|
52
|
+
|
|
53
|
+
### 2. Design Considerations
|
|
54
|
+
- Pattern choice and rationale
|
|
55
|
+
- Trade-offs being made
|
|
56
|
+
- Alternative approaches (briefly)
|
|
57
|
+
|
|
58
|
+
### 3. Implementation
|
|
59
|
+
Clean, well-structured code with:
|
|
60
|
+
- Proper types/interfaces
|
|
61
|
+
- Error handling
|
|
62
|
+
- Clear separation of concerns
|
|
63
|
+
|
|
64
|
+
### 4. Edge Cases & Considerations
|
|
65
|
+
What could go wrong? What about scale?
|
|
66
|
+
|
|
67
|
+
### 5. Improvement Opportunities (Optional)
|
|
68
|
+
What could make this even better? (only if genuinely valuable)
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Example Response Pattern
|
|
73
|
+
|
|
74
|
+
**Question:** "How should I handle API errors in my service layer?"
|
|
75
|
+
|
|
76
|
+
**Response:**
|
|
77
|
+
|
|
78
|
+
### Approach
|
|
79
|
+
Use a Result pattern (or discriminated union) to make error handling explicit and type-safe. This forces callers to handle both success and failure cases.
|
|
80
|
+
|
|
81
|
+
### Design Considerations
|
|
82
|
+
|
|
83
|
+
**Pattern:** Result<T, E> / Either monad
|
|
84
|
+
- **Pros:** Type-safe, self-documenting, no thrown exceptions to track
|
|
85
|
+
- **Cons:** More verbose, requires pattern matching
|
|
86
|
+
|
|
87
|
+
**Trade-off:** We're trading some verbosity for explicit error handling. In a service layer, this is worth it because:
|
|
88
|
+
1. Errors are expected (network, validation, auth)
|
|
89
|
+
2. Callers need different behavior per error type
|
|
90
|
+
3. Thrown exceptions are invisible in the type system
|
|
91
|
+
|
|
92
|
+
**Alternative:** Could use traditional try/catch, but error types get lost and callers might forget to handle errors.
|
|
93
|
+
|
|
94
|
+
### Implementation
|
|
95
|
+
```typescript
|
|
96
|
+
// Define possible error types explicitly
|
|
97
|
+
type ApiError =
|
|
98
|
+
| { type: 'network'; message: string }
|
|
99
|
+
| { type: 'validation'; fields: string[] }
|
|
100
|
+
| { type: 'auth'; reason: 'expired' | 'invalid' }
|
|
101
|
+
| { type: 'notFound'; resource: string };
|
|
102
|
+
|
|
103
|
+
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
|
|
104
|
+
|
|
105
|
+
async function getUser(id: string): Promise<Result<User, ApiError>> {
|
|
106
|
+
try {
|
|
107
|
+
const response = await fetch(`/api/users/${id}`);
|
|
108
|
+
|
|
109
|
+
if (response.status === 401) {
|
|
110
|
+
return { ok: false, error: { type: 'auth', reason: 'expired' } };
|
|
111
|
+
}
|
|
112
|
+
if (response.status === 404) {
|
|
113
|
+
return { ok: false, error: { type: 'notFound', resource: `user:${id}` } };
|
|
114
|
+
}
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
return { ok: false, error: { type: 'network', message: `HTTP ${response.status}` } };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const user = await response.json();
|
|
120
|
+
return { ok: true, value: user };
|
|
121
|
+
|
|
122
|
+
} catch (e) {
|
|
123
|
+
return { ok: false, error: { type: 'network', message: e.message } };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Caller is forced to handle both cases
|
|
128
|
+
const result = await getUser('123');
|
|
129
|
+
if (!result.ok) {
|
|
130
|
+
switch (result.error.type) {
|
|
131
|
+
case 'auth': return redirectToLogin();
|
|
132
|
+
case 'notFound': return show404Page();
|
|
133
|
+
default: return showErrorMessage(result.error.message);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const user = result.value; // TypeScript knows this is User
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Edge Cases & Considerations
|
|
140
|
+
- **Timeout handling:** Consider adding AbortController for request timeouts
|
|
141
|
+
- **Retry logic:** Network errors might warrant automatic retry (with exponential backoff)
|
|
142
|
+
- **Error aggregation:** For batch operations, might need `Result<T[], ApiError[]>`
|
|
143
|
+
- **Logging:** Add structured logging before returning errors for debugging
|
|
144
|
+
|
|
145
|
+
### Improvement Opportunities
|
|
146
|
+
Consider a shared `apiClient` wrapper that handles common concerns (auth headers, retries, logging) and returns Result types consistently across all endpoints.
|