mercury-agent 0.4.22 → 0.4.24

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.
Files changed (60) hide show
  1. package/docs/ARCHITECTURE.md +30 -0
  2. package/docs/DESIGN.md +42 -0
  3. package/docs/ROADMAP.md +41 -0
  4. package/docs/VISION.md +32 -0
  5. package/docs/archive/.gitkeep +0 -0
  6. package/docs/backlog/.gitkeep +0 -0
  7. package/docs/bugs/.gitkeep +0 -0
  8. package/docs/bugs/bwrap-privileged-linux-docker.md +140 -0
  9. package/docs/bugs/registry-pull-no-local-fallback.md +168 -0
  10. package/docs/debug/major/.gitkeep +0 -0
  11. package/docs/debug/minor/.gitkeep +0 -0
  12. package/docs/debug/moderate/.gitkeep +0 -0
  13. package/docs/html-slides/.gitkeep +0 -0
  14. package/docs/ideas/.gitkeep +0 -0
  15. package/docs/in-progress/.gitkeep +0 -0
  16. package/docs/notes/.gitkeep +0 -0
  17. package/docs/pending-updates/.gitkeep +0 -0
  18. package/docs/runbooks/publish-checklist.md +8 -0
  19. package/docs/templates/TEMPLATE-AUTOPILOT-CONFIG.yaml +35 -0
  20. package/docs/templates/TEMPLATE-BUG.md +71 -0
  21. package/docs/templates/TEMPLATE-CI.yml +25 -0
  22. package/docs/templates/TEMPLATE-DECISIONS.md +11 -0
  23. package/docs/templates/TEMPLATE-FEATURE.md +127 -0
  24. package/docs/templates/TEMPLATE-GOAL.md +31 -0
  25. package/docs/templates/TEMPLATE-IDEA.md +31 -0
  26. package/docs/templates/TEMPLATE-NOTE.md +27 -0
  27. package/docs/templates/TEMPLATE-ROADMAP.md +21 -0
  28. package/examples/extensions/pinchtab/index.ts +1 -1
  29. package/package.json +1 -1
  30. package/src/adapters/whatsapp.ts +635 -635
  31. package/src/agent/container-entry.ts +66 -12
  32. package/src/agent/container-runner.ts +18 -12
  33. package/src/agent/model-capabilities.ts +231 -231
  34. package/src/bridges/discord.ts +178 -178
  35. package/src/bridges/slack.ts +179 -179
  36. package/src/bridges/teams.ts +162 -162
  37. package/src/bridges/telegram.ts +579 -579
  38. package/src/cli/mercury.ts +2587 -2585
  39. package/src/cli/whatsapp-auth.ts +263 -263
  40. package/src/config.ts +316 -316
  41. package/src/core/commands.ts +110 -110
  42. package/src/core/permissions.ts +196 -196
  43. package/src/core/router.ts +204 -204
  44. package/src/core/routes/chat.ts +175 -175
  45. package/src/core/routes/dashboard.ts +2493 -2493
  46. package/src/core/routes/messages.ts +37 -37
  47. package/src/core/routes/mutes.ts +95 -95
  48. package/src/core/routes/roles.ts +135 -135
  49. package/src/core/runtime.ts +1508 -1508
  50. package/src/core/task-scheduler.ts +139 -139
  51. package/src/extensions/catalog.ts +117 -117
  52. package/src/extensions/hooks.ts +161 -161
  53. package/src/extensions/installer.ts +306 -306
  54. package/src/extensions/loader.ts +271 -271
  55. package/src/extensions/permission-guard.ts +52 -52
  56. package/src/server.ts +391 -391
  57. package/src/storage/db.ts +1684 -1687
  58. package/src/storage/pi-auth.ts +95 -95
  59. package/src/tts/azure.ts +52 -52
  60. package/src/tts/synthesize.ts +133 -133
@@ -0,0 +1,30 @@
1
+ # {Project Name} — Architecture Reference
2
+
3
+ > On-demand reference. Do not auto-load. Read when a task is cross-cutting or you need to understand inter-package data flow.
4
+
5
+ ## Packages
6
+
7
+ | Package | Purpose | Stack | Runs On |
8
+ |---------|---------|-------|---------|
9
+ | `{package}/` | {purpose} | {stack} | {where it runs} |
10
+
11
+ ## Deployment Topology
12
+
13
+ ```
14
+ {ASCII diagram of your deployment — servers, services, databases, CDNs, etc.}
15
+ ```
16
+
17
+ ## Data Flow
18
+
19
+ > How data moves between packages, services, and external systems. Include request paths, event flows, and storage interactions.
20
+
21
+ ## Key Invariants
22
+
23
+ > Rules that must always hold true across the system. Breaking these causes cascading failures.
24
+
25
+ - {Invariant 1}
26
+ - {Invariant 2}
27
+
28
+ ## Extension Points
29
+
30
+ > Where the system is designed to be extended — plugin interfaces, hook points, configuration surfaces.
package/docs/DESIGN.md ADDED
@@ -0,0 +1,42 @@
1
+ # {Project Name} — Design System
2
+
3
+ > Fill this in if your project has a UI. Skip if it's a backend-only project.
4
+
5
+ ## 1. Visual Theme
6
+
7
+ > Design principles — what the UI should feel like.
8
+
9
+ ## 2. Color Roles
10
+
11
+ > CSS variable inventory. All colors must be defined as variables — never hardcode hex in component files.
12
+
13
+ | Token | Dark Value | Light Value | Role |
14
+ |-------|-----------|-------------|------|
15
+ | `--bg` | {hex} | {hex} | Page background |
16
+ | `--surface` | {hex} | {hex} | Card/panel background |
17
+ | `--text` | {hex} | {hex} | Primary text |
18
+ | `--muted` | {hex} | {hex} | Secondary text |
19
+ | `--accent` | {hex} | {hex} | Interactive elements |
20
+ | `--border` | {hex} | {hex} | Borders and dividers |
21
+ | `--color-success` | {hex} | {hex} | Success states |
22
+ | `--color-error` | {hex} | {hex} | Error states |
23
+ | `--color-warning` | {hex} | {hex} | Warning states |
24
+
25
+ ## 3. Typography
26
+
27
+ > Font families, sizes, weights. Which fonts for which contexts.
28
+
29
+ ## 4. Layout & Spacing
30
+
31
+ > Grid system, breakpoints, spacing scale. Include RTL/logical property conventions if applicable.
32
+
33
+ ## 5. Components
34
+
35
+ > Component conventions — buttons, inputs, cards, modals, status indicators, etc.
36
+
37
+ ## 6. Hard Rules
38
+
39
+ > Violations block merge. Examples:
40
+ > - No hardcoded hex colors in component files — use CSS variables
41
+ > - No physical CSS properties (`left`/`right`) — use logical properties
42
+ > - All interactive elements must have visible focus rings
@@ -0,0 +1,41 @@
1
+ # {Project Name} — Roadmap
2
+
3
+ Single source of truth for priority. Rule: ≤15 min/week to maintain.
4
+
5
+ ---
6
+
7
+ ## Inbox
8
+
9
+ > Uncategorized ideas. Triage into Now / Next / Later or drop.
10
+
11
+ | Item | Doc | Notes |
12
+ |------|-----|-------|
13
+ | — | — | — |
14
+
15
+ ## Now
16
+
17
+ > Max 2 items. What you're actively working on.
18
+
19
+ | Item | Doc | Started | Notes |
20
+ |------|-----|---------|-------|
21
+ | — | — | — | — |
22
+
23
+ ## Next
24
+
25
+ | # | Item | Doc | Depends on | Why now |
26
+ |---|------|-----|-----------|---------|
27
+ | 1 | **autonomous-planning-tier** | [doc](backlog/autonomous-planning-tier.md) | — | Let agents decompose ideas, keep human gate |
28
+
29
+ ## Later
30
+
31
+ | Item | Doc | Notes |
32
+ |------|-----|-------|
33
+ | — | — | — |
34
+
35
+ ---
36
+
37
+ ## Shipped
38
+
39
+ | Item | Shipped | What |
40
+ |------|---------|------|
41
+ | — | — | — |
package/docs/VISION.md ADDED
@@ -0,0 +1,32 @@
1
+ # {Project Name} — Product Vision
2
+
3
+ ## What {Project Name} Is
4
+
5
+ > One-sentence pitch.
6
+
7
+ ## Target User
8
+
9
+ > Who is this for? Be specific — role, context, what they're trying to accomplish.
10
+
11
+ ## What Makes {Project Name} Different
12
+
13
+ | Differentiator | Why it matters |
14
+ |---------------|----------------|
15
+ | {differentiator} | {why} |
16
+
17
+ ## Non-Goals
18
+
19
+ > Explicit list of what this project does NOT try to be. Helps filter feature requests.
20
+
21
+ - {Non-goal 1}
22
+ - {Non-goal 2}
23
+
24
+ ## Guiding Questions for New Ideas
25
+
26
+ > Use these to evaluate whether a feature idea fits the product:
27
+
28
+ 1. Does this serve the target user directly?
29
+ 2. Does this align with the differentiators above?
30
+ 3. Does this conflict with any non-goal?
31
+ 4. Can the user benefit from this without configuration or documentation?
32
+ 5. Would removing this make the product worse for the target user?
File without changes
File without changes
File without changes
@@ -0,0 +1,140 @@
1
+ # Bug: bwrap fails to mount /proc on Linux Docker Engine (non-Desktop)
2
+
3
+ **Severity:** P1 — blocks all agent responses on standard Linux Docker hosts
4
+ **Affected:** Linux servers running Docker Engine (not Docker Desktop, not gVisor)
5
+ **File:** `src/agent/container-runner.ts`, bwrap compat branch (~line 980)
6
+
7
+ ## Symptom
8
+
9
+ ```
10
+ Container error: Container failed (exit code 1): Error: pi CLI failed (1):
11
+ bwrap: Can't mount proc on /newroot/proc: Operation not permitted
12
+ ```
13
+
14
+ Happens on Linux servers (e.g. Hetzner, AWS EC2, DigitalOcean) running
15
+ Docker Engine with the default kernel config. The existing bwrap Docker compat
16
+ flags (`seccomp=unconfined`, `apparmor=unconfined`, `CAP_SYS_ADMIN`) are not
17
+ sufficient for bwrap to mount `/proc` inside the container.
18
+
19
+ ## Root cause
20
+
21
+ On Linux Docker Engine, the default seccomp + AppArmor + capability set does
22
+ not allow `mount(2)` inside a user namespace, even with:
23
+ - `--security-opt seccomp=unconfined`
24
+ - `--security-opt apparmor=unconfined`
25
+ - `--cap-add SYS_ADMIN`
26
+
27
+ This is a known limitation: Docker's default behavior strips many mount-related
28
+ permissions that `--privileged` restores (device cgroup rules, all capabilities,
29
+ full /sys and /proc access).
30
+
31
+ **Verified:** `--privileged` makes bwrap work:
32
+ ```bash
33
+ # Fails:
34
+ docker run --rm --entrypoint bwrap \
35
+ --security-opt seccomp=unconfined --security-opt apparmor=unconfined \
36
+ --cap-add SYS_ADMIN mercury-agent:latest \
37
+ --ro-bind /usr /usr --proc /proc --dev /dev --unshare-pid echo hello
38
+ # → bwrap: Can't mount proc on /newroot/proc: Operation not permitted
39
+
40
+ # Works:
41
+ docker run --rm --entrypoint bwrap --privileged mercury-agent:latest \
42
+ --ro-bind /usr /usr --proc /proc --dev /dev --unshare-pid echo hello
43
+ # → execvp echo: No such file or directory (bwrap ran fine, echo just not in /usr)
44
+ ```
45
+
46
+ ## Fix
47
+
48
+ ### Option A: Add `--privileged` flag to bwrap compat (recommended short-term)
49
+
50
+ In `container-runner.ts` (~line 985), replace the current compat flags with
51
+ `--privileged` when `containerBwrapDockerCompat` is explicitly set to `true`:
52
+
53
+ ```typescript
54
+ } else if (this.config.containerBwrapDockerCompat || isDockerDesktop()) {
55
+ logger.info("Enabling bwrap Docker compat (seccomp/apparmor/SYS_ADMIN)", {
56
+ configFlag: this.config.containerBwrapDockerCompat,
57
+ dockerDesktop: isDockerDesktop(),
58
+ });
59
+ if (this.config.containerBwrapDockerCompat) {
60
+ // Explicit opt-in: Linux Docker Engine needs --privileged for bwrap
61
+ // to mount /proc inside a user namespace. The finer-grained flags
62
+ // (seccomp=unconfined + apparmor=unconfined + SYS_ADMIN) are not
63
+ // sufficient on standard Linux kernels.
64
+ args.push("--privileged");
65
+ } else {
66
+ // Docker Desktop auto-detection: use the lighter-weight flags
67
+ // (Docker Desktop's VM has a more permissive kernel config)
68
+ args.push(
69
+ "--security-opt",
70
+ "seccomp=unconfined",
71
+ "--security-opt",
72
+ "apparmor=unconfined",
73
+ "--cap-add",
74
+ "SYS_ADMIN",
75
+ );
76
+ }
77
+ }
78
+ ```
79
+
80
+ This keeps the lighter flags for Docker Desktop (where they work) and uses
81
+ `--privileged` only when the user explicitly opted in via
82
+ `MERCURY_CONTAINER_BWRAP_DOCKER_COMPAT=true`.
83
+
84
+ ### Option B: Add a separate `MERCURY_CONTAINER_PRIVILEGED` config flag
85
+
86
+ If you prefer to keep the compat flag behavior unchanged, add a new flag:
87
+
88
+ In `config.ts`, add:
89
+ ```typescript
90
+ containerPrivileged: boolean; // default: false
91
+ ```
92
+
93
+ In `config-file.ts`, add the env mapping:
94
+ ```typescript
95
+ containerPrivileged: "MERCURY_CONTAINER_PRIVILEGED",
96
+ ```
97
+
98
+ In `container-runner.ts`, after the existing compat block:
99
+ ```typescript
100
+ if (this.config.containerPrivileged) {
101
+ args.push("--privileged");
102
+ }
103
+ ```
104
+
105
+ User sets `MERCURY_CONTAINER_PRIVILEGED=true` in `.env`.
106
+
107
+ ### Option C: Auto-detect and use --privileged as fallback
108
+
109
+ Run a probe container on startup to test if bwrap works with the lighter
110
+ flags. If it fails, automatically escalate to `--privileged` and log a
111
+ warning. This is the most user-friendly but adds startup latency.
112
+
113
+ ## Workaround (immediate)
114
+
115
+ Until the fix is in place, users can work around this by manually running
116
+ mercury with Docker's `--privileged` flag. However, since `mercury run`
117
+ doesn't expose extra Docker args, the only current workaround is to
118
+ modify `MERCURY_AGENT_IMAGE` to point to a locally-built image and skip
119
+ bwrap entirely by setting `MERCURY_CONTAINER_RUNTIME=runsc` (requires
120
+ gVisor installed), or to apply the code change.
121
+
122
+ ## Linux server setup checklist
123
+
124
+ These sysctl settings are needed regardless of the fix above:
125
+
126
+ ```bash
127
+ sysctl -w kernel.unprivileged_userns_clone=1
128
+ sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
129
+ cat > /etc/sysctl.d/99-bubblewrap.conf << 'EOF'
130
+ kernel.unprivileged_userns_clone=1
131
+ kernel.apparmor_restrict_unprivileged_userns=0
132
+ EOF
133
+ ```
134
+
135
+ ## How to verify
136
+
137
+ 1. Set `MERCURY_CONTAINER_BWRAP_DOCKER_COMPAT=true` in `.env`
138
+ 2. Start mercury: `pm2 restart all` or `mercury service install`
139
+ 3. Run: `mercury chat 'hello'`
140
+ 4. Check logs — should see successful container run, no bwrap errors
@@ -0,0 +1,168 @@
1
+ # Bug: mercury run fails when registry pull fails but local build exists
2
+
3
+ **Severity:** P1 — blocks users who build locally but have a registry image configured
4
+ **Introduced in:** 0.4.22 (commit 75e8e71)
5
+ **File:** `src/cli/mercury.ts`, `runAction()` (~line 187)
6
+
7
+ ## Symptom
8
+
9
+ ```
10
+ $ mercury build # succeeds → mercury-agent:latest exists locally
11
+ $ mercury run
12
+ Image 'ghcr.io/avishai-tsabari/mercury-agent:latest' not found locally, pulling...
13
+ Error response from daemon: unauthorized
14
+
15
+ Error: Failed to pull 'ghcr.io/avishai-tsabari/mercury-agent:latest'.
16
+ If this is a private registry, authenticate first:
17
+ docker login ghcr.io
18
+ ```
19
+
20
+ The user has a working local image (`mercury-agent:latest`) from `mercury build`,
21
+ but `mercury run` exits with an error because the configured registry image
22
+ can't be pulled (private registry, no auth, offline, etc.).
23
+
24
+ ## Root cause
25
+
26
+ The 0.4.22 change replaced the local-fallback logic with auto-pull. The old
27
+ code tried `mercury-agent:latest` as a fallback when the configured image
28
+ wasn't found. The new code attempts `docker pull` and hard-exits on failure —
29
+ it never checks whether a locally built image exists.
30
+
31
+ ### Before (0.4.21)
32
+
33
+ ```
34
+ configured image not found?
35
+ → try mercury-agent:latest locally
36
+ → found? use it (with warning)
37
+ → not found? error: pull or build
38
+ ```
39
+
40
+ ### After (0.4.22)
41
+
42
+ ```
43
+ configured image not found?
44
+ → is registry image? attempt pull
45
+ → pull fails? hard exit ← BUG: should fall back to local
46
+ → not registry? error: run mercury build
47
+ ```
48
+
49
+ ## Fix
50
+
51
+ After a failed pull of a registry image, check if `mercury-agent:latest`
52
+ exists locally before giving up. If it does, use it with a warning.
53
+
54
+ ### Implementation (lines ~187–213 of `src/cli/mercury.ts`)
55
+
56
+ Replace the current block:
57
+
58
+ ```typescript
59
+ if (imageCheck.status !== 0) {
60
+ const isRegistryImage = imageName.includes("/");
61
+ if (isRegistryImage) {
62
+ console.log(`Image '${imageName}' not found locally, pulling...`);
63
+ const pull = spawnSync("docker", ["pull", imageName], {
64
+ stdio: "inherit",
65
+ });
66
+ if (pull.signal) {
67
+ process.exit(1);
68
+ }
69
+ if (pull.status !== 0) {
70
+ const firstSegment = imageName.split("/")[0];
71
+ const registry = firstSegment.includes(".")
72
+ ? firstSegment
73
+ : "docker.io";
74
+ console.error(`\nError: Failed to pull '${imageName}'.`);
75
+ console.error(
76
+ "If this is a private registry, authenticate first:\n" +
77
+ ` docker login ${registry}`,
78
+ );
79
+ process.exit(1);
80
+ }
81
+ } else {
82
+ console.error(`Error: Container image '${imageName}' not found.`);
83
+ console.error("Run 'mercury build' to build it.");
84
+ process.exit(1);
85
+ }
86
+ }
87
+ ```
88
+
89
+ With:
90
+
91
+ ```typescript
92
+ if (imageCheck.status !== 0) {
93
+ const isRegistryImage = imageName.includes("/");
94
+ let resolved = false;
95
+
96
+ if (isRegistryImage) {
97
+ console.log(`Image '${imageName}' not found locally, pulling...`);
98
+ const pull = spawnSync("docker", ["pull", imageName], {
99
+ stdio: "inherit",
100
+ });
101
+ if (pull.signal) {
102
+ process.exit(1);
103
+ }
104
+ if (pull.status === 0) {
105
+ resolved = true;
106
+ }
107
+ }
108
+
109
+ // Fallback: if the configured image isn't available (pull failed, not a
110
+ // registry image, or never pulled), try the local build tag.
111
+ if (!resolved) {
112
+ const localTag = "mercury-agent:latest";
113
+ if (imageName !== localTag) {
114
+ const localCheck = spawnSync("docker", ["image", "inspect", localTag], {
115
+ stdio: "pipe",
116
+ });
117
+ if (localCheck.status === 0) {
118
+ console.log(
119
+ `\nℹ️ Using locally built ${localTag} (configured image unavailable)\n`,
120
+ );
121
+ process.env.MERCURY_AGENT_IMAGE = localTag;
122
+ resolved = true;
123
+ }
124
+ }
125
+ }
126
+
127
+ if (!resolved) {
128
+ if (isRegistryImage) {
129
+ const firstSegment = imageName.split("/")[0];
130
+ const registry = firstSegment.includes(".")
131
+ ? firstSegment
132
+ : "docker.io";
133
+ console.error(`\nError: Failed to pull '${imageName}'.`);
134
+ console.error(
135
+ "If this is a private registry, authenticate first:\n" +
136
+ ` docker login ${registry}\n` +
137
+ "Or build locally:\n" +
138
+ " mercury build",
139
+ );
140
+ } else {
141
+ console.error(`Error: Container image '${imageName}' not found.`);
142
+ console.error("Run 'mercury build' to build it.");
143
+ }
144
+ process.exit(1);
145
+ }
146
+ }
147
+ ```
148
+
149
+ ### Behavior after fix
150
+
151
+ ```
152
+ configured image not found?
153
+ → is registry image? attempt pull
154
+ → pull succeeds? use it ✓
155
+ → pull fails? continue to fallback
156
+ → try mercury-agent:latest locally
157
+ → found? use it (with info message) ✓
158
+ → not found? error with both suggestions (login + build) ✓
159
+ ```
160
+
161
+ ## How to verify
162
+
163
+ 1. Build locally: `mercury build`
164
+ 2. Ensure no GHCR auth: `docker logout ghcr.io`
165
+ 3. Set `.env` to `MERCURY_AGENT_IMAGE=ghcr.io/avishai-tsabari/mercury-agent:latest`
166
+ 4. Run `mercury run` — should fall back to local image with info message
167
+ 5. Remove local image: `docker rmi mercury-agent:latest`
168
+ 6. Run `mercury run` — should error with both `docker login` and `mercury build` suggestions
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+ # Publish Checklist
2
+
3
+ Before publishing a new version to npm:
4
+
5
+ 1. **`bun run check`** — typecheck + lint + tests
6
+ 2. **`mercury build`** — if you touched build path, Dockerfiles, or file-copy logic
7
+ 3. **`mercury init` + `mercury service install`** in a test project — if you touched CLI flow, config loading, or service management
8
+ 4. **Smoke test assistants** — send a message, verify they respond
@@ -0,0 +1,35 @@
1
+ # Autopilot Configuration
2
+ # Copy this file to docs/autopilot/config.yaml and customize.
3
+ # The orchestrator script reads this file each iteration.
4
+
5
+ gates:
6
+ max_iterations: 10 # stop after N iterations per session
7
+ max_features_without_review: 3 # stop after completing N features/bugs without human review
8
+ max_retries_same_task: 3 # skip a task after N failed attempts
9
+ iteration_timeout_minutes: 30 # kill a single execute phase after this long
10
+
11
+ risk:
12
+ sensitive_paths: # changes to these = immediate stop for review
13
+ - "**/auth/**"
14
+ - "**/migration*"
15
+ - "**/.env*"
16
+ - "**/schema*"
17
+ auto_stop_risk_threshold: 8 # risk_score >= this from assess = stop
18
+
19
+ scope:
20
+ allowed_actions: # which actions the autopilot may take
21
+ - implement_feature
22
+ - continue_feature
23
+ - fix_bug
24
+ - sync_docs
25
+ # - propose_decomposition # uncomment to enable autonomous planning (requires allow_autonomous_planning: true)
26
+ skip_slugs: # slugs to never touch autonomously
27
+ # - my-feature-slug
28
+
29
+ planning:
30
+ allow_autonomous_planning: false # when true, autopilot can decompose ideas into draft plans (requires propose_decomposition in allowed_actions)
31
+ # plans land as Status: Proposed and always stop for human review
32
+
33
+ notifications:
34
+ on_stop: console # "console" | "file" (future: "slack", "email")
35
+ decision_log: docs/autopilot/decision-log.md
@@ -0,0 +1,71 @@
1
+ # Bug: {Title}
2
+
3
+ **Status**: Open | In-Progress | Fixed
4
+ **Severity**: minor | moderate | major
5
+ **Slug**: {slug}
6
+ **Reported**: {YYYY-MM-DD}
7
+ **Last updated**: {YYYY-MM-DD}
8
+
9
+ ---
10
+
11
+ ## Summary
12
+
13
+ {One-sentence description of what's broken and where.}
14
+
15
+ ## Steps to Reproduce
16
+
17
+ 1.
18
+ 2.
19
+ 3.
20
+
21
+ ## Expected Behavior
22
+
23
+ {What should happen.}
24
+
25
+ ## Actual Behavior
26
+
27
+ {What actually happens. Include any error messages or observable symptoms.}
28
+
29
+ ## Impact
30
+
31
+ - {Who or what is affected, and how severely.}
32
+
33
+ ## Suspected Location
34
+
35
+ - {File path(s) or component(s) most likely responsible.}
36
+
37
+ ## Notes
38
+
39
+ - {Workarounds, related issues, env var context, etc.}
40
+
41
+ ---
42
+
43
+ ## Implementation Checklist
44
+
45
+ - [ ] Root cause identified
46
+ - [ ] Fix implemented
47
+ - [ ] `{your check command}` passes
48
+ - [ ] No secrets or `.env` files committed
49
+ - [ ] No unrelated files modified
50
+
51
+ ---
52
+
53
+ ## Post-Mortem
54
+
55
+ > Fill in after the fix is complete.
56
+
57
+ ### Investigation
58
+
59
+ {How you traced the bug — files read, code paths followed, assumptions tested.}
60
+
61
+ ### Root Cause
62
+
63
+ {Precise explanation of the defective code and why it caused the symptom.}
64
+
65
+ ### Fix
66
+
67
+ {What changed and why. Include file paths and key line references.}
68
+
69
+ ### Lessons
70
+
71
+ - {Takeaways applicable to future work — patterns to avoid, checks to add, etc.}
@@ -0,0 +1,25 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ check:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ # TODO: Add stack setup steps, e.g.:
16
+ # - uses: actions/setup-node@v4
17
+ # with: { node-version: 20 }
18
+ # - run: npm ci
19
+
20
+ - name: Run checks
21
+ run: |
22
+ # TODO: Paste your check command from .claude/project-checks.md
23
+ # Example: npm run typecheck && npm run lint && npm test
24
+ echo "CI not configured — fill in the check command above"
25
+ exit 1
@@ -0,0 +1,11 @@
1
+ # Decisions: {Goal Title}
2
+
3
+ **Goal**: [{goal-slug}](goal.md)
4
+
5
+ ## D-001: {Decision title}
6
+ - **Category:** tech-stack | architecture | scope | pattern | trade-off
7
+ - **Decided:** {what was chosen}
8
+ - **Alternatives considered:** {list}
9
+ - **Reasoning:** {why this choice}
10
+ - **Revisit if:** {condition that would invalidate this decision}
11
+ - **Used by:** {feature-slug-1}, {feature-slug-2}