opencode-thrum-pro 0.1.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/assets/commands/thrum-_deviations-protocol.md +87 -0
- package/assets/commands/thrum-_generator-idempotency-protocol.md +15 -0
- package/assets/commands/thrum-_project-rules-protocol.md +18 -0
- package/assets/commands/thrum-_snapshot-protocol.md +265 -0
- package/assets/commands/thrum-_stamp-protocol.md +112 -0
- package/assets/commands/thrum-_verify-before-write-protocol.md +27 -0
- package/assets/commands/thrum-inbox.md +22 -0
- package/assets/commands/thrum-load-context.md +17 -0
- package/assets/commands/thrum-overview.md +17 -0
- package/assets/commands/thrum-prime.md +30 -0
- package/assets/commands/thrum-quickstart.md +14 -0
- package/assets/commands/thrum-reply.md +28 -0
- package/assets/commands/thrum-restart-extended.md +195 -0
- package/assets/commands/thrum-restart.md +293 -0
- package/assets/commands/thrum-send.md +31 -0
- package/assets/commands/thrum-sleep-extended.md +186 -0
- package/assets/commands/thrum-sleep.md +212 -0
- package/assets/commands/thrum-team.md +12 -0
- package/assets/commands/thrum-update-project.md +259 -0
- package/assets/commands/thrum-wait.md +14 -0
- package/assets/skills/adversarial-critique/SKILL.md +242 -0
- package/assets/skills/brainstorm-queue-aware/SKILL.md +167 -0
- package/assets/skills/brainstorm-steward/SKILL.md +181 -0
- package/assets/skills/choosing-subagent-models/SKILL.md +244 -0
- package/assets/skills/closing-findings-while-warm/SKILL.md +104 -0
- package/assets/skills/configure-roles/SKILL.md +229 -0
- package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +205 -0
- package/assets/skills/coordinator-assessing-agent-completion/scan.py +117 -0
- package/assets/skills/coordinator-branch-split-on-block/SKILL.md +168 -0
- package/assets/skills/coordinator-context-monitoring/SKILL.md +674 -0
- package/assets/skills/coordinator-dispatching-work/SKILL.md +288 -0
- package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +522 -0
- package/assets/skills/coordinator-interacting-with-the-owner/SKILL.md +171 -0
- package/assets/skills/coordinator-maintaining-memory/SKILL.md +89 -0
- package/assets/skills/coordinator-managing-state-and-lifecycle/SKILL.md +192 -0
- package/assets/skills/coordinator-merging-code/SKILL.md +331 -0
- package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +442 -0
- package/assets/skills/coordinator-plan-reconcile-gate/SKILL.md +198 -0
- package/assets/skills/coordinator-post-restart-sweep/SKILL.md +135 -0
- package/assets/skills/coordinator-running-autonomous-feature-development/SKILL.md +199 -0
- package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +654 -0
- package/assets/skills/coordinator-running-review-cycles/SKILL.md +153 -0
- package/assets/skills/coordinator-single-responsibility-merge-gate/SKILL.md +14 -0
- package/assets/skills/diagnosing-fleet-and-daemon/SKILL.md +255 -0
- package/assets/skills/efficient-multi-agent-research/SKILL.md +177 -0
- package/assets/skills/fixing-documentation-errors/SKILL.md +258 -0
- package/assets/skills/implementer-maintaining-memory/SKILL.md +84 -0
- package/assets/skills/implementer-orchestrating-execution/SKILL.md +125 -0
- package/assets/skills/implementer-receiving-dispatch/SKILL.md +127 -0
- package/assets/skills/implementer-receiving-review-feedback/SKILL.md +125 -0
- package/assets/skills/implementer-status-and-handoff/SKILL.md +150 -0
- package/assets/skills/implementer-tdd-and-quality/SKILL.md +99 -0
- package/assets/skills/memory-audit-recover/SKILL.md +153 -0
- package/assets/skills/memory-curate/SKILL.md +139 -0
- package/assets/skills/memory-maintenance/SKILL.md +87 -0
- package/assets/skills/memory-read-discipline/SKILL.md +164 -0
- package/assets/skills/memory-search-advanced/SKILL.md +217 -0
- package/assets/skills/memory-write-discipline/SKILL.md +135 -0
- package/assets/skills/orchestrate/SKILL.md +795 -0
- package/assets/skills/persistent-watcher-archetype/SKILL.md +225 -0
- package/assets/skills/prime-agent/SKILL.md +92 -0
- package/assets/skills/project-hotpath-gate/SKILL.md +255 -0
- package/assets/skills/project-philosophy/SKILL.md +418 -0
- package/assets/skills/project-philosophy/resources/philosophy-template.md +155 -0
- package/assets/skills/project-philosophy/resources/reliability-class-library.md +653 -0
- package/assets/skills/project-setup/SKILL.md +1007 -0
- package/assets/skills/project-setup/resources/implementation-agent.md +826 -0
- package/assets/skills/researcher-answering-queries/SKILL.md +100 -0
- package/assets/skills/researcher-investigating/SKILL.md +152 -0
- package/assets/skills/researcher-maintaining-memory/SKILL.md +176 -0
- package/assets/skills/state-migration/SKILL.md +54 -0
- package/assets/skills/thrum/SKILL.md +161 -0
- package/assets/skills/thrum/resources/ANTI_PATTERNS.md +132 -0
- package/assets/skills/thrum/resources/BOUNDARIES.md +56 -0
- package/assets/skills/thrum/resources/CLI_REFERENCE.md +1066 -0
- package/assets/skills/thrum/resources/IDENTITY.md +49 -0
- package/assets/skills/thrum/resources/LISTENER_PATTERN.md +64 -0
- package/assets/skills/thrum/resources/MESSAGING.md +163 -0
- package/assets/skills/thrum/resources/TMUX_SESSIONS.md +118 -0
- package/assets/skills/thrum/resources/WORKTREES.md +117 -0
- package/assets/skills/thrum-memory/SKILL.md +138 -0
- package/assets/skills/trace-spec-to-plan/SKILL.md +104 -0
- package/assets/skills/trace-spec-to-plan/resources/sweep-agent-prompt.md +57 -0
- package/assets/skills/update-queue/SKILL.md +149 -0
- package/assets/skills/using-the-queue/SKILL.md +172 -0
- package/assets/skills/using-thrum-state/SKILL.md +104 -0
- package/assets/skills/verify-against-plan/SKILL.md +323 -0
- package/assets/skills/verify-against-source/SKILL.md +237 -0
- package/assets/skills/watcher-archetype/SKILL.md +84 -0
- package/assets/skills/writing-durable-markdown/SKILL.md +66 -0
- package/dist/hooks/block-sync-cd.d.ts +9 -0
- package/dist/hooks/block-sync-cd.js +71 -0
- package/dist/hooks/block-sync-cd.test.d.ts +1 -0
- package/dist/hooks/block-sync-cd.test.js +61 -0
- package/dist/hooks/shell-env.d.ts +8 -0
- package/dist/hooks/shell-env.js +22 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +25 -0
- package/dist/installer.d.ts +2 -0
- package/dist/installer.js +86 -0
- package/package.json +49 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project-philosophy
|
|
3
|
+
description: "Use when a project needs its implementation philosophy established or updated — the canonical doc at .thrum/philosophy.md defining anti-patterns, red flags, and project-specific rules that implementation agents read at task-start time. First invocation generates from project inspection; subsequent invocations reconcile against current project state and propose diffs."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Project Philosophy
|
|
7
|
+
|
|
8
|
+
## Canonical path
|
|
9
|
+
|
|
10
|
+
`.thrum/philosophy.md` — the single authoritative location. `project-setup` and
|
|
11
|
+
every implementation-agent prompt read from this path only. Non-standard paths
|
|
12
|
+
are handled by the fallback migration (documented below), not by moving the
|
|
13
|
+
canonical target.
|
|
14
|
+
|
|
15
|
+
## Run modes and dispatch order
|
|
16
|
+
|
|
17
|
+
On every invocation, dispatch in this order. Earlier branches short-circuit
|
|
18
|
+
later ones.
|
|
19
|
+
|
|
20
|
+
0. **Fallback migration** — runs first when `.thrum/philosophy.md` is absent. If
|
|
21
|
+
a legacy philosophy doc exists elsewhere in the repo, offer move/link/fresh
|
|
22
|
+
before generating anything new. If no legacy doc is found, fall through to
|
|
23
|
+
branch 1.
|
|
24
|
+
1. **First-run** (doc absent, no legacy doc or "fresh" chosen above) — generate
|
|
25
|
+
a new `.thrum/philosophy.md` from project inspection + interactive prompts
|
|
26
|
+
(documented below).
|
|
27
|
+
2. **Re-run-unchanged** (doc present, matches current project state) — report
|
|
28
|
+
"philosophy.md is current; no changes needed" and exit without writing.
|
|
29
|
+
3. **Re-run-evolved** (doc present, project has drifted) — compute a sectional
|
|
30
|
+
diff, present via `AskUserQuestion`, write only on confirmation.
|
|
31
|
+
|
|
32
|
+
Read the shared partial at the absolute path:
|
|
33
|
+
`claude-plugin/commands/_generator-idempotency-protocol.md`
|
|
34
|
+
|
|
35
|
+
> **Note: human-in-the-loop required.** This skill uses `AskUserQuestion` for
|
|
36
|
+
> first-run project-specific prompts, re-run-evolved diff approval, and
|
|
37
|
+
> fallback-migration three-way choice. It cannot run unattended in CI or any
|
|
38
|
+
> other non-interactive automation context. Invoke it only from a session that
|
|
39
|
+
> can answer prompts.
|
|
40
|
+
|
|
41
|
+
## Fallback migration
|
|
42
|
+
|
|
43
|
+
Runs before the First-run branch when `.thrum/philosophy.md` is absent. If the
|
|
44
|
+
user has a philosophy doc at a legacy path, offer a three-way choice rather than
|
|
45
|
+
ignoring it and generating a parallel doc.
|
|
46
|
+
|
|
47
|
+
### Step 1: Search for legacy philosophy docs
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
find . -type f \( -name "*philosophy*" -o -name "*anti-pattern*" -o -name "*implementation-standards*" -o -name "CONTRIBUTING.md" \) \
|
|
51
|
+
-not -path '*/node_modules/*' \
|
|
52
|
+
-not -path '*/.git/*' \
|
|
53
|
+
-not -path '*/dist/*' \
|
|
54
|
+
-not -path '*/build/*' \
|
|
55
|
+
2>/dev/null | head
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Common legacy locations: `dev-docs/implementation-philosophy.md`,
|
|
59
|
+
`docs/anti-patterns.md`, `CONTRIBUTING.md` with an anti-patterns section.
|
|
60
|
+
|
|
61
|
+
If zero candidates: fall through to First-run. If one or more candidates:
|
|
62
|
+
present the choice.
|
|
63
|
+
|
|
64
|
+
### Step 2: Present three-way choice via `AskUserQuestion`
|
|
65
|
+
|
|
66
|
+
Question: "Found existing philosophy doc at `<path>`. What should I do?"
|
|
67
|
+
|
|
68
|
+
Options:
|
|
69
|
+
|
|
70
|
+
- **Move** — `git mv <path> .thrum/philosophy.md`. Preserves history via rename;
|
|
71
|
+
the file moves to the canonical location and the legacy path stops existing.
|
|
72
|
+
- **Link** — Create `.thrum/philosophy.md` with a single line: `See: <path>`.
|
|
73
|
+
The legacy doc stays in place; the canonical path becomes a pointer. Useful
|
|
74
|
+
when the legacy path is load-bearing (e.g., referenced from a
|
|
75
|
+
`CONTRIBUTING.md` that can't be retargeted cheaply).
|
|
76
|
+
- **Fresh** — Ignore the legacy doc; generate a new `.thrum/philosophy.md` via
|
|
77
|
+
the First-run flow. The legacy doc stays unmodified. Useful when the legacy
|
|
78
|
+
doc is stale or incomplete.
|
|
79
|
+
|
|
80
|
+
If multiple candidates were found, ask which one first (separate
|
|
81
|
+
`AskUserQuestion`) before offering move/link/fresh.
|
|
82
|
+
|
|
83
|
+
### Step 3: Execute the chosen option
|
|
84
|
+
|
|
85
|
+
**Move path:**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
mkdir -p .thrum/
|
|
89
|
+
git mv <legacy-path> .thrum/philosophy.md
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`git mv` requires the repo to be initialized with at least one commit on the
|
|
93
|
+
current branch. If the repo has no commits (fresh `git init`), fall back to a
|
|
94
|
+
plain `mv` + `git add`, and note in the final message that rename history is not
|
|
95
|
+
preserved.
|
|
96
|
+
|
|
97
|
+
**Link path:**
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
mkdir -p .thrum/
|
|
101
|
+
printf 'See: %s\n' "<legacy-path>" > .thrum/philosophy.md
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Fresh path:** Drop into First-run mode without touching the legacy file.
|
|
105
|
+
|
|
106
|
+
### Step 4: Announce and continue
|
|
107
|
+
|
|
108
|
+
Tell the user what was done and where the canonical doc now lives. If `move` or
|
|
109
|
+
`link` was chosen, exit (the doc is materialized — no further generation
|
|
110
|
+
needed). If `fresh` was chosen, continue into First-run Step 1.
|
|
111
|
+
|
|
112
|
+
## First-run mode
|
|
113
|
+
|
|
114
|
+
Triggered when `.thrum/philosophy.md` does not exist AND no non-standard
|
|
115
|
+
philosophy doc is found (or the fallback migration is skipped via the "fresh"
|
|
116
|
+
option).
|
|
117
|
+
|
|
118
|
+
### Step 1: Detect language
|
|
119
|
+
|
|
120
|
+
Inspect the repo root for manifest files and pick the primary language:
|
|
121
|
+
|
|
122
|
+
| File present | Language |
|
|
123
|
+
| ---------------------------------------------------- | ----------------------- |
|
|
124
|
+
| `go.mod` | Go |
|
|
125
|
+
| `package.json` | JavaScript / TypeScript |
|
|
126
|
+
| `Cargo.toml` | Rust |
|
|
127
|
+
| `pyproject.toml` or `setup.py` or `requirements.txt` | Python |
|
|
128
|
+
| `pom.xml` or `build.gradle*` | Java / Kotlin |
|
|
129
|
+
| `Gemfile` | Ruby |
|
|
130
|
+
| `mix.exs` | Elixir |
|
|
131
|
+
|
|
132
|
+
If multiple are present, record the repo as polyglot and pick the most prominent
|
|
133
|
+
by file count.
|
|
134
|
+
|
|
135
|
+
### Step 2: Detect framework
|
|
136
|
+
|
|
137
|
+
Grep the detected language's manifest for well-known framework markers:
|
|
138
|
+
|
|
139
|
+
- Go: `cmd/` layout + `net/http` or `gin-gonic` or `chi` → web service; `cobra`
|
|
140
|
+
→ CLI; pure library if neither
|
|
141
|
+
- JS/TS: `next` in `package.json` → Next.js; `react` without Next → React SPA;
|
|
142
|
+
`express`/`fastify` → Node backend
|
|
143
|
+
- Python: `fastapi`/`flask`/`django` in dependencies → web backend;
|
|
144
|
+
`pytorch`/`tensorflow` → ML
|
|
145
|
+
- Rust: `tokio`/`actix-web`/`axum` → async service; bin-only → CLI
|
|
146
|
+
|
|
147
|
+
### Step 3: Detect test harness
|
|
148
|
+
|
|
149
|
+
Check for test files and harness config:
|
|
150
|
+
|
|
151
|
+
- Go: `*_test.go` files; `testing` package import → stdlib; `testify` →
|
|
152
|
+
assertions; `ginkgo` → BDD
|
|
153
|
+
- JS/TS: `__tests__/` or `*.test.ts`; `jest.config.*`, `vitest.config.*`,
|
|
154
|
+
`playwright.config.*`
|
|
155
|
+
- Python: `tests/` dir; `pytest.ini`, `conftest.py`
|
|
156
|
+
- Rust: `#[cfg(test)]` blocks; `cargo test` always available
|
|
157
|
+
|
|
158
|
+
Record the harness in the rendered template so implementation-agent prompts know
|
|
159
|
+
how to run tests.
|
|
160
|
+
|
|
161
|
+
### Step 4: Detect pattern conventions visible in existing code
|
|
162
|
+
|
|
163
|
+
Sample the codebase for:
|
|
164
|
+
|
|
165
|
+
- Error handling shape (Go: `if err != nil { return ..., fmt.Errorf(...) }`;
|
|
166
|
+
Rust: `?` propagation; TS: try/catch vs. Result types)
|
|
167
|
+
- Logging convention (structured vs. `fmt.Println`; named logger vs.
|
|
168
|
+
package-level)
|
|
169
|
+
- Public API shape (exported types, interface-heavy vs. struct-heavy)
|
|
170
|
+
|
|
171
|
+
Grep narrow — 20–50 lines is enough to surface the dominant convention. Don't
|
|
172
|
+
read the whole repo; surface what's consistent, let the user correct via
|
|
173
|
+
prompts.
|
|
174
|
+
|
|
175
|
+
### Step 4a: Probe for generalizable reliability classes
|
|
176
|
+
|
|
177
|
+
Read `resources/reliability-class-library.md`. For each of its 7 classes, run
|
|
178
|
+
the per-language probe matching the language detected in Step 1 (fall back to
|
|
179
|
+
the class's generic probe if the detected language has no dedicated entry).
|
|
180
|
+
Record every hit as an adapted finding: the class name, the specific file/line
|
|
181
|
+
found, and a BAD/GOOD pair phrased in the target repo's own language and
|
|
182
|
+
idioms — never reuse the library's own example snippets verbatim, they are
|
|
183
|
+
illustrations of the SHAPE to look for, not text to paste.
|
|
184
|
+
|
|
185
|
+
A class with zero hits is not an error — record it as walked-and-not-found and
|
|
186
|
+
move on. This step runs before the interactive prompts (Step 5) so seeded
|
|
187
|
+
findings can be shown to the user as defaults they can accept, edit, or
|
|
188
|
+
decline, rather than starting from a blank prompt.
|
|
189
|
+
|
|
190
|
+
### Step 5: Interactive prompts for project-specific rules
|
|
191
|
+
|
|
192
|
+
Use `AskUserQuestion` for items the codebase can't reveal:
|
|
193
|
+
|
|
194
|
+
- Known anti-patterns this team has hit (with links to post-mortems if any)
|
|
195
|
+
- Non-negotiable red flags (e.g. "never rm -rf a session dir")
|
|
196
|
+
- Deploy/release constraints (e.g. "no pushes to main from agents")
|
|
197
|
+
- External dependencies that require care (e.g. "never call prod Salesforce APIs
|
|
198
|
+
from tests")
|
|
199
|
+
|
|
200
|
+
Each prompt should offer a clear default (usually "none"). Philosophy doc
|
|
201
|
+
quality comes from real answers, not filler.
|
|
202
|
+
|
|
203
|
+
> **`AskUserQuestion` permits at most 4 options per question.** Exceeding the
|
|
204
|
+
> limit triggers a runtime "Invalid tool parameters" / "expected array to have
|
|
205
|
+
> <=4 items" error. Each of the categories above has a natural option count that
|
|
206
|
+
> can grow past 4 once a real team's rules are listed — so use multiple
|
|
207
|
+
> sequential questions (e.g. "category?" → "specific item within category?")
|
|
208
|
+
> rather than packing options into a single prompt. Prefer one prompt per
|
|
209
|
+
> category over one prompt with all categories listed.
|
|
210
|
+
|
|
211
|
+
### Step 6: Render the template
|
|
212
|
+
|
|
213
|
+
Read `resources/philosophy-template.md`. It is not token-substituted — it
|
|
214
|
+
uses bracketed prose placeholders (e.g. `[Criterion 1 — e.g., ...]`) that you
|
|
215
|
+
replace with real content, and `<!-- TODO: ... -->` comments for anything left
|
|
216
|
+
undetected or unprovided. Fill in:
|
|
217
|
+
|
|
218
|
+
- The intro/language/framework/test-harness lines from Step 1–3.
|
|
219
|
+
- The `## Anti-Patterns` section's `### 1.`–`### 3.` entries are universal
|
|
220
|
+
defaults — leave them as-is unless a detected convention (Step 4)
|
|
221
|
+
contradicts one.
|
|
222
|
+
- `### 4.` onward: one numbered section per Step 4a finding (an adapted class
|
|
223
|
+
hit), in the order the classes are listed in the library, using that
|
|
224
|
+
finding's BAD/GOOD pair and Why. If Step 4a found more than 2 classes, add
|
|
225
|
+
as many numbered sections as the probe finds — the template's `### 4.`/
|
|
226
|
+
`### 5.` are illustrative slots, not a fixed count. If Step 4a found fewer
|
|
227
|
+
than 2, leave the remaining slot(s) as the template's own
|
|
228
|
+
`[Project-specific anti-pattern]` placeholder rather than fabricating a
|
|
229
|
+
finding.
|
|
230
|
+
- Any remaining `[...]` placeholder with no detected or provided value stays
|
|
231
|
+
as a `<!-- TODO: … -->` line rather than silent emptiness.
|
|
232
|
+
|
|
233
|
+
### Step 6a: MANDATORY — wire the project's security/threat model into the Decision Framework
|
|
234
|
+
|
|
235
|
+
If the project has a written threat model (search `docs/security_model/`,
|
|
236
|
+
`docs/security*.md`, `SECURITY.md`), the rendered philosophy MUST carry a
|
|
237
|
+
Decision Framework row pointing at it — and that row MUST NOT be keyed on the
|
|
238
|
+
word "attacker".
|
|
239
|
+
|
|
240
|
+
```text
|
|
241
|
+
| Does this add a GUARD, RETENTION RULE, PERMANENCE/IMMUTABILITY claim,
|
|
242
|
+
AUDIT/FORENSIC requirement, TAMPER-EVIDENCE, or AUTHORIZATION/RECIPIENT
|
|
243
|
+
check — WHETHER OR NOT it names an attacker? | Read <threat-model-path> §1
|
|
244
|
+
BEFORE designing it. State the project's actual deployment shape here. |
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**A control whose key excludes its own target population is decoration** —
|
|
248
|
+
key the Decision Framework row on effect (adds a guard, retention rule,
|
|
249
|
+
permanence claim, audit/forensic requirement, tamper-evidence, or
|
|
250
|
+
authorization check), never on whether it names an attacker. Security-shaped
|
|
251
|
+
requirements often arrive wearing non-security vocabulary: durability,
|
|
252
|
+
forensics, compliance, "defence in depth", "must never be lost".
|
|
253
|
+
|
|
254
|
+
🔴 **AND STATE THE DEPLOYMENT SHAPE POSITIVELY, not just the exclusions.** The
|
|
255
|
+
dominant failure here is importing a SaaS/multi-tenant frame into a system
|
|
256
|
+
that is not one — which **manufactures defects out of correct design**.
|
|
257
|
+
Write what the project IS, e.g. for thrum: *NOT SaaS, NOT
|
|
258
|
+
internet-facing, NOT product-oriented; single-user, localhost, multi-machine
|
|
259
|
+
on the same network.* A reader who knows only what is out of scope will still
|
|
260
|
+
import the wrong frame.
|
|
261
|
+
|
|
262
|
+
### Step 7: Write `.thrum/philosophy.md`
|
|
263
|
+
|
|
264
|
+
`mkdir -p .thrum/` then write the rendered content. Announce the path in the
|
|
265
|
+
final message so the user knows where to edit it manually later.
|
|
266
|
+
|
|
267
|
+
## Re-run-unchanged mode
|
|
268
|
+
|
|
269
|
+
Triggered when `.thrum/philosophy.md` exists. The goal is a fast,
|
|
270
|
+
side-effect-free sanity check that confirms the doc is still accurate for the
|
|
271
|
+
current project state.
|
|
272
|
+
|
|
273
|
+
### Step 1: Read the existing doc
|
|
274
|
+
|
|
275
|
+
Read `.thrum/philosophy.md` in full. Parse its sections — at minimum the
|
|
276
|
+
language/framework line, the test harness line, and the anti-patterns list.
|
|
277
|
+
|
|
278
|
+
### Step 2: Sanity-check against current project state
|
|
279
|
+
|
|
280
|
+
Walk the same detection steps as first-run, but compare rather than write:
|
|
281
|
+
|
|
282
|
+
- Language / framework / test harness — do the current manifest files agree with
|
|
283
|
+
what the doc claims?
|
|
284
|
+
- Anti-patterns in `CLAUDE.md` (or equivalent) — is every anti-pattern in
|
|
285
|
+
CLAUDE.md reflected in the doc?
|
|
286
|
+
- Linters or test configs recently added — are they acknowledged?
|
|
287
|
+
|
|
288
|
+
Each check is a boolean "matches" vs. "differs". Keep the comparison narrow;
|
|
289
|
+
this mode should not do deep inspection.
|
|
290
|
+
|
|
291
|
+
### Step 3: If nothing differs — no-op exit
|
|
292
|
+
|
|
293
|
+
Print:
|
|
294
|
+
|
|
295
|
+
> `.thrum/philosophy.md` is current; no changes needed.
|
|
296
|
+
|
|
297
|
+
Do NOT write to the file. Do NOT update mtime. Do NOT create backups. Exit
|
|
298
|
+
cleanly.
|
|
299
|
+
|
|
300
|
+
### Step 4: If anything differs — hand off to evolved mode
|
|
301
|
+
|
|
302
|
+
If at least one check reports "differs", transition to the re-run-evolved flow
|
|
303
|
+
(below). The drift detection from Step 2 becomes the input to the diff proposal.
|
|
304
|
+
|
|
305
|
+
Idempotency invariant: re-running `/project-philosophy` on an unchanged project
|
|
306
|
+
must never modify any file. Tests for this mode should confirm mtime is
|
|
307
|
+
untouched — `stat -c %Y .thrum/philosophy.md` on Linux,
|
|
308
|
+
`stat -f %m .thrum/philosophy.md` on macOS.
|
|
309
|
+
|
|
310
|
+
## Re-run-evolved mode
|
|
311
|
+
|
|
312
|
+
Triggered when `.thrum/philosophy.md` exists AND the unchanged-mode sanity check
|
|
313
|
+
flagged drift. This is the load-bearing idempotency path — philosophy docs
|
|
314
|
+
accumulate learned anti-patterns over time, so silent overwrites destroy
|
|
315
|
+
context. The merge-proposal shape is the only correct shape.
|
|
316
|
+
|
|
317
|
+
> **Never silently overwrite.** Philosophy docs are not regenerated — they are
|
|
318
|
+
> evolved. If the user has added hand-written anti-patterns, post-mortem
|
|
319
|
+
> references, or team-specific notes, those must survive every re-run. A write
|
|
320
|
+
> without explicit user confirmation is a bug.
|
|
321
|
+
|
|
322
|
+
### Step 1: Read the existing doc
|
|
323
|
+
|
|
324
|
+
Same as re-run-unchanged Step 1. Keep the parsed sections in memory so the diff
|
|
325
|
+
proposal can cite them.
|
|
326
|
+
|
|
327
|
+
### Step 2: Detect drift
|
|
328
|
+
|
|
329
|
+
Four drift categories, conservative on purpose:
|
|
330
|
+
|
|
331
|
+
- **Language/framework version change.** `go.mod`'s `go 1.X` differs from the
|
|
332
|
+
doc's stated version; `package.json` lists `next@15.x` but doc says
|
|
333
|
+
`next@14.x`.
|
|
334
|
+
- **New test patterns in codebase.** `ginkgo` imports appear but the doc lists
|
|
335
|
+
only `stdlib testing`. New `playwright.config.ts` exists but doc doesn't
|
|
336
|
+
mention E2E.
|
|
337
|
+
- **New anti-patterns recorded in CLAUDE.md since last run.** Compare
|
|
338
|
+
anti-pattern bullets in CLAUDE.md against the doc's `{{ANTI_PATTERNS}}`
|
|
339
|
+
section; anything new in CLAUDE.md is a drift candidate.
|
|
340
|
+
- **New linters or code-quality tooling added.** `.golangci.yml`,
|
|
341
|
+
`eslint.config.js`, `ruff.toml` that weren't mentioned in the doc.
|
|
342
|
+
|
|
343
|
+
Start conservative. Expand the detector list only based on real-use feedback —
|
|
344
|
+
over-eager drift detection pesters users and erodes trust in the skill.
|
|
345
|
+
|
|
346
|
+
### Step 3: Compute a proposed diff (sectional)
|
|
347
|
+
|
|
348
|
+
Present drift as a readable sectional diff, one item per drift category. Each
|
|
349
|
+
item should have:
|
|
350
|
+
|
|
351
|
+
- The detected change in plain language
|
|
352
|
+
- A proposed edit (insertion / replacement / addition at the bottom of a
|
|
353
|
+
section)
|
|
354
|
+
- A one-line rationale
|
|
355
|
+
|
|
356
|
+
Example shape:
|
|
357
|
+
|
|
358
|
+
```markdown
|
|
359
|
+
### Proposed updates to `.thrum/philosophy.md`
|
|
360
|
+
|
|
361
|
+
**1. Framework version bump**
|
|
362
|
+
|
|
363
|
+
- Current: "Next.js 14"
|
|
364
|
+
- Proposed: "Next.js 15"
|
|
365
|
+
- Rationale: `package.json` lists `"next": "^15.0.0"`
|
|
366
|
+
|
|
367
|
+
**2. New anti-pattern from CLAUDE.md**
|
|
368
|
+
|
|
369
|
+
- Proposed addition under "## Anti-patterns":
|
|
370
|
+
> - Never run migrations from an agent session — always via the release
|
|
371
|
+
> pipeline.
|
|
372
|
+
- Rationale: Added to CLAUDE.md in commit abc1234 after the 2026-03 incident.
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Step 4: Present via `AskUserQuestion`
|
|
376
|
+
|
|
377
|
+
Use `AskUserQuestion` with:
|
|
378
|
+
|
|
379
|
+
- A concise summary question: "3 drifts detected against `.thrum/philosophy.md`.
|
|
380
|
+
Apply all, select, or decline?"
|
|
381
|
+
- Options: `Apply all`, `Select items to apply`, `Decline (keep doc as-is)`
|
|
382
|
+
- Include the full sectional diff from Step 3 in the question context so the
|
|
383
|
+
user can see what they're approving
|
|
384
|
+
|
|
385
|
+
If the user picks `Select items`, fire a follow-up `AskUserQuestion` with
|
|
386
|
+
per-item yes/no choices.
|
|
387
|
+
|
|
388
|
+
### Step 5: Write only on confirmation
|
|
389
|
+
|
|
390
|
+
Apply approved edits in-place. For each applied edit:
|
|
391
|
+
|
|
392
|
+
- Preserve surrounding content (don't re-render the whole template)
|
|
393
|
+
- Append a provenance comment near the change:
|
|
394
|
+
`<!-- updated YYYY-MM-DD via project-philosophy re-run-evolved -->`
|
|
395
|
+
|
|
396
|
+
Write the file once, at the end. Announce the applied items in the final
|
|
397
|
+
message.
|
|
398
|
+
|
|
399
|
+
### Step 6: On decline — no write + log
|
|
400
|
+
|
|
401
|
+
If the user declines (or selects zero items), do NOT write to the file. Record
|
|
402
|
+
the skipped proposal in `.thrum/philosophy-skipped.jsonl` (append-only, one JSON
|
|
403
|
+
line per decline) with the timestamp and the drift items proposed. Future runs
|
|
404
|
+
can re-surface the same items without re-computing drift from scratch.
|
|
405
|
+
|
|
406
|
+
Skipped-proposal log is advisory — its absence is not an error.
|
|
407
|
+
|
|
408
|
+
## Reference
|
|
409
|
+
|
|
410
|
+
- `.thrum/philosophy.md` — the canonical doc this skill generates
|
|
411
|
+
- `resources/reliability-class-library.md` — the generalizable reliability
|
|
412
|
+
class library Step 4a probes; shared with `project-hotpath-gate`
|
|
413
|
+
- `coordinator-philosophy-merge-gate` — the gate skill that reads the philosophy
|
|
414
|
+
doc
|
|
415
|
+
- `project-hotpath-gate` — the companion builder that generates
|
|
416
|
+
`.thrum/hotpath-gate.json` (hot-path/perf gate config). Run both at the same
|
|
417
|
+
onboarding moment so the project has both general philosophy and hot-path gate
|
|
418
|
+
configuration from day one.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Implementation Philosophy
|
|
2
|
+
|
|
3
|
+
> **For all agents:** This document governs how features are built. Read this
|
|
4
|
+
> BEFORE any plan file or task descriptions. When in doubt, ask: "[your > >
|
|
5
|
+
> project's > guiding question — e.g., 'Am I wiring a real service, or faking >
|
|
6
|
+
>
|
|
7
|
+
> > it?']"
|
|
8
|
+
>
|
|
9
|
+
> **Fill this template** for your project. The pre-filled examples below are
|
|
10
|
+
> universal defaults — adapt, replace, or extend them for your domain.
|
|
11
|
+
|
|
12
|
+
## Core Principle
|
|
13
|
+
|
|
14
|
+
**Every implementation MUST satisfy ALL of these criteria:**
|
|
15
|
+
|
|
16
|
+
1. [Criterion 1 — e.g., Handler calls real service method, not hardcoded data]
|
|
17
|
+
2. [Criterion 2 — e.g., Template renders from service response, not inline HTML]
|
|
18
|
+
3. [Criterion 3 — e.g., Changing underlying data changes rendered output]
|
|
19
|
+
4. [Criterion 4 — e.g., Access control uses real permission checks, not
|
|
20
|
+
client-side hiding]
|
|
21
|
+
5. The verification step in the task description passes
|
|
22
|
+
|
|
23
|
+
## Decision Framework
|
|
24
|
+
|
|
25
|
+
When implementing any requirement, follow this decision tree:
|
|
26
|
+
|
|
27
|
+
| Question | Action |
|
|
28
|
+
| ------------------------------------------ | ------------------------------------- |
|
|
29
|
+
| Does a backend service already exist? | Wire it. Do not rewrite. |
|
|
30
|
+
| Does the service exist but need extension? | Extend the service, then wire. |
|
|
31
|
+
| Is this purely new capability? | Build minimal service first, then UI. |
|
|
32
|
+
| Is this seed data / configuration? | Load into real stores, not hardcoded. |
|
|
33
|
+
|
|
34
|
+
## Anti-Patterns
|
|
35
|
+
|
|
36
|
+
<!-- Define BAD/GOOD code examples. Sections 1-3 are universal defaults. -->
|
|
37
|
+
<!-- Sections 4+ are seeded from the reliability-class-library probe -->
|
|
38
|
+
<!-- (project-philosophy SKILL.md Step 4a) — as many numbered sections as the probe finds, not a fixed count. -->
|
|
39
|
+
<!-- The BAD/GOOD format is critical — it makes the standard concrete and unambiguous. -->
|
|
40
|
+
|
|
41
|
+
### 1. Hardcoded data in handlers
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
// BAD — handler returns static data, ignoring the service layer
|
|
45
|
+
func handleList(w http.ResponseWriter, r *http.Request) {
|
|
46
|
+
items := []Item{{Name: "hardcoded-1"}, {Name: "hardcoded-2"}}
|
|
47
|
+
tmpl.Execute(w, items)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// GOOD — handler calls real service, renders response
|
|
51
|
+
func handleList(w http.ResponseWriter, r *http.Request) {
|
|
52
|
+
items, err := h.store.ListItems(r.Context())
|
|
53
|
+
if err != nil { http.Error(w, err.Error(), 500); return }
|
|
54
|
+
tmpl.Execute(w, items)
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Why:** Hardcoded data passes tests but breaks when real data changes. It
|
|
59
|
+
creates a false sense of completion.
|
|
60
|
+
|
|
61
|
+
### 2. Client-side permission hiding
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<!-- BAD — server renders everything, JS/CSS hides unauthorized items -->
|
|
65
|
+
<button id="admin-action" style="display:none">Delete</button>
|
|
66
|
+
<script>
|
|
67
|
+
if (userRole === "admin") show("admin-action");
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<!-- GOOD — server only renders items the user can access -->
|
|
71
|
+
{{if .Permissions.CanDelete}}
|
|
72
|
+
<button>Delete</button>
|
|
73
|
+
{{end}}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Why:** Client-side hiding is a UI illusion, not access control. The server
|
|
77
|
+
still processes unauthorized requests.
|
|
78
|
+
|
|
79
|
+
### 3. Scripted/mocked responses in production paths
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
# BAD — handler returns a pre-written response instead of calling the service
|
|
83
|
+
def analyze(request):
|
|
84
|
+
return {"result": "This ticket appears to be high priority..."}
|
|
85
|
+
|
|
86
|
+
# GOOD — handler calls the real analysis service
|
|
87
|
+
def analyze(request):
|
|
88
|
+
result = analysis_service.analyze(request.ticket_id)
|
|
89
|
+
return {"result": result}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Why:** Scripted responses mask integration failures. The service may not
|
|
93
|
+
actually work, and you won't know until production.
|
|
94
|
+
|
|
95
|
+
### 4. [Project-specific anti-pattern]
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
// BAD
|
|
99
|
+
// GOOD
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Why:** [Impact explanation]
|
|
103
|
+
|
|
104
|
+
### 5. [Project-specific anti-pattern]
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
// BAD
|
|
108
|
+
// GOOD
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Why:** [Impact explanation]
|
|
112
|
+
|
|
113
|
+
## Acceptable Simplifications
|
|
114
|
+
|
|
115
|
+
Not everything needs to be production-grade. These simplifications are OK:
|
|
116
|
+
|
|
117
|
+
| Simplification | Why It's OK | Boundary (when to stop) |
|
|
118
|
+
| -------------------------- | ------------------------------------ | ---------------------------------------- |
|
|
119
|
+
| SQLite instead of Postgres | Same SQL interface, simpler setup | When concurrent write throughput matters |
|
|
120
|
+
| Cached/mock external APIs | Deterministic tests, no network deps | When testing real API behavior changes |
|
|
121
|
+
| Static seed data | Reproducible demos and tests | When data must reflect real user input |
|
|
122
|
+
| [Project-specific] | [Rationale] | [Boundary] |
|
|
123
|
+
|
|
124
|
+
## Red Flags
|
|
125
|
+
|
|
126
|
+
If you see any of these in your code, **STOP and fix before continuing:**
|
|
127
|
+
|
|
128
|
+
- [ ] Literal data structures returned from handlers (not from a store/service)
|
|
129
|
+
- [ ] Inline HTML generation (`fmt.Fprintf`, string concatenation) instead of
|
|
130
|
+
templates
|
|
131
|
+
- [ ] Missing error handling on service/store calls
|
|
132
|
+
- [ ] TODO/FIXME comments left in committed code
|
|
133
|
+
- [ ] [Project-specific red flag]
|
|
134
|
+
- [ ] [Project-specific red flag]
|
|
135
|
+
- [ ] [Project-specific red flag]
|
|
136
|
+
|
|
137
|
+
## For Implementation Agents
|
|
138
|
+
|
|
139
|
+
### Before You Start a Task
|
|
140
|
+
|
|
141
|
+
- [ ] Read the design doc referenced in your prompt
|
|
142
|
+
- [ ] Read the task description (`bd show {TASK_ID}`) — it's your source of
|
|
143
|
+
truth
|
|
144
|
+
- [ ] Search the plan file for your task's implementation code
|
|
145
|
+
(`grep "## Task: {BEAD_ID}" plan-file.md`)
|
|
146
|
+
- [ ] Identify which existing services to wire (do not reimplement)
|
|
147
|
+
- [ ] Review the anti-patterns above — know what NOT to do
|
|
148
|
+
|
|
149
|
+
### Before You Close a Task
|
|
150
|
+
|
|
151
|
+
- [ ] All acceptance criteria in the beads task are satisfied
|
|
152
|
+
- [ ] Tests pass (run quality commands from your prompt)
|
|
153
|
+
- [ ] No red flags present in your implementation
|
|
154
|
+
- [ ] Commit message is descriptive
|
|
155
|
+
- [ ] Code follows existing project patterns and conventions
|