@jamie-tam/forge 6.0.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/LICENSE +21 -0
- package/README.md +389 -0
- package/agents/architect.md +92 -0
- package/agents/builder.md +122 -0
- package/agents/code-reviewer.md +107 -0
- package/agents/concept-designer.md +207 -0
- package/agents/craft-reviewer.md +132 -0
- package/agents/critic.md +130 -0
- package/agents/doc-writer.md +85 -0
- package/agents/dreamer.md +129 -0
- package/agents/e2e-runner.md +89 -0
- package/agents/gotcha-hunter.md +127 -0
- package/agents/prototype-builder.md +193 -0
- package/agents/prototype-codifier.md +204 -0
- package/agents/prototype-reviewer.md +163 -0
- package/agents/security-reviewer.md +108 -0
- package/agents/spec-reviewer.md +94 -0
- package/agents/tracer.md +98 -0
- package/agents/wireframer.md +109 -0
- package/commands/abort.md +25 -0
- package/commands/bugfix.md +151 -0
- package/commands/evolve.md +118 -0
- package/commands/feature.md +236 -0
- package/commands/forge.md +100 -0
- package/commands/greenfield.md +185 -0
- package/commands/hotfix.md +98 -0
- package/commands/refactor.md +147 -0
- package/commands/resume.md +25 -0
- package/commands/setup.md +201 -0
- package/commands/status.md +27 -0
- package/commands/task-force.md +110 -0
- package/commands/validate.md +12 -0
- package/dist/__tests__/active-manifest.test.js +272 -0
- package/dist/__tests__/copy.test.js +96 -0
- package/dist/__tests__/gate-check.test.js +384 -0
- package/dist/__tests__/wiki.test.js +472 -0
- package/dist/__tests__/work-manifest.test.js +304 -0
- package/dist/active-manifest.js +229 -0
- package/dist/cli.js +158 -0
- package/dist/copy.js +124 -0
- package/dist/gate-check.js +326 -0
- package/dist/hooks.js +60 -0
- package/dist/init.js +140 -0
- package/dist/manifest.js +90 -0
- package/dist/merge.js +77 -0
- package/dist/paths.js +36 -0
- package/dist/uninstall.js +216 -0
- package/dist/update.js +158 -0
- package/dist/verify-manifest.js +65 -0
- package/dist/verify.js +98 -0
- package/dist/wiki-ui.js +310 -0
- package/dist/wiki.js +364 -0
- package/dist/work-manifest.js +798 -0
- package/hooks/config/gate-requirements.json +79 -0
- package/hooks/hooks.json +143 -0
- package/hooks/scripts/analyze-telemetry.sh +114 -0
- package/hooks/scripts/gate-enforcer.sh +164 -0
- package/hooks/scripts/pre-compact.sh +90 -0
- package/hooks/scripts/session-start.sh +81 -0
- package/hooks/scripts/telemetry.sh +41 -0
- package/hooks/scripts/wiki-lint.sh +87 -0
- package/hooks/templates/AGENTS.md.template +48 -0
- package/hooks/templates/CLAUDE.md.template +45 -0
- package/package.json +55 -0
- package/protocols/README.md +40 -0
- package/protocols/codex.md +151 -0
- package/protocols/graphify.md +156 -0
- package/references/common/agent-coordination.md +65 -0
- package/references/common/coding-standards.md +54 -0
- package/references/common/feature-tracking.md +21 -0
- package/references/common/io-protocol.md +36 -0
- package/references/common/phases.md +57 -0
- package/references/common/quality-gates.md +130 -0
- package/references/common/skill-authoring.md +154 -0
- package/references/common/skill-compliance.md +30 -0
- package/references/python/standards.md +44 -0
- package/references/react/standards.md +61 -0
- package/references/typescript/standards.md +42 -0
- package/rules/common/forge-system.md +59 -0
- package/rules/common/git-workflow.md +40 -0
- package/rules/common/guardrails.md +37 -0
- package/rules/common/quality-gates.md +18 -0
- package/rules/common/security.md +50 -0
- package/rules/common/skill-selection.md +78 -0
- package/rules/common/testing.md +58 -0
- package/rules/common/verification.md +39 -0
- package/skills/build-pr-workflow/SKILL.md +301 -0
- package/skills/build-pr-workflow/references/pr-template.md +62 -0
- package/skills/build-pr-workflow/references/subagent-merge.md +47 -0
- package/skills/build-pr-workflow/references/worktree-setup.md +125 -0
- package/skills/build-prototype/SKILL.md +264 -0
- package/skills/build-scaffold/SKILL.md +340 -0
- package/skills/build-tdd/SKILL.md +89 -0
- package/skills/build-wireframe/SKILL.md +110 -0
- package/skills/build-wireframe/assets/baseline-template.html +486 -0
- package/skills/build-wireframe/references/demo-walkthroughs.md +170 -0
- package/skills/build-wireframe/references/gotchas.md +188 -0
- package/skills/build-wireframe/references/legend-lines.md +141 -0
- package/skills/concept-slides/SKILL.md +192 -0
- package/skills/deliver-db-migration/SKILL.md +466 -0
- package/skills/deliver-deploy/SKILL.md +407 -0
- package/skills/deliver-onboarding/SKILL.md +198 -0
- package/skills/deliver-onboarding/references/document-templates.md +393 -0
- package/skills/deliver-onboarding/templates/getting-started.md +122 -0
- package/skills/discover-codebase-analysis/SKILL.md +448 -0
- package/skills/discover-requirements/SKILL.md +418 -0
- package/skills/discover-requirements/templates/prd.md +99 -0
- package/skills/discover-requirements/templates/technical-spec.md +123 -0
- package/skills/discover-requirements/templates/user-stories.md +76 -0
- package/skills/harden/SKILL.md +214 -0
- package/skills/iterate-prototype/SKILL.md +241 -0
- package/skills/plan-architecture/SKILL.md +457 -0
- package/skills/plan-architecture/templates/adr-template.md +52 -0
- package/skills/plan-architecture/templates/api-contract.md +99 -0
- package/skills/plan-architecture/templates/db-schema.md +81 -0
- package/skills/plan-architecture/templates/system-design.md +111 -0
- package/skills/plan-brainstorm/SKILL.md +433 -0
- package/skills/plan-design-system/SKILL.md +279 -0
- package/skills/plan-task-decompose/SKILL.md +454 -0
- package/skills/quality-code-review/SKILL.md +286 -0
- package/skills/quality-security-audit/SKILL.md +292 -0
- package/skills/quality-security-audit/references/audit-report-template.md +89 -0
- package/skills/quality-security-audit/references/owasp-checks.md +178 -0
- package/skills/quality-test-execution/SKILL.md +435 -0
- package/skills/quality-test-plan/SKILL.md +297 -0
- package/skills/quality-test-plan/references/test-type-guide.md +263 -0
- package/skills/quality-test-plan/templates/e2e-test-plan.md +72 -0
- package/skills/quality-test-plan/templates/integration-test-plan.md +74 -0
- package/skills/quality-test-plan/templates/load-test-plan.md +111 -0
- package/skills/quality-test-plan/templates/smoke-test-plan.md +68 -0
- package/skills/quality-test-plan/templates/unit-test-plan.md +56 -0
- package/skills/quality-uiux/SKILL.md +481 -0
- package/skills/support-debug/SKILL.md +464 -0
- package/skills/support-dream/SKILL.md +213 -0
- package/skills/support-gotcha/SKILL.md +249 -0
- package/skills/support-runtime-reachability/SKILL.md +190 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-01-passes-app-use/src/app.ts +7 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-01-passes-app-use/src/handlers/cases.ts +7 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-02-orphan-no-app-use/src/app.ts +8 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-02-orphan-no-app-use/src/handlers/cases.ts +7 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-03-orphan-import-only/src/App.tsx +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-03-orphan-import-only/src/components/RingingBanner.tsx +7 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-03-orphan-import-only/src/hooks/useTwilio.ts +6 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-04-jsx-component-rendered/src/App.tsx +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-04-jsx-component-rendered/src/components/MyComp.tsx +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-05-jsx-component-not-rendered/src/App.tsx +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-05-jsx-component-not-rendered/src/components/Orphan.tsx +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-06-class-instantiated/src/lib/Service.ts +6 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-06-class-instantiated/src/main.ts +4 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-07-class-not-instantiated/src/lib/Lonely.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-07-class-not-instantiated/src/main.ts +2 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-08-default-export-imported-and-called/src/handler.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-08-default-export-imported-and-called/src/main.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-09-default-export-orphan/src/handler.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-09-default-export-orphan/src/main.ts +2 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-10-aliased-named-export/src/lib.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-10-aliased-named-export/src/main.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-11-re-export-chain/src/lib/index.ts +1 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-11-re-export-chain/src/lib/internal.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-11-re-export-chain/src/main.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-12-test-only-caller/src/util.test.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-12-test-only-caller/src/util.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-13-gated-pending-annotation/src/future.ts +4 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-14-untraceable-annotation/src/decorated.ts +4 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-15-untraceable-empty/src/lazy.ts +4 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-16-python-module/src/lib.py +15 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-16-python-module/src/main.py +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-17-router-use/src/parent.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-17-router-use/src/routes/cases.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-18-shadowed-name-fp/src/lib/foo.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-18-shadowed-name-fp/src/other.ts +8 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-19-same-name-different-module/src/handlers/cases.ts +4 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-19-same-name-different-module/src/handlers/users.ts +4 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-19-same-name-different-module/src/main.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-20-aliased-import-usage/src/handlers/cases.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-20-aliased-import-usage/src/main.ts +4 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-21-mixed-default-and-named/src/lib.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-21-mixed-default-and-named/src/main.ts +5 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-22-dynamic-import-then-caller/src/lib.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-22-dynamic-import-then-caller/src/main.ts +8 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-23-dynamic-import-with-space/src/lib.ts +3 -0
- package/skills/support-runtime-reachability/scripts/__fixtures__/case-23-dynamic-import-with-space/src/main.ts +7 -0
- package/skills/support-runtime-reachability/scripts/check.mjs +638 -0
- package/skills/support-runtime-reachability/scripts/check.test.mjs +244 -0
- package/skills/support-skill-validator/SKILL.md +194 -0
- package/skills/support-skill-validator/references/false-positives.md +59 -0
- package/skills/support-skill-validator/references/validation-checks.md +280 -0
- package/skills/support-system-guide/SKILL.md +311 -0
- package/skills/support-task-force/SKILL.md +265 -0
- package/skills/support-task-force/references/dispatch-pattern.md +178 -0
- package/skills/support-task-force/references/synthesis-template.md +126 -0
- package/skills/support-wiki-bootstrap/SKILL.md +37 -0
- package/skills/support-wiki-lint/SKILL.md +196 -0
- package/skills/support-wiki-lint/scripts/lint.mjs +488 -0
- package/skills/support-wiki-lint/scripts/lint.test.mjs +196 -0
- package/templates/README.md +23 -0
- package/templates/aiwiki/CLAUDE.md.template +78 -0
- package/templates/aiwiki/schemas/architecture.md +118 -0
- package/templates/aiwiki/schemas/convention.md +112 -0
- package/templates/aiwiki/schemas/decision.md +144 -0
- package/templates/aiwiki/schemas/gotcha.md +118 -0
- package/templates/aiwiki/schemas/oracle.md +105 -0
- package/templates/aiwiki/schemas/session.md +125 -0
- package/templates/manifests/bugfix.yaml +41 -0
- package/templates/manifests/feature.yaml +69 -0
- package/templates/manifests/greenfield.yaml +61 -0
- package/templates/manifests/hotfix.yaml +45 -0
- package/templates/manifests/refactor.yaml +44 -0
- package/templates/manifests/v5/SCHEMA.md +327 -0
- package/templates/manifests/v5/feature.yaml +77 -0
- package/templates/manifests/v6/SCHEMA.md +199 -0
- package/templates/wiki-html/dream-detail.html +378 -0
- package/templates/wiki-html/dreams-list.html +155 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: support-gotcha
|
|
3
|
+
description: "Use when a subtle bug, surprising behavior, or hard-won lesson is uncovered that could recur — records it as a typed wiki page for future prevention."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Support: Gotcha
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Every bug fixed, every failed approach, every "I wish I'd known that earlier" moment contains a lesson. This skill captures those lessons as typed wiki pages in `aiwiki/gotchas/` so future sessions hit them before the same mistake happens again.
|
|
11
|
+
|
|
12
|
+
**Core Principle:** A gotcha recorded once should prevent the same mistake forever.
|
|
13
|
+
|
|
14
|
+
**Announce at start:** "I'm using the support-gotcha skill to record this lesson learned."
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
**Automatic triggers (invoked by other skills):**
|
|
19
|
+
- After `support-debug` resolves a bug
|
|
20
|
+
- After `deliver-db-migration` encounters an issue
|
|
21
|
+
- After `deliver-deploy` has a rollback or complication
|
|
22
|
+
- After any skill encounters an unexpected failure
|
|
23
|
+
|
|
24
|
+
**Manual triggers:**
|
|
25
|
+
- User says "remember this" or "note this for next time"
|
|
26
|
+
- A non-obvious library or tool behavior is discovered
|
|
27
|
+
- A workaround is needed that should eventually be fixed properly
|
|
28
|
+
- A pattern keeps recurring across features
|
|
29
|
+
|
|
30
|
+
**Always record a gotcha when:**
|
|
31
|
+
- A bug took longer than expected to fix
|
|
32
|
+
- The fix was different from the initial hypothesis
|
|
33
|
+
- A library behaved differently than documented
|
|
34
|
+
- An environment-specific issue wasted time
|
|
35
|
+
- A process step was skipped and caused problems
|
|
36
|
+
|
|
37
|
+
**Do NOT write a gotcha for:** bugs in your own code that weren't framework- or pattern-related, one-off typos, problems already documented in `aiwiki/conventions/` (write the convention instead).
|
|
38
|
+
|
|
39
|
+
## I/O Contract
|
|
40
|
+
|
|
41
|
+
| Field | Value |
|
|
42
|
+
|---|---|
|
|
43
|
+
| **Requires** | Concrete lesson: what broke, why, how to prevent |
|
|
44
|
+
| **Produces** | Gotcha page in `aiwiki/gotchas/{YYYY-MM-DD}-{slug}.md` (project) or `~/.claude/gotchas/{YYYY-MM-DD}-{slug}.md` (global) |
|
|
45
|
+
| **Schema** | `aiwiki/schemas/gotcha.md` — LINT validates frontmatter + sections on write |
|
|
46
|
+
| **Feeds into** | Future sessions (prevention), `gotcha-hunter` agent (surfaces relevant entries to reviewers), `/evolve` (skill improvement) |
|
|
47
|
+
|
|
48
|
+
### Storage tiers
|
|
49
|
+
|
|
50
|
+
| Tier | Location | Scope | When |
|
|
51
|
+
|---|---|---|---|
|
|
52
|
+
| Project | `aiwiki/gotchas/` | This codebase only | Issue specific to this stack, patterns, or config |
|
|
53
|
+
| Global | `~/.claude/gotchas/` | All future projects | Issue applies universally — library behavior, general pattern |
|
|
54
|
+
|
|
55
|
+
When uncertain, default to project. The gotcha can be promoted later by writing a global copy and retiring the project one.
|
|
56
|
+
|
|
57
|
+
## The Gotcha Process
|
|
58
|
+
|
|
59
|
+
### Step 1: Extract the lesson
|
|
60
|
+
|
|
61
|
+
Three pieces of information must be concrete:
|
|
62
|
+
|
|
63
|
+
1. **What broke** — the failure or surprise, not the symptom
|
|
64
|
+
2. **Root cause** — what was actually wrong, not what looked wrong
|
|
65
|
+
3. **Prevention** — actionable steps ("Check X before doing Y"), not "be more careful"
|
|
66
|
+
|
|
67
|
+
### Step 2: Classify project vs global
|
|
68
|
+
|
|
69
|
+
| Question | Answer |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Would this happen in a different project with a different stack? | Yes → global |
|
|
72
|
+
| Is this about a specific library version, config, or this project's architecture? | Yes → project |
|
|
73
|
+
| Is this about Docker, CI, or deployment in general? | Yes → global |
|
|
74
|
+
|
|
75
|
+
When genuinely ambiguous, ask the user: "Project-specific or universal?"
|
|
76
|
+
|
|
77
|
+
### Step 3: Search for existing matches
|
|
78
|
+
|
|
79
|
+
Before writing a new file, grep `aiwiki/gotchas/` (and `~/.claude/gotchas/` for global) for the same pattern. If a matching gotcha exists:
|
|
80
|
+
|
|
81
|
+
- Bump its frontmatter `occurrences` field by 1
|
|
82
|
+
- Update `status` per the auto-promotion path (see Step 5): 1 → `active`, 2 → `watch`, 3 → `promotion-pending`
|
|
83
|
+
- Append a one-line entry under `## Reproducer` if the new occurrence has a different reproducer
|
|
84
|
+
|
|
85
|
+
Do NOT write a duplicate file.
|
|
86
|
+
|
|
87
|
+
### Step 4: Write the gotcha page
|
|
88
|
+
|
|
89
|
+
**File naming:** `{YYYY-MM-DD}-{slug}.md`. Slug is kebab-case, ≤8 words, describes the pattern (not the symptom).
|
|
90
|
+
|
|
91
|
+
**Schema-aligned frontmatter:**
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
---
|
|
95
|
+
schema_id: gotcha
|
|
96
|
+
schema_version: 1
|
|
97
|
+
severity: low | medium | high | critical
|
|
98
|
+
date: YYYY-MM-DD
|
|
99
|
+
occurrences: 1
|
|
100
|
+
status: active
|
|
101
|
+
---
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Required sections** (LINT will reject the file if any are missing or out of order):
|
|
105
|
+
|
|
106
|
+
| Section | Content | Citation |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| `## What broke` | One sentence — what failed and where | Cite the failure point |
|
|
109
|
+
| `## Reproducer` | Minimal steps or code link | Cite if linking to an existing test |
|
|
110
|
+
| `## Root cause` | What was actually wrong | Cite with `file:line@<sha7>` |
|
|
111
|
+
| `## Fix` | The resolution | Cite the fix code |
|
|
112
|
+
| `## Prevention` | Rule, check, or pattern that prevents recurrence | Cite a convention or rule if one exists |
|
|
113
|
+
|
|
114
|
+
**Line caps:** hard cap 150 lines, soft target 50-100. A gotcha that needs more than 150 lines is two gotchas, or it's narrative debug logs that don't belong here.
|
|
115
|
+
|
|
116
|
+
**Citations:** every section needs at least one. Code references use `file:line@<sha7>` form. LINT auto-fills missing `@<sha7>` on first save.
|
|
117
|
+
|
|
118
|
+
Skeleton example: see `aiwiki/schemas/gotcha.md`.
|
|
119
|
+
|
|
120
|
+
### Step 5: Auto-promotion path (1 → 2 → 3 occurrences)
|
|
121
|
+
|
|
122
|
+
The `occurrences` field drives `status` automatically. Step 3 bumps the count; this step records the corresponding state transition.
|
|
123
|
+
|
|
124
|
+
| Occurrences | `status` | What happens |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| 1 | `active` | Newly recorded. Default state. |
|
|
127
|
+
| 2 | `watch` | Pattern is accumulating. `gotcha-hunter` surfaces as "one more triggers promotion". No rule drafted yet. |
|
|
128
|
+
| 3 | `promotion-pending` | Auto-draft a proposed rule into frontmatter (see below). The next session-start surfaces this as a hard-interrupt. |
|
|
129
|
+
| 4+ | stays `promotion-pending` | Until the user reviews (Step 6), additional occurrences keep bumping `occurrences` but `status` stays at `promotion-pending`. |
|
|
130
|
+
|
|
131
|
+
**When occurrences hits 3 — draft the proposed rule (mechanical only):**
|
|
132
|
+
|
|
133
|
+
1. Set frontmatter `status: promotion-pending`.
|
|
134
|
+
2. Identify the target rule file from the **Promotion paths** table below.
|
|
135
|
+
3. Draft a one-to-three-sentence actionable rule based on the `## Prevention` section. Keep it imperative ("must / never / always") so it reads as a rule, not a tip.
|
|
136
|
+
4. Add a `proposed_rule:` block to the frontmatter:
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
proposed_rule:
|
|
140
|
+
rule_path: rules/common/{relevant-rule}.md
|
|
141
|
+
draft: |
|
|
142
|
+
{actionable rule statement}
|
|
143
|
+
drafted_at: YYYY-MM-DD
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
5. Surface to the user: "3rd occurrence of <title> recorded. Proposed rule drafted in frontmatter; awaiting review at next session start."
|
|
147
|
+
|
|
148
|
+
Do not edit any rule file at this step. Drafting is mechanical; promotion is reviewed at Step 6.
|
|
149
|
+
|
|
150
|
+
**Promotion paths:**
|
|
151
|
+
|
|
152
|
+
| Current page | Promotion target | When |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| Project gotcha (`aiwiki/gotchas/`) | Same gotcha as global (`~/.claude/gotchas/`) | Same pattern seen in a different project |
|
|
155
|
+
| Project gotcha at occurrences=3 | Project rule (`.claude/rules/<area>.md`) — typically a phase-conditional or always-on rule | 3× in same project |
|
|
156
|
+
| Global gotcha at occurrences=3 | Common rule (`rules/common/<area>.md`) | 3× across projects |
|
|
157
|
+
|
|
158
|
+
### Step 6: Session-start review of pending promotions
|
|
159
|
+
|
|
160
|
+
When session-start surfaces a gotcha with `status: promotion-pending` (always carries a `proposed_rule:` block), do not start new work. Process each one:
|
|
161
|
+
|
|
162
|
+
1. Read the gotcha's `## Prevention` section and the `proposed_rule.draft` value.
|
|
163
|
+
2. Ask the user: approve, defer, or reject.
|
|
164
|
+
|
|
165
|
+
**On approve:**
|
|
166
|
+
- Append the `draft` rule text to the file at `proposed_rule.rule_path` (create the file if needed; match its existing list/heading style).
|
|
167
|
+
- Invoke `support-skill-validator` against the modified rule file. If it reports a contradiction with existing rules, revert the rule-file edit and surface the contradiction. The user resolves the conflict and re-runs this step.
|
|
168
|
+
- On validator pass: change the gotcha's frontmatter `status: promotion-pending` → `status: promoted-to-rule`. Remove the `proposed_rule:` block. Cross-reference the rule path under `## Prevention`.
|
|
169
|
+
- Also update any other gotchas that share the same pattern with a `Promoted to rule: <rule_path>` line under `## Prevention`.
|
|
170
|
+
|
|
171
|
+
**On defer:** Leave `status: promotion-pending` and the `proposed_rule:` block in frontmatter. Append a `defer:` field with the user's rationale and date. Next session-start surfaces it again.
|
|
172
|
+
|
|
173
|
+
**On reject:** Change frontmatter `status: promotion-pending` → `status: rejected`. Remove the `proposed_rule:` block. Add a one-line note under `## Prevention`: "Proposed rule rejected ({date}): {reason}". The gotcha is retained as a recorded lesson, but session-start will not re-prompt and `gotcha-hunter` skips it at session-start scope.
|
|
174
|
+
|
|
175
|
+
### Step 7: Retiring a gotcha
|
|
176
|
+
|
|
177
|
+
When a gotcha no longer applies (framework upgrade made it impossible, code path was removed, library fixed the underlying issue):
|
|
178
|
+
|
|
179
|
+
- Change frontmatter `status` → `status: retired` (regardless of prior state)
|
|
180
|
+
- Add a one-line note under `## Prevention`: "Retired ({date}): {reason}"
|
|
181
|
+
|
|
182
|
+
LINT preserves retired entries — they're still searchable history. `gotcha-hunter` skips retired entries when surfacing context to reviewers.
|
|
183
|
+
|
|
184
|
+
## Severity classification
|
|
185
|
+
|
|
186
|
+
| Severity | Criteria | Example |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| `critical` | Data loss, security breach, production outage | Migration deletes production data |
|
|
189
|
+
| `high` | Significant time waste (1+ hour), incorrect behavior shipped | Subtle race condition in auth |
|
|
190
|
+
| `medium` | Moderate time waste (15-60 min), development friction | Docker seed duplication |
|
|
191
|
+
| `low` | Minor inconvenience, cosmetic, easily worked around | Wrong import path convention |
|
|
192
|
+
|
|
193
|
+
## Status values (schema-canonical)
|
|
194
|
+
|
|
195
|
+
The unified status vocabulary spans the auto-promotion path and manual retirement. Transitions are governed by `occurrences` (auto) and user review (manual). `gotcha-hunter` and `support-wiki-lint` both validate against this enum.
|
|
196
|
+
|
|
197
|
+
| Status | Meaning | How entered |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| `active` | Newly recorded; `occurrences = 1`. Default state. | Step 4 writes a new gotcha. |
|
|
200
|
+
| `watch` | `occurrences = 2`. Pattern is accumulating; one more occurrence triggers promotion drafting. | Step 3 bumps a 1× gotcha to 2×. |
|
|
201
|
+
| `promotion-pending` | `occurrences = 3` (or more, until reviewed). A `proposed_rule:` block is attached. Awaits user review at next session-start. | Step 5 auto-drafts. |
|
|
202
|
+
| `promoted-to-rule` | The proposed rule was approved and appended to a rule file. Gotcha retained as cross-referenced provenance. | Step 6 approve path. |
|
|
203
|
+
| `rejected` | User reviewed a `promotion-pending` gotcha and declined promotion. Do not re-prompt. Lesson stays recorded; `gotcha-hunter` skips at session-start scope. | Step 6 reject path. |
|
|
204
|
+
| `retired` | Gotcha no longer applies (framework upgrade, code path removed, library fixed). Kept for searchable history; `gotcha-hunter` skips. | Step 7 manual. |
|
|
205
|
+
|
|
206
|
+
## Session-start integration
|
|
207
|
+
|
|
208
|
+
A session-start hook scans `aiwiki/gotchas/INDEX.md` (and `~/.claude/gotchas/INDEX.md`) for rows whose `status` cell is `promotion-pending` and surfaces them as a hard-interrupt before new work begins. Step 6 is the gate between "draft rule" and "ship rule".
|
|
209
|
+
|
|
210
|
+
When no pending promotions exist, `gotcha-hunter` (separate agent) reads `aiwiki/gotchas/` to surface diff-relevant entries to reviewers in the `quality-code-review` chain.
|
|
211
|
+
|
|
212
|
+
## Red flags — record a gotcha
|
|
213
|
+
|
|
214
|
+
| Situation | Why |
|
|
215
|
+
|---|---|
|
|
216
|
+
| "Oh, I've seen this before" | If you've seen it and it isn't recorded, it will happen again |
|
|
217
|
+
| Fix took more than 3 attempts | The debugging path itself is worth recording |
|
|
218
|
+
| Library behaved differently than documented | Future sessions will hit this too |
|
|
219
|
+
| "Works on my machine" issues | Environment differences are always gotcha-worthy |
|
|
220
|
+
| Skipped a process step and paid for it | Process-compliance lessons are valuable |
|
|
221
|
+
| Found a workaround instead of a fix | Both the workaround and the underlying issue need documenting |
|
|
222
|
+
| Deployment had unexpected complications | Deployment lessons prevent outages |
|
|
223
|
+
| Test was flaky or timing-dependent | Document the pattern; flaky tests erode confidence |
|
|
224
|
+
|
|
225
|
+
## Integration with other skills and agents
|
|
226
|
+
|
|
227
|
+
| Skill / agent | Interaction |
|
|
228
|
+
|---|---|
|
|
229
|
+
| `support-debug` | Invokes this skill after a successful fix |
|
|
230
|
+
| `deliver-db-migration` | Records migration-related lessons |
|
|
231
|
+
| `deliver-deploy` | Records deployment-related lessons |
|
|
232
|
+
| `deliver-onboarding` | Reads `aiwiki/gotchas/` to populate troubleshooting sections |
|
|
233
|
+
| `support-skill-validator` | Validates promoted rules at the approve step (Step 6) |
|
|
234
|
+
| `gotcha-hunter` (agent) | Reads `aiwiki/gotchas/` and surfaces diff-relevant entries to reviewers; never writes |
|
|
235
|
+
| `support-wiki-lint` | Validates frontmatter + sections on every write |
|
|
236
|
+
| `support-dream` | At phase-close / PreCompact: consolidates raw entries, may merge similar gotchas, prunes retired entries (writes proposals to `aiwiki/proposed/{dream_id}/` for user review) |
|
|
237
|
+
| `/evolve` command | Reads gotchas to identify skill improvement opportunities |
|
|
238
|
+
|
|
239
|
+
## Quick reference
|
|
240
|
+
|
|
241
|
+
| Step | Action | Output |
|
|
242
|
+
|---|---|---|
|
|
243
|
+
| 1. Extract | What broke / root cause / prevention | Three-part lesson |
|
|
244
|
+
| 2. Classify | Project or global? | Storage location chosen |
|
|
245
|
+
| 3. Search | Existing matching gotcha? | Bump `occurrences` instead of writing duplicate |
|
|
246
|
+
| 4. Write | Schema-aligned page with required frontmatter + 5 sections | `aiwiki/gotchas/{YYYY-MM-DD}-{slug}.md` (`status: active`) |
|
|
247
|
+
| 5. Auto-promote | 1 → `active`; 2 → `watch`; 3 → `promotion-pending` + `proposed_rule:` block | Awaits session-start review |
|
|
248
|
+
| 6. Session-start review | Approve / defer / reject the proposed rule | `promoted-to-rule`, deferred (stays `promotion-pending`), or `rejected` |
|
|
249
|
+
| 7. Retire (when no longer applies) | Set `status: retired` | Kept as searchable history |
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: support-runtime-reachability
|
|
3
|
+
description: "Use to verify that every export in the slice diff has a production caller — the runtime-reach gate. Catches orphan exports (code defined but never reached at runtime) before the slice closes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Support: Runtime Reachability
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
An export with no production caller is wiring debt: code that exists, passes its own tests against mocks, and ships unreached by production. Pattern review can't catch this — each file looks correct in isolation. This skill walks the slice diff, finds the exports it introduced, and proves each one is actually called.
|
|
11
|
+
|
|
12
|
+
**Core principle:** wiring is reachability. If production never calls it, it doesn't exist.
|
|
13
|
+
|
|
14
|
+
**Announce at start:** "I'm using the support-runtime-reachability skill to verify slice exports are wired."
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
- Per-slice gate after `build-tdd` completes — writes the `runtime-reach` gate result on the slice.
|
|
19
|
+
- Before invoking `quality-code-review`'s pattern-conformance pass.
|
|
20
|
+
- On-demand when investigating "code shipped but doesn't run".
|
|
21
|
+
|
|
22
|
+
**Do NOT skip when:**
|
|
23
|
+
- The slice "feels small" — the most common orphans are tiny (a hook, a route, a handler).
|
|
24
|
+
- Tests pass — mocked tests prove behavior under test, not under production wiring.
|
|
25
|
+
- A reviewer already approved the diff — pattern review and reachability are different bug classes.
|
|
26
|
+
|
|
27
|
+
## Scope
|
|
28
|
+
|
|
29
|
+
Catches **export-level orphans** in TS/JS and Python: a top-level `export` / `def` / `class` with no production call site and no escape-hatch annotation. Other failure classes are someone else's job:
|
|
30
|
+
|
|
31
|
+
| Failure | Owner |
|
|
32
|
+
|---|---|
|
|
33
|
+
| No-op stubs (function called, body empty) | `craft-reviewer` Pass 2 |
|
|
34
|
+
| Internal binding misses (handler not bound to JSX prop) | human review |
|
|
35
|
+
| Method-on-object misses (`store.setUser` never called, where `store` is the export) | human review |
|
|
36
|
+
| Behavioral completeness (caller exists, logic incomplete) | behavioral review |
|
|
37
|
+
| Transitive runtime unreachability (caller exists, but its calling path is dead) | the `quality-test-execution` phase |
|
|
38
|
+
|
|
39
|
+
Do not try to fold these into the runtime-reach result.
|
|
40
|
+
|
|
41
|
+
## I/O Contract
|
|
42
|
+
|
|
43
|
+
| Field | Value |
|
|
44
|
+
|---|---|
|
|
45
|
+
| **Requires** | Slice diff file list, manifest path |
|
|
46
|
+
| **Produces** | `runtime-reach` gate result (pass / fail with orphan list) |
|
|
47
|
+
| **Feeds into** | `quality-code-review` (Pass 2 + reachability), slice-close gate |
|
|
48
|
+
| **Updates manifest** | `slice_graph.slices.<id>.gates.runtime-reach.{status, gate-passed}` |
|
|
49
|
+
|
|
50
|
+
## Process
|
|
51
|
+
|
|
52
|
+
### Step 0: locate inputs
|
|
53
|
+
|
|
54
|
+
Discover what the script needs before invoking it. Each input has a fallback if the primary source isn't available.
|
|
55
|
+
|
|
56
|
+
| Input | How to find |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Repo root | `git rev-parse --show-toplevel`, or `${CLAUDE_PROJECT_DIR}` if set. |
|
|
59
|
+
| Manifest path | The single in-progress manifest under `.forge/work/*/*/manifest.yaml`. If multiple, ask the user which slice graph to validate against. |
|
|
60
|
+
| Current slice id | `slice_graph.current_slice` field of that manifest. If the manifest has no `slice_graph` block, surface the gap and stop — this gate has nothing to attach its result to. |
|
|
61
|
+
| Slice-parent ref | `slice_graph.slices.<current>.depends_on[0]`'s commit pointer if recorded; otherwise fall back to `origin/main`. If the repo has no `origin/main`, ask the user which ref to diff against. |
|
|
62
|
+
| Script path | `<repo-root>/.claude/skills/support-runtime-reachability/scripts/check.mjs`. If missing, the skill isn't installed in this project — surface the gap. |
|
|
63
|
+
|
|
64
|
+
### Step 1: collect slice diff files
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git -C <repo-root> diff --name-only <slice-parent>...HEAD \
|
|
68
|
+
-- '*.ts' '*.tsx' '*.js' '*.jsx' '*.mjs' '*.cjs' '*.py'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Skip deleted files. If the diff is empty (slice has no code changes), the gate passes trivially with `exports_found: 0`.
|
|
72
|
+
|
|
73
|
+
### Step 2: invoke the check script
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
node "<repo-root>/.claude/skills/support-runtime-reachability/scripts/check.mjs" \
|
|
77
|
+
--files <comma-separated-paths-from-step-1> \
|
|
78
|
+
--root "<repo-root>"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Output: JSON to stdout, exit 0 on success and exit 2 on internal error. The `exports` array reports per-export production callers, test callers, and any escape-hatch annotation found.
|
|
82
|
+
|
|
83
|
+
### Step 3: cross-check annotations against the manifest
|
|
84
|
+
|
|
85
|
+
The script reports what it sees; you decide validity using the slice graph.
|
|
86
|
+
|
|
87
|
+
**Decision rules:**
|
|
88
|
+
|
|
89
|
+
| Script reports | Manifest cross-check | Verdict |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `production_callers ≥ 1` | — | reachable |
|
|
92
|
+
| `production_callers = 0`, `annotation = null` | — | **orphan** |
|
|
93
|
+
| `annotation.kind = "untraceable"`, `value` non-empty | — | annotated, pass |
|
|
94
|
+
| `annotation.kind = "untraceable"`, `value` empty/whitespace | — | **malformed annotation** |
|
|
95
|
+
| `annotation.kind = "gated-pending"`, slice exists, status ∉ {complete} | — | annotated, pass |
|
|
96
|
+
| `annotation.kind = "gated-pending"`, slice missing OR status `complete` | — | **stale annotation** |
|
|
97
|
+
|
|
98
|
+
### Step 4: write the gate result
|
|
99
|
+
|
|
100
|
+
| Outcome | Manifest write |
|
|
101
|
+
|---|---|
|
|
102
|
+
| All exports reachable or validly annotated | `gates.runtime-reach: { status: complete, gate-passed: true }` |
|
|
103
|
+
| Any orphan / stale / malformed | `gates.runtime-reach: { status: complete, gate-passed: false }` |
|
|
104
|
+
|
|
105
|
+
### Step 5: report
|
|
106
|
+
|
|
107
|
+
If pass: one line — `runtime-reach: <N> exports checked, all wired.`
|
|
108
|
+
|
|
109
|
+
If fail: structured report:
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
## runtime-reach: FAILED (<N> findings)
|
|
113
|
+
|
|
114
|
+
### Orphan exports
|
|
115
|
+
1. `src/handlers/cases.ts:3` exports `casesRouter` (const)
|
|
116
|
+
Fix: wire it (e.g. `app.use('/cases', casesRouter)`), annotate `// gated-pending: <slice-id>`, or delete.
|
|
117
|
+
|
|
118
|
+
### Stale gated-pending
|
|
119
|
+
2. `src/future.ts:5` exports `futureHandler` annotated `// gated-pending: phase-2-wiring`,
|
|
120
|
+
but slice `phase-2-wiring` is `complete`. Wire it now.
|
|
121
|
+
|
|
122
|
+
### Malformed untraceable
|
|
123
|
+
3. `src/lazy.ts:2` exports `lazy` annotated `// untraceable:` with no rationale.
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The user fixes; re-run.
|
|
127
|
+
|
|
128
|
+
## Annotations
|
|
129
|
+
|
|
130
|
+
Place on the line immediately preceding the export, or trailing on the same line:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
// gated-pending: <slice-id>
|
|
134
|
+
export function futureHandler() { ... }
|
|
135
|
+
|
|
136
|
+
export const lateMount = ...; // gated-pending: phase-2-wiring
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
# gated-pending: phase-2-wiring
|
|
141
|
+
def future_handler():
|
|
142
|
+
pass
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
| Annotation | Use when |
|
|
146
|
+
|---|---|
|
|
147
|
+
| `// gated-pending: <slice-id>` | Export is intentionally orphan in this slice; another (named, non-complete) slice will wire it. |
|
|
148
|
+
| `// untraceable: <rationale>` | Export is consumed via mechanism the gate can't see: framework auto-discovery (Next.js routes), decorator mounts (NestJS, Spring), reflection-based loaders, defensive exports invoked only by upstream failures. |
|
|
149
|
+
|
|
150
|
+
Use line comments (`//` for TS/JS, `#` for Python). Block comments and annotations separated from the export by blank lines, JSDoc, or decorators are not parsed — place the annotation immediately above.
|
|
151
|
+
|
|
152
|
+
## When to Suspect a Finding
|
|
153
|
+
|
|
154
|
+
When the script's verdict disagrees with what you can verify by reading the code, the cause is usually one of these. Each row's "signal" is something you can observe in the diff or a quick grep — no script-internals knowledge required.
|
|
155
|
+
|
|
156
|
+
| Signal in the code | Likely cause | Fix |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| Script reports orphan, but you can grep a usage in a file that imports via `@/...`, `~/...`, or a non-relative path other than a known npm package | Path-aliased import — script can't resolve the alias to the export's file | Annotate `// untraceable: path-alias-consumer` |
|
|
159
|
+
| Script reports orphan, but the only usage is inside an `import('./X')` call | Dynamic import not detected | Annotate `// untraceable: dynamic-import` |
|
|
160
|
+
| Script reports orphan on a Next.js route, NestJS controller, Spring-annotated handler, or similar framework-mounted file | Framework auto-discovery — no explicit caller exists | Annotate `// untraceable: framework-mounted` |
|
|
161
|
+
| Script reports orphan, but you can grep `export * from '<path-resolving-to-this-file>'` in a re-export module | Wildcard re-export not followed | Convert to a named re-export (`export { name } from ...`), or annotate |
|
|
162
|
+
| Two source files in the diff both export the same identifier name | Same-name across modules — caller could be credited to the wrong export | Read the script output's `production_callers[].file` to confirm which export the call resolves to; restructure if needed |
|
|
163
|
+
| Script reports a caller, but the caller file both imports `name` AND declares its own `const name = ...` / `function name(...)` | Local shadow — the call resolves to the local declaration, not the import | Rename the local; the script's name-based fallback can't distinguish shadows |
|
|
164
|
+
|
|
165
|
+
The script's other constraints: regex (not AST); ESM only (no CommonJS `module.exports`); commented-out callers don't count (line comments are stripped).
|
|
166
|
+
|
|
167
|
+
## Red Flags
|
|
168
|
+
|
|
169
|
+
**Never:**
|
|
170
|
+
- Add a no-op caller (`useless();`) to satisfy reachability — that's gaming, not wiring.
|
|
171
|
+
- Annotate every orphan as `untraceable` to silence the gate. High annotation density signals architecture problems, not gate problems.
|
|
172
|
+
- Suppress findings to make the slice look clean.
|
|
173
|
+
|
|
174
|
+
**Always:**
|
|
175
|
+
- Resolve orphans before closing the slice.
|
|
176
|
+
- Re-run the script after every fix attempt.
|
|
177
|
+
- Annotate genuine framework-mounted exports so the next reviewer doesn't relitigate.
|
|
178
|
+
|
|
179
|
+
## Integration
|
|
180
|
+
|
|
181
|
+
| Caller | When |
|
|
182
|
+
|---|---|
|
|
183
|
+
| `quality-code-review` | After Pass 1 safety and Pass 2 craft, before Codex adversarial cross-check. |
|
|
184
|
+
| `/feature` and `/refactor` slice-close | Per-slice gate. |
|
|
185
|
+
| Ad-hoc | When a reviewer suspects orphan code. |
|
|
186
|
+
|
|
187
|
+
| Pairs with | For |
|
|
188
|
+
|---|---|
|
|
189
|
+
| `craft-reviewer` | Stubs the reachability gate accepts as called-but-empty. |
|
|
190
|
+
| `verify-manifest` | Validates the slice graph this skill cross-references. |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { doStuff } from './internal';
|