omniconductor 0.3.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/CHANGELOG.md +64 -0
- package/LICENSE +219 -0
- package/NOTICE +11 -0
- package/README.md +526 -0
- package/THIRD_PARTY_NOTICES.md +31 -0
- package/TRADEMARKS.md +26 -0
- package/VISION.md +106 -0
- package/adapters/README.md +121 -0
- package/adapters/claude/README.md +102 -0
- package/adapters/claude/SUPPORTED-FEATURES.md +66 -0
- package/adapters/claude/hookify-templates/.recipe-scoped +9 -0
- package/adapters/claude/hookify-templates/README.md +93 -0
- package/adapters/claude/hookify-templates/block-completion-claim-without-push.local.md.template +56 -0
- package/adapters/claude/hookify-templates/block-direct-push-protected-branch.local.md.template +18 -0
- package/adapters/claude/hookify-templates/block-force-push-protected-branch.local.md.template +42 -0
- package/adapters/claude/hookify-templates/block-server-secret-in-client.local.md.template +36 -0
- package/adapters/claude/hookify-templates/warn-any-type-added.local.md.template +44 -0
- package/adapters/claude/hookify-templates/warn-commit-without-pre-commit-review.local.md.template +52 -0
- package/adapters/claude/hookify-templates/warn-console-direct.local.md.template +55 -0
- package/adapters/claude/hookify-templates/warn-create-table-without-access-control.local.md.template +35 -0
- package/adapters/claude/hookify-templates/warn-current-work-without-remaining-tasks.local.md.template +36 -0
- package/adapters/claude/hookify-templates/warn-gh-pr-create-without-pre-merge-review.local.md.template +38 -0
- package/adapters/claude/hookify-templates/warn-hardcoded-text-without-i18n-key.local.md.template +21 -0
- package/adapters/claude/hookify-templates/warn-on-gh-pr-merge.local.md.template +33 -0
- package/adapters/claude/hookify-templates/warn-plan-spec-without-remaining-tasks.local.md.template +44 -0
- package/adapters/claude/hookify-templates/warn-raw-hex-instead-of-token.local.md.template +21 -0
- package/adapters/claude/hookify-templates/warn-security-definer-without-search-path.local.md.template +30 -0
- package/adapters/claude/hookify-templates/warn-stop-commit-without-current-work.local.md.template +47 -0
- package/adapters/claude/hookify-templates/warn-user-manual-completion.local.md.template +40 -0
- package/adapters/claude/transform-spec.md +140 -0
- package/adapters/claude/transform.sh +1169 -0
- package/adapters/codex/README.md +87 -0
- package/adapters/codex/SUPPORTED-FEATURES.md +66 -0
- package/adapters/codex/transform-spec.md +90 -0
- package/adapters/codex/transform.sh +748 -0
- package/adapters/copilot/README.md +88 -0
- package/adapters/copilot/SUPPORTED-FEATURES.md +73 -0
- package/adapters/copilot/transform-spec.md +111 -0
- package/adapters/copilot/transform.sh +757 -0
- package/adapters/cursor/README.md +87 -0
- package/adapters/cursor/SUPPORTED-FEATURES.md +90 -0
- package/adapters/cursor/transform-spec.md +124 -0
- package/adapters/cursor/transform.sh +731 -0
- package/adapters/gemini/README.md +93 -0
- package/adapters/gemini/SUPPORTED-FEATURES.md +80 -0
- package/adapters/gemini/transform-spec.md +102 -0
- package/adapters/gemini/transform.sh +844 -0
- package/adapters/windsurf/README.md +93 -0
- package/adapters/windsurf/SUPPORTED-FEATURES.md +67 -0
- package/adapters/windsurf/transform-spec.md +99 -0
- package/adapters/windsurf/transform.sh +727 -0
- package/bin/omniconductor.js +130 -0
- package/core/README.md +64 -0
- package/core/anti-patterns/README.md +142 -0
- package/core/anti-patterns/dynamic-system-prompt.md +113 -0
- package/core/anti-patterns/frequent-rule-file-edit.md +83 -0
- package/core/anti-patterns/large-file-read-no-range.md +90 -0
- package/core/anti-patterns/no-sub-agent-dispatch.md +89 -0
- package/core/anti-patterns/single-monolithic-rule-file.md +99 -0
- package/core/anti-patterns/skill-eager-load.md +83 -0
- package/core/anti-patterns/tool-call-spam.md +93 -0
- package/core/docs-templates/CURRENT_WORK.md +64 -0
- package/core/docs-templates/INDEX.md +57 -0
- package/core/docs-templates/PLANS.md +44 -0
- package/core/docs-templates/README.md +40 -0
- package/core/docs-templates/REMAINING_TASKS.md +43 -0
- package/core/docs-templates/TASKS.md +51 -0
- package/core/docs-templates/specs/_example.md +121 -0
- package/core/hooks/README.md +62 -0
- package/core/hooks/pretool-agent-routing.sh.template +97 -0
- package/core/hooks/pretool-commit-current-work-check.sh.template +103 -0
- package/core/hooks/pretool-commit-test-coverage-check.sh.template +116 -0
- package/core/hooks/pretool-large-file-read-guard.sh.template +117 -0
- package/core/hooks/stop-cache-hit-baseline-check.sh.template +133 -0
- package/core/hooks/stop-r6-review-check.sh.template +80 -0
- package/core/hooks/stop-session-log-check.sh.template +101 -0
- package/core/hooks/stop-trajectory-log.sh.template +96 -0
- package/core/memory-pattern/EXAMPLES.md +114 -0
- package/core/memory-pattern/README.md +133 -0
- package/core/recipes/README.md +46 -0
- package/core/recipes/auto-mock-data.md +82 -0
- package/core/recipes/branch-strategy.md +100 -0
- package/core/recipes/coding-conventions.md +123 -0
- package/core/recipes/database-discipline.md +65 -0
- package/core/recipes/debugging.md +143 -0
- package/core/recipes/design-system.md +30 -0
- package/core/recipes/i18n.md +118 -0
- package/core/recipes/monorepo.md +101 -0
- package/core/recipes/self-improvement.md +61 -0
- package/core/recipes/tdd.md +128 -0
- package/core/recipes/web-mobile-parity.md +87 -0
- package/core/reflector/SCHEDULING.md +83 -0
- package/core/reflector/prune-lessons.sh +105 -0
- package/core/reflector/reflect-brief.md +11 -0
- package/core/reflector/reflect.command.md +13 -0
- package/core/reflector/run-weekly.sh +54 -0
- package/core/reflector/trajectory-log.sh +55 -0
- package/core/roles/README.md +61 -0
- package/core/roles/builder.md +75 -0
- package/core/roles/designer.md +93 -0
- package/core/roles/helper.md +70 -0
- package/core/roles/planner.md +123 -0
- package/core/roles/reflector.md +72 -0
- package/core/roles/reviewer.md +104 -0
- package/core/roles/scribe.md +89 -0
- package/core/universal-rules/README.md +71 -0
- package/core/universal-rules/meta-discipline.md +292 -0
- package/core/universal-rules/operations.md +162 -0
- package/core/universal-rules/quality-gates.md +191 -0
- package/core/universal-rules/spec-as-you-go.md +123 -0
- package/core/universal-rules/workflow.md +153 -0
- package/core/workflow/PHASES.md +134 -0
- package/core/workflow/README.md +56 -0
- package/docs/MANUAL-INSTALL.md +456 -0
- package/package.json +52 -0
- package/tools/check-framework-purity.sh +91 -0
- package/tools/measure-tokens.sh +169 -0
- package/tools/validate-adapter-output.sh +611 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# `core/recipes/` — Project-specific opt-in patterns
|
|
2
|
+
|
|
3
|
+
Per ADR-013, CONDUCTOR ships project-specific recipes as OPT-IN. They are not loaded by default. Adopters select the recipes that match their project and the adapter wires them into the appropriate native location.
|
|
4
|
+
|
|
5
|
+
## The 11 recipes
|
|
6
|
+
|
|
7
|
+
| File | When to install |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `web-mobile-parity.md` | Project has both web and mobile surfaces sharing business logic |
|
|
10
|
+
| `i18n.md` | Project supports multiple locales |
|
|
11
|
+
| `monorepo.md` | Project uses npm workspaces (or equivalent) with shared packages |
|
|
12
|
+
| `branch-strategy.md` | Project uses a 3-branch model (or wants the example pattern) |
|
|
13
|
+
| `auto-mock-data.md` | Project has a database and wants seed data autogen on schema change |
|
|
14
|
+
| `coding-conventions.md` | Project wants explicit naming / TS / error-handling conventions enforced |
|
|
15
|
+
| `tdd.md` | Project has a test framework and wants Red-Green-Refactor methodology enforced across feature work and bug fixes |
|
|
16
|
+
| `debugging.md` | Any project — enforces root-cause-first investigation before any fix is attempted |
|
|
17
|
+
| `database-discipline.md` | Project has a relational store with migrations + dev/prod split. Ships 2 recipe-scoped hookify rules (SQL access-control + SECURITY DEFINER search_path) — see ADR-028 |
|
|
18
|
+
| `design-system.md` | Project maintains a design-token system (color/spacing/typography tokens). Ships 1 recipe-scoped hookify rule (raw-hex-instead-of-token) — see ADR-028 |
|
|
19
|
+
| `self-improvement.md` | Project wants a periodic, human-approved Reflector that distils session lessons into memory/rules. Propose-only; nothing auto-applies. Drives the `reflector` role — see ADR-030 |
|
|
20
|
+
|
|
21
|
+
## Selection patterns
|
|
22
|
+
|
|
23
|
+
| Project type | Recommended recipes |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Solo SaaS, web-only, single-locale | `coding-conventions` + `tdd` + `debugging` |
|
|
26
|
+
| SaaS with mobile companion | `web-mobile-parity` + `coding-conventions` + `tdd` + `debugging` |
|
|
27
|
+
| Multi-locale SaaS | `i18n` + `coding-conventions` + `tdd` + `debugging` |
|
|
28
|
+
| Relational-DB-backed SaaS (migrations + dev/prod) | `database-discipline` + `coding-conventions` + `tdd` + `debugging` |
|
|
29
|
+
| Token-driven design system (theming / dark-mode) | `design-system` + `coding-conventions` + `tdd` + `debugging` |
|
|
30
|
+
| Full-stack SaaS with web + mobile + i18n | All 11 |
|
|
31
|
+
| Greenfield experiment | None — universal-rules + roles only is enough |
|
|
32
|
+
|
|
33
|
+
## How adapters consume these files
|
|
34
|
+
|
|
35
|
+
Adapter `transform.sh` accepts a `--recipes=<comma-separated-list>` flag (or per-tool equivalent). Selected recipes are written to:
|
|
36
|
+
|
|
37
|
+
| Adapter | Output path |
|
|
38
|
+
|---|---|
|
|
39
|
+
| Claude | `.claude/rules/<recipe>.md` (with `paths:` frontmatter where the recipe ships its own path scope) |
|
|
40
|
+
| Cursor | `.cursor/rules/<recipe>.mdc` |
|
|
41
|
+
| Copilot | `.github/instructions/<recipe>.instructions.md` |
|
|
42
|
+
| Gemini | Section in `GEMINI.md` |
|
|
43
|
+
| Codex | Section in `.codex/codex.md` |
|
|
44
|
+
| Windsurf | `.windsurf/rules/<recipe>.md` |
|
|
45
|
+
|
|
46
|
+
Recipes are layered on TOP of universal-rules. They never override; they extend.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe_id: auto-mock-data
|
|
3
|
+
recipe_name: "Auto-generate mock seed data on schema change"
|
|
4
|
+
applies_when: "project has a relational database and wants seed data autogen"
|
|
5
|
+
severity: STRONG (when installed)
|
|
6
|
+
linked_rules:
|
|
7
|
+
- spec-as-you-go
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Recipe — Auto Mock Data
|
|
11
|
+
|
|
12
|
+
> Opt-in recipe. Install when the project has a relational database (Postgres, MySQL, SQLite, etc.) and wants seed data automatically generated whenever the schema changes. Do NOT install on document-store-only projects.
|
|
13
|
+
|
|
14
|
+
## 1. The rule
|
|
15
|
+
|
|
16
|
+
Whenever a database table is created, modified, or removed, the corresponding mock seed SQL (or seed script) MUST be generated or updated in the SAME turn as the schema change.
|
|
17
|
+
|
|
18
|
+
### 1.1 Why same-turn
|
|
19
|
+
|
|
20
|
+
The orchestrator that just finished the migration has the table's column types, constraints, and example values fresh in mind. By the next session, that context is gone. Seed data generated later is generic and misses the realistic data shapes that the migration was actually for.
|
|
21
|
+
|
|
22
|
+
### 1.2 What "mock seed" means
|
|
23
|
+
|
|
24
|
+
- A SQL file (or seed script) that inserts representative rows for the new / changed table.
|
|
25
|
+
- "Representative" = covers the access patterns the application code will use:
|
|
26
|
+
- Edge cases (null values where allowed, empty strings, max-length strings).
|
|
27
|
+
- Realistic values (not "lorem ipsum" — actual data shapes the dev / staging environment needs).
|
|
28
|
+
- Foreign-key relationships intact (seed parent rows before child rows).
|
|
29
|
+
|
|
30
|
+
## 2. File organization
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
db/
|
|
34
|
+
├── migrations/
|
|
35
|
+
│ ├── 20260506_add_foo_table.sql
|
|
36
|
+
│ └── 20260507_alter_bar_column.sql
|
|
37
|
+
├── seeds/
|
|
38
|
+
│ ├── foo.seed.sql
|
|
39
|
+
│ └── bar.seed.sql
|
|
40
|
+
└── README.md
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or whatever convention the project's ORM / migration tool prefers. The recipe is "seed updates land alongside schema updates", not a specific tool.
|
|
44
|
+
|
|
45
|
+
## 3. The "no manual ask" sub-rule
|
|
46
|
+
|
|
47
|
+
The orchestrator does NOT ask "should I add seed data?" after a migration. Seed data is a default deliverable of any schema change. The dispatch brief for a database change MUST include "and update seed data" without the user requesting it.
|
|
48
|
+
|
|
49
|
+
This is the recipe's central discipline: seed data autogen is automatic, not opt-in per change.
|
|
50
|
+
|
|
51
|
+
## 4. Seed quality requirements
|
|
52
|
+
|
|
53
|
+
| Requirement | Why |
|
|
54
|
+
|---|---|
|
|
55
|
+
| At least 3 rows per new table | Single-row seeds don't exercise list / pagination paths |
|
|
56
|
+
| Foreign keys intact | Broken references defeat the seed |
|
|
57
|
+
| Mix of edge cases (nulls, empty strings, max lengths) | Catches column constraint mistakes |
|
|
58
|
+
| Realistic values (not placeholder "test1", "test2") | Dev environment should look like prod, just smaller |
|
|
59
|
+
| Idempotent inserts (`INSERT ... ON CONFLICT DO NOTHING` or equivalent) | Safe to re-run during dev environment resets |
|
|
60
|
+
|
|
61
|
+
## 5. When schema is removed
|
|
62
|
+
|
|
63
|
+
When a table or column is dropped:
|
|
64
|
+
|
|
65
|
+
- Remove the corresponding seed entries.
|
|
66
|
+
- Remove dependent seeds in other tables (foreign-key cleanup).
|
|
67
|
+
- Document the removal in the migration's commit message.
|
|
68
|
+
|
|
69
|
+
## 6. Production case
|
|
70
|
+
|
|
71
|
+
Documented case: a new table was added without seed updates. The dev environment had the table empty. UI code that read the table with an `expects-non-empty` assumption crashed when developers tried to render the new feature locally. The seed update would have caught this immediately.
|
|
72
|
+
|
|
73
|
+
## 7. Cross-tool enforcement
|
|
74
|
+
|
|
75
|
+
| Mechanism | Where |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Spec-as-you-go (universal) | Same-turn doc + seed update enforced by `spec-as-you-go.md` |
|
|
78
|
+
| Migration script template | Project's migration tool template includes a "seed updated?" checkbox in commit message |
|
|
79
|
+
| Pre-commit review (Q1) | Reviewer checklist: "DB schema changed → seed updated?" |
|
|
80
|
+
| Rule text | This recipe loaded into the tool's rule context |
|
|
81
|
+
|
|
82
|
+
The recipe does not add a new automated check; it adds a discipline that the existing checks (spec-as-you-go, Q1) catch when followed.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe_id: branch-strategy
|
|
3
|
+
recipe_name: "3-branch deploy model (main / develop / release)"
|
|
4
|
+
applies_when: "project wants a 3-branch deploy model with auto-deploy environments"
|
|
5
|
+
severity: STRONG (when installed)
|
|
6
|
+
linked_rules:
|
|
7
|
+
- operations
|
|
8
|
+
- quality-gates
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Recipe — Branch Strategy (3-branch model)
|
|
12
|
+
|
|
13
|
+
> Opt-in recipe. Install when the project wants a 3-branch model (or the example pattern). Adopters with their own strategy (trunk-based, GitFlow, etc.) ignore this recipe; the universal `operations.md` rules still apply.
|
|
14
|
+
|
|
15
|
+
## 1. Branch roles
|
|
16
|
+
|
|
17
|
+
| Branch | Role | Auto-deploys to |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `main` | Source of truth — last successful release snapshot. NO auto-deploy. | None |
|
|
20
|
+
| `develop` | Integration / dev environment. Auto-deploy. | dev environment (e.g., `<project>-dev` on your hosting provider + dev DB) |
|
|
21
|
+
| `release` | Pre-prod / staging. Auto-deploy. | prod environment (e.g., `<project>-prod` on your hosting provider + prod DB) |
|
|
22
|
+
|
|
23
|
+
The originating project uses this model; the names (`main` / `develop` / `release`) are the reference. Adopters with `main` / `staging` / `production` semantics map equivalently.
|
|
24
|
+
|
|
25
|
+
## 2. New work flow
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
main → branch off → feature/<name> (or fix/<name>, chore/<name>)
|
|
29
|
+
→ PR to develop → CI green + review → merge develop
|
|
30
|
+
→ PR to release → prod verification → merge release
|
|
31
|
+
→ PR release → main → merge main
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Each step has a quality gate:
|
|
35
|
+
|
|
36
|
+
| Step | Gate |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `feature/*` → `develop` PR | Q1 pre-commit + Q2 pre-merge + CI green |
|
|
39
|
+
| `develop` → `release` PR | dev verification confirmed + Q2 |
|
|
40
|
+
| `release` → `main` PR | prod verification confirmed (smoke tests) |
|
|
41
|
+
|
|
42
|
+
## 3. Hotfix flow
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
main → branch off → hotfix/<name>
|
|
46
|
+
→ PR to release → emergency review → merge
|
|
47
|
+
→ cherry-pick to develop (sync)
|
|
48
|
+
→ PR release → main
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Hotfixes skip the develop integration step because the urgency demands it. The cherry-pick to develop ensures the fix is not lost when develop next merges into release.
|
|
52
|
+
|
|
53
|
+
## 4. Push policy
|
|
54
|
+
|
|
55
|
+
| Branch | Direct push | PR required | Force push |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| `main` | FORBIDDEN | Required | FORBIDDEN |
|
|
58
|
+
| `release` | FORBIDDEN | Required | FORBIDDEN |
|
|
59
|
+
| `develop` | Allowed for orchestrator (with review) | Strongly preferred | FORBIDDEN |
|
|
60
|
+
| `feature/*`, `fix/*`, `chore/*`, `hotfix/*` | Allowed | Required to land | Allowed locally |
|
|
61
|
+
|
|
62
|
+
GitHub branch protection (or equivalent) enforces the FORBIDDEN rows. Force push is FORBIDDEN on every protected branch — even by admins, without a documented exception.
|
|
63
|
+
|
|
64
|
+
## 5. PR review (Q2 cross-link)
|
|
65
|
+
|
|
66
|
+
Every code PR to `develop`, `release`, or `main` requires Q2 pre-merge code review per `quality-gates.md`. Docs-only PRs are exempt.
|
|
67
|
+
|
|
68
|
+
The orchestrator runs the slash command (Claude Code) or its equivalent on PR open. The Stop-hook (Claude Code) reminds if the orchestrator forgets.
|
|
69
|
+
|
|
70
|
+
## 6. Push timing
|
|
71
|
+
|
|
72
|
+
> Adopters CHOOSE this convention. It is not universal.
|
|
73
|
+
|
|
74
|
+
The originating project's push timing convention:
|
|
75
|
+
|
|
76
|
+
- Code commits: push immediately (CI runs, deploy triggers).
|
|
77
|
+
- Docs-only commits: do NOT push immediately. Batch with the next code push.
|
|
78
|
+
|
|
79
|
+
### 6.1 Why batch docs
|
|
80
|
+
|
|
81
|
+
Each push triggers a deploy pipeline. Docs-only pushes consume deploy budget without changing what runs in production. On platforms with deploy quotas (many hosting providers cap free-tier deploys per day), batching docs-only pushes is non-trivial savings.
|
|
82
|
+
|
|
83
|
+
### 6.2 Exceptions to batch
|
|
84
|
+
|
|
85
|
+
- Time-critical doc updates (a public-facing doc page must update now).
|
|
86
|
+
- Docs that gate other work (CURRENT_WORK.md mid-day update so another session can resume).
|
|
87
|
+
|
|
88
|
+
## 7. Cross-tool enforcement
|
|
89
|
+
|
|
90
|
+
| Mechanism | Where |
|
|
91
|
+
|---|---|
|
|
92
|
+
| Direct-push prevention on protected branches | GitHub branch protection (or platform equivalent) |
|
|
93
|
+
| Force-push prevention on protected branches | Branch protection |
|
|
94
|
+
| PR review required | Branch protection (require approving review) |
|
|
95
|
+
| CI green required | Branch protection (require status checks) |
|
|
96
|
+
| Push timing convention | Rule text + orchestrator self-discipline |
|
|
97
|
+
|
|
98
|
+
## 8. Connection to `operations.md` (universal)
|
|
99
|
+
|
|
100
|
+
The universal operations rule (`P3` dev/prod sync) assumes a branch model exists. This recipe provides one example. Adopters with different conventions still satisfy P3 by ensuring env-var / migration / external-service parity at deploy time, regardless of branch names.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe_id: coding-conventions
|
|
3
|
+
recipe_name: "TypeScript-first coding conventions"
|
|
4
|
+
applies_when: "TypeScript / TSX project that wants explicit naming + error-handling + type-safety conventions"
|
|
5
|
+
severity: STRONG (when installed)
|
|
6
|
+
linked_rules:
|
|
7
|
+
- quality-gates
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Recipe — Coding Conventions
|
|
11
|
+
|
|
12
|
+
> Opt-in recipe. Install on TypeScript / TSX projects that want explicit naming, error-handling, and type-safety conventions. Adopters in other languages (Go, Rust, Python) skip this recipe and write their own.
|
|
13
|
+
|
|
14
|
+
## 1. Naming
|
|
15
|
+
|
|
16
|
+
| Kind | Convention | Example |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| Components / Types / Interfaces | PascalCase | `AccountCard.tsx`, `interface Account` |
|
|
19
|
+
| Files (non-component) | camelCase | `accounts.ts` |
|
|
20
|
+
| Functions / Variables | camelCase | `getAccounts()`, `accountId` |
|
|
21
|
+
| Constants | UPPER_SNAKE_CASE | `MAX_POINTS` |
|
|
22
|
+
| Folders | kebab-case | `lib/db-client/` |
|
|
23
|
+
| Booleans | `is` / `has` prefix | `isLoading`, `hasError` |
|
|
24
|
+
| Event handlers | `on` prefix | `onClick`, `onSubmit` |
|
|
25
|
+
|
|
26
|
+
## 2. TypeScript
|
|
27
|
+
|
|
28
|
+
- Always `.ts` / `.tsx`. Never `.js` / `.jsx` in source.
|
|
29
|
+
- Explicit types on EVERY function parameter and return value. No "rely on inference for top-level signatures".
|
|
30
|
+
- The `any` type is FORBIDDEN. When the type is genuinely unknown, use `unknown` and narrow.
|
|
31
|
+
- Shared types live in the project's shared package (`packages/shared` or equivalent) when consumed by multiple apps; otherwise in a local `types/` directory.
|
|
32
|
+
- `as` casts are last-resort. Prefer type guards.
|
|
33
|
+
|
|
34
|
+
## 3. Error handling — Result pattern
|
|
35
|
+
|
|
36
|
+
Service functions return a Result tuple, not throw exceptions:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
type Result<T> = { data: T; error: null } | { data: null; error: string };
|
|
40
|
+
|
|
41
|
+
async function getAccounts(userId: string): Promise<Result<Account[]>> {
|
|
42
|
+
const { data, error } = await db.from('accounts').select().eq('user_id', userId);
|
|
43
|
+
if (error) {
|
|
44
|
+
logError(error, { context: 'getAccounts', userId });
|
|
45
|
+
return { data: null, error: error.message };
|
|
46
|
+
}
|
|
47
|
+
return { data, error: null };
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3.1 Why Result-pattern (not exceptions)
|
|
52
|
+
|
|
53
|
+
- Forces the caller to handle the error case at the call site.
|
|
54
|
+
- Type system surfaces the error path in the function signature.
|
|
55
|
+
- Avoids "try/catch the world" patterns that swallow errors.
|
|
56
|
+
- Stack traces are not the primary error-comm channel; the structured error string is.
|
|
57
|
+
|
|
58
|
+
### 3.2 The structured logger rule
|
|
59
|
+
|
|
60
|
+
Always use the project's `logError()` (or equivalent structured-logging utility) — never raw `console.error`. Why:
|
|
61
|
+
|
|
62
|
+
- `logError()` includes context (user id, request id, feature flag, environment).
|
|
63
|
+
- `logError()` ships to the project's observability platform (your error-aggregation service of choice).
|
|
64
|
+
- Raw `console.error` gets lost in serverless function logs and produces no alert.
|
|
65
|
+
|
|
66
|
+
## 4. Error UX patterns
|
|
67
|
+
|
|
68
|
+
| Surface | Pattern |
|
|
69
|
+
|---|---|
|
|
70
|
+
| Page-level fatal error (load failed) | Project's error-banner component (e.g., `ErrorBanner`) |
|
|
71
|
+
| Action feedback (save success, validation error) | Project's toast utility (e.g., `toast.success()` / `toast.error()`) |
|
|
72
|
+
| Form field error | Inline error message under field |
|
|
73
|
+
| API response | Result-pattern JSON: `{ data, error }` |
|
|
74
|
+
|
|
75
|
+
User-facing error messages MUST be translated (i18n key, not raw error string from the service). The raw error goes to the logger; the translated message goes to the UI.
|
|
76
|
+
|
|
77
|
+
## 5. Forbidden
|
|
78
|
+
|
|
79
|
+
- Hardcoded secrets / API keys / tokens — load from environment at runtime.
|
|
80
|
+
- Service-role / admin keys in client code — server-side only.
|
|
81
|
+
- Untyped escape hatches (`any`, `as unknown as Foo`).
|
|
82
|
+
- UI libraries beyond the project's approved set (the rule index lists them — typically a single primary library).
|
|
83
|
+
- Hardcoded user-facing strings on multi-locale projects (use translation keys — see `recipes/i18n.md`).
|
|
84
|
+
- Duplicated business logic between apps in a monorepo (it goes in shared — see `recipes/monorepo.md`).
|
|
85
|
+
|
|
86
|
+
## 6. Folder conventions (TypeScript app)
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
apps/<app>/
|
|
90
|
+
├── app/ ← Next.js app router (or equivalent framework structure)
|
|
91
|
+
├── components/ ← Reusable UI components
|
|
92
|
+
│ ├── common/ ← Cross-feature primitives (ErrorBanner, etc.)
|
|
93
|
+
│ └── <feature>/ ← Feature-scoped components
|
|
94
|
+
├── lib/
|
|
95
|
+
│ ├── i18n/ ← Translation hook + per-app local copy
|
|
96
|
+
│ └── utils/ ← Pure utilities (errorLogger, formatters, etc.)
|
|
97
|
+
├── services/ ← Service-layer functions (Result pattern)
|
|
98
|
+
└── types/ ← Local types (not consumed by other apps)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The recipe is the rule; the project's framework dictates the actual structure.
|
|
102
|
+
|
|
103
|
+
## 7. Test discipline
|
|
104
|
+
|
|
105
|
+
| Test type | Location | When required |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| Unit | `<file>.test.ts` co-located | New service function, new utility |
|
|
108
|
+
| E2E functional | `apps/<app>/e2e/functional/` | New page / flow / API endpoint |
|
|
109
|
+
| Visual smoke | `apps/<app>/e2e/visual/` | New page / screen |
|
|
110
|
+
| Snapshot | `<feature>/__tests__/` | New email template, new render-only artifact |
|
|
111
|
+
|
|
112
|
+
The full test sync rule is in `quality-gates.md` Q3. This recipe enumerates the test types specifically for the TypeScript stack.
|
|
113
|
+
|
|
114
|
+
## 8. Cross-tool enforcement
|
|
115
|
+
|
|
116
|
+
| Mechanism | Where |
|
|
117
|
+
|---|---|
|
|
118
|
+
| TypeScript strict mode | `tsconfig.json` `"strict": true` |
|
|
119
|
+
| `any` ban | ESLint rule (`@typescript-eslint/no-explicit-any`) |
|
|
120
|
+
| Naming conventions | ESLint rule (`@typescript-eslint/naming-convention`) |
|
|
121
|
+
| Result pattern | Reviewer checklist + `coding-conventions` rule loaded into tool context |
|
|
122
|
+
| Hardcoded string ban | ESLint custom rule (when present) + reviewer checklist |
|
|
123
|
+
| `console.error` ban | ESLint rule + reviewer checklist |
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe_id: database-discipline
|
|
3
|
+
recipe_name: "Relational DB discipline — access control, idempotent migrations, drift safety"
|
|
4
|
+
applies_when: "Project has a relational store with migrations and an environment split (dev/prod)"
|
|
5
|
+
severity: STRONG (when installed)
|
|
6
|
+
linked_rules:
|
|
7
|
+
- quality-gates
|
|
8
|
+
ships_hookify:
|
|
9
|
+
- warn-create-table-without-access-control
|
|
10
|
+
- warn-security-definer-without-search-path
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Recipe — Database Discipline
|
|
14
|
+
|
|
15
|
+
> Opt-in recipe. Install on projects backed by a relational store that uses migrations and runs a dev/prod environment split. It encodes four disciplines that prevent the most common (and highest-severity) data-layer failures: missing access control, non-idempotent migrations, brittle seeds, and silent production drift. Projects without a relational store skip this recipe.
|
|
16
|
+
|
|
17
|
+
## 1. Access control on every table
|
|
18
|
+
|
|
19
|
+
Every table enables row-level (or equivalent) access control. Access without an explicit policy is a security hole, not a convenience.
|
|
20
|
+
|
|
21
|
+
- Enable row-level access control on the table at creation time — never as a follow-up "we'll add it later" step.
|
|
22
|
+
- Every policy names the allowed role explicitly. A policy with no role, or a permissive / PUBLIC default, grants access to everyone.
|
|
23
|
+
- No table ships with a permissive default. If a row should be readable by a tier, name that tier in the policy.
|
|
24
|
+
- Read-only reference tables (lookup tables, enums-as-rows) may scope SELECT broadly, but they still enable access control — broad SELECT is a deliberate policy, not an absence of one.
|
|
25
|
+
|
|
26
|
+
## 2. Idempotent migrations
|
|
27
|
+
|
|
28
|
+
A migration must be safe to re-run. Re-application happens routinely — replays, partial failures, parallel environments — and a non-idempotent migration turns a retry into an outage.
|
|
29
|
+
|
|
30
|
+
- Create with guards: `CREATE … IF NOT EXISTS`.
|
|
31
|
+
- Alter with guards: `ADD COLUMN IF NOT EXISTS`, and equivalent existence checks for indexes / constraints.
|
|
32
|
+
- Insert with conflict handling: `ON CONFLICT DO NOTHING` (or an explicit upsert) for seed / lookup rows.
|
|
33
|
+
- Guard any data backfill so a second run is a no-op.
|
|
34
|
+
|
|
35
|
+
If running the migration twice would fail or double-write, it is not idempotent — fix it before it ships.
|
|
36
|
+
|
|
37
|
+
## 3. Seed by name-lookup, not hardcoded ID
|
|
38
|
+
|
|
39
|
+
Foreign-key seeds resolve their target by a stable natural key (a name, a slug, a code), never a literal ID.
|
|
40
|
+
|
|
41
|
+
- IDs differ across environments — an auto-generated primary key in dev is not the same value in prod. A hardcoded ID silently points at the wrong row (or nothing) in another environment.
|
|
42
|
+
- Resolve the target row by its natural key at seed time, then use the resolved ID. The natural key is the stable contract across environments; the ID is not.
|
|
43
|
+
- This keeps the same seed script correct in dev, staging, and prod without per-environment edits.
|
|
44
|
+
|
|
45
|
+
## 4. Pre-apply drift verification
|
|
46
|
+
|
|
47
|
+
Before applying a dev-verified schema or data change to production, verify that production's current state still matches the baseline the change was built against. Production drifts (hotfixes, manual edits, concurrent writes); applying a change blind can overwrite that drift.
|
|
48
|
+
|
|
49
|
+
- Re-query production's pre-state for the affected range (the rows / schema the change touches) immediately before applying.
|
|
50
|
+
- Diff it against the dev baseline: row count, the set of keys, and the pre-state values.
|
|
51
|
+
- On any drift → abort and surface the difference. Never overwrite a drifted production silently.
|
|
52
|
+
- Apply only when parity holds. After applying, verify the post-state matches the intended result.
|
|
53
|
+
|
|
54
|
+
The discipline is: dev verifies the change is correct; the pre-apply diff verifies production is still the world the change expects.
|
|
55
|
+
|
|
56
|
+
## 5. Shipped hookify (Claude adapter)
|
|
57
|
+
|
|
58
|
+
The Claude adapter ships two recipe-scoped hookify rules that install **only when this recipe is selected** (`--recipes=database-discipline`):
|
|
59
|
+
|
|
60
|
+
| Rule | Event | Action | Catches |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| `warn-create-table-without-access-control` | file | warn | A `CREATE TABLE` in a `.sql` file with no row-level access control enabled in the same change (section 1) |
|
|
63
|
+
| `warn-security-definer-without-search-path` | file | warn | A `SECURITY DEFINER` function with no explicit `SET search_path`, leaving it open to schema-shadowing privilege hijack |
|
|
64
|
+
|
|
65
|
+
These are stack-shaped (SQL-specific), so they are gated behind this recipe rather than shipped always-on. See the CONDUCTOR repo's `adapters/claude/hookify-templates/.recipe-scoped` and `docs/DESIGN-DECISIONS.md` ADR-028.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe_id: debugging
|
|
3
|
+
recipe_name: "Systematic Debugging (Root-Cause-First)"
|
|
4
|
+
applies_when: "any bug, test failure, unexpected behavior, or production incident — whenever the temptation to 'just try something' arises"
|
|
5
|
+
severity: STRONG (when installed)
|
|
6
|
+
linked_rules:
|
|
7
|
+
- meta-discipline
|
|
8
|
+
- spec-as-you-go
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Recipe — Systematic Debugging
|
|
12
|
+
|
|
13
|
+
> Opt-in recipe. Install on any project where bugs are a reality (i.e., all of them). Especially valuable on codebases where time pressure makes guess-and-check feel faster — it isn't.
|
|
14
|
+
|
|
15
|
+
## When to Apply
|
|
16
|
+
|
|
17
|
+
Any technical issue where behavior diverges from expectation:
|
|
18
|
+
|
|
19
|
+
- Test failures (unit, integration, E2E)
|
|
20
|
+
- Production bugs
|
|
21
|
+
- Unexpected output or side effects
|
|
22
|
+
- Build or compilation failures
|
|
23
|
+
- Performance regressions
|
|
24
|
+
- Integration failures between services
|
|
25
|
+
|
|
26
|
+
**Apply especially when:**
|
|
27
|
+
|
|
28
|
+
- Under time pressure — urgency makes guessing tempting, which is when it causes the most damage
|
|
29
|
+
- "One quick fix" seems obvious — obvious fixes treat symptoms
|
|
30
|
+
- You have already tried at least one fix — if the first fix failed, the root cause is not what you thought
|
|
31
|
+
- You do not fully understand why the issue occurs
|
|
32
|
+
|
|
33
|
+
## Pattern — Four Phases
|
|
34
|
+
|
|
35
|
+
Phases are sequential. Do not advance to the next phase until the current phase is complete.
|
|
36
|
+
|
|
37
|
+
### Phase 1 — Reproduce
|
|
38
|
+
|
|
39
|
+
Establish a deterministic, minimal reproduction. A bug you cannot reproduce consistently cannot be verified as fixed.
|
|
40
|
+
|
|
41
|
+
Steps:
|
|
42
|
+
1. Read the full error message and stack trace — they frequently contain the exact file, line, and cause
|
|
43
|
+
2. Write down the exact steps that trigger the issue
|
|
44
|
+
3. Confirm the issue occurs every time those steps are followed
|
|
45
|
+
4. If not reproducible: add logging at component boundaries to gather evidence before continuing
|
|
46
|
+
|
|
47
|
+
For multi-component systems (API → service → database, CI → build → signing), add boundary logging at each layer before forming any hypothesis:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Example: trace where in a pipeline a value goes wrong
|
|
51
|
+
echo "=== component A output: ${VALUE:+SET}${VALUE:-UNSET} ==="
|
|
52
|
+
# ... run the pipeline ...
|
|
53
|
+
echo "=== component B received: $RECEIVED ==="
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Run once to gather evidence. Identify which layer breaks. Then investigate that specific layer.
|
|
57
|
+
|
|
58
|
+
### Phase 2 — Isolate
|
|
59
|
+
|
|
60
|
+
Narrow the search space before forming a hypothesis.
|
|
61
|
+
|
|
62
|
+
Steps:
|
|
63
|
+
1. Find working code similar to the broken code in the same codebase
|
|
64
|
+
2. Compare working vs. broken — list every difference, however small
|
|
65
|
+
3. Check recent changes: `git log --oneline -20`, `git diff HEAD~5`
|
|
66
|
+
4. Identify what changed that could cause this (new dependency, config change, environment difference)
|
|
67
|
+
5. Use `git bisect` for regressions that appeared between two known-good commits
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Binary search for the commit that introduced a regression
|
|
71
|
+
git bisect start
|
|
72
|
+
git bisect bad HEAD
|
|
73
|
+
git bisect good <last-known-good-commit>
|
|
74
|
+
# git bisect will check out commits; run your test and mark good/bad
|
|
75
|
+
git bisect run npx vitest run path/to/failing.test.ts
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Phase 3 — Hypothesize and Verify
|
|
79
|
+
|
|
80
|
+
Form one specific hypothesis. Test it minimally.
|
|
81
|
+
|
|
82
|
+
1. Write down: "I believe X is the root cause because Y"
|
|
83
|
+
2. Make the smallest possible change that would confirm or refute this hypothesis
|
|
84
|
+
3. Run the test — did it work?
|
|
85
|
+
- Yes → proceed to Phase 4
|
|
86
|
+
- No → form a NEW hypothesis; do NOT layer additional changes on top of the failed one
|
|
87
|
+
4. If you genuinely do not know: say so, add more logging, return to Phase 1 with new evidence
|
|
88
|
+
|
|
89
|
+
One variable at a time. Multiple simultaneous changes make it impossible to know which change fixed (or broke) something.
|
|
90
|
+
|
|
91
|
+
### Phase 4 — Fix and Regression-Test
|
|
92
|
+
|
|
93
|
+
Fix only the confirmed root cause. Then lock it in with a test.
|
|
94
|
+
|
|
95
|
+
1. Write a failing test that reproduces the bug (apply `core/recipes/tdd.md`)
|
|
96
|
+
2. Implement the minimal fix
|
|
97
|
+
3. Confirm the test passes
|
|
98
|
+
4. Run the full suite — confirm no regression introduced
|
|
99
|
+
5. If the fix does not work: return to Phase 1 with new evidence
|
|
100
|
+
|
|
101
|
+
**If three or more fixes have failed:** stop attempting fixes. The root cause may be architectural — a coupling or shared-state assumption that no local fix can address. Discuss with your team before attempting another fix.
|
|
102
|
+
|
|
103
|
+
After a confirmed fix, update the relevant spec or known-issues section (spec-as-you-go). Bugs that recur after being fixed typically had no regression test and no spec update.
|
|
104
|
+
|
|
105
|
+
## Tool Reference
|
|
106
|
+
|
|
107
|
+
| Tool | Use |
|
|
108
|
+
|---|---|
|
|
109
|
+
| `git bisect` | Binary-search commits to find regression introduction point |
|
|
110
|
+
| `git stash` | Temporarily remove local changes to verify they are or are not the cause |
|
|
111
|
+
| `git diff HEAD~N` | See what changed in the last N commits |
|
|
112
|
+
| Structured logging | Add `console.log` / logger at component boundaries during Phase 1; remove before commit |
|
|
113
|
+
| Debugger / breakpoints | Confirm data values at specific points in the call stack |
|
|
114
|
+
| Minimal reproduction test | Isolate the failing behavior in the smallest possible test case |
|
|
115
|
+
|
|
116
|
+
## Conductor Integration
|
|
117
|
+
|
|
118
|
+
**meta-discipline (M1 — verify before claim)**: A fix is not complete until the test passes and the full suite is green. Do not report "fixed" before verifying.
|
|
119
|
+
|
|
120
|
+
**spec-as-you-go (W3)**: Bug fixes update the spec. If the bug was a known edge case not previously documented, add it to the spec's known-issues section. If the fix changes behavior, update the relevant spec section.
|
|
121
|
+
|
|
122
|
+
**workflow.md W2 (build phase)**: When a build-phase failure occurs, invoke this recipe before proposing any code change. The recipe gates Phase 4 on Phases 1-3 being complete.
|
|
123
|
+
|
|
124
|
+
**tdd.md**: Phase 4 of this recipe directly invokes the TDD cycle — write the failing test first, then fix. The two recipes are complementary: TDD prevents bugs; this recipe resolves them when they occur anyway.
|
|
125
|
+
|
|
126
|
+
## Anti-Patterns
|
|
127
|
+
|
|
128
|
+
| Anti-pattern | Why it fails |
|
|
129
|
+
|---|---|
|
|
130
|
+
| "Just try X and see if it works" | Sets a guess-and-check precedent. First guess being right is luck; subsequent guesses are compounding debt. |
|
|
131
|
+
| Suppress the error with try/catch | Treats the symptom. The root cause continues to fire; you just stopped hearing about it. |
|
|
132
|
+
| Multiple simultaneous fixes | If the bug disappears, you cannot know which fix resolved it. If it persists, you have added noise. |
|
|
133
|
+
| Asking an LLM before gathering evidence | Without a minimal reproduction and specific error output, LLM responses are pattern-matched hallucinations, not diagnosis. |
|
|
134
|
+
| Time-pressure skip of Phase 1-2 | Systematic debugging is faster than guess-and-check. Urgency is when discipline matters most, not when to abandon it. |
|
|
135
|
+
| Fix without a regression test | The bug will recur. A fix with no test is a temporary suppression. |
|
|
136
|
+
| "One more fix attempt" after two failures | Three failures indicate the hypothesis model is wrong, not that a better fix exists within the same model. |
|
|
137
|
+
|
|
138
|
+
## Cross-References
|
|
139
|
+
|
|
140
|
+
- `core/universal-rules/meta-discipline.md` — M1 verify before claim: fix is not done until verified
|
|
141
|
+
- `core/universal-rules/spec-as-you-go.md` — bug fixes update specs and known-issues sections
|
|
142
|
+
- `core/recipes/tdd.md` — Phase 4 creates the failing test; TDD cycle drives the fix
|
|
143
|
+
- Root-cause-first / four-phase debugging is long-standing public practice; this recipe is independently written. Its structure was informed in part by the **Superpowers** project (idea-level; no text reproduced) — see `THIRD_PARTY_NOTICES.md`.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe_id: design-system
|
|
3
|
+
recipe_name: "Design-token discipline"
|
|
4
|
+
applies_when: "Project has a design-token system (color/spacing/typography tokens)"
|
|
5
|
+
severity: STRONG (when installed)
|
|
6
|
+
ships_hookify:
|
|
7
|
+
- warn-raw-hex-instead-of-token
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Recipe — Design-Token Discipline
|
|
11
|
+
|
|
12
|
+
> Opt-in recipe. Install on projects that maintain a design-token system (color / spacing / typography tokens). Projects with no token system skip this recipe.
|
|
13
|
+
|
|
14
|
+
## 1. Tokens, not literals
|
|
15
|
+
|
|
16
|
+
Component styling references design tokens (color / spacing / typography), never raw hex colors or magic pixel values. A raw literal defeats theming: it cannot follow a dark-mode switch, a brand re-skin, or a density change, and it silently drifts from the rest of the system. Every visual value a component renders should resolve through a named token, so a single token edit propagates everywhere consistently.
|
|
17
|
+
|
|
18
|
+
## 2. Out of scope for this recipe
|
|
19
|
+
|
|
20
|
+
Which UI library, which icon pack, and which specific token names a project uses are **project-local** decisions, not framework policy (ADR-018). CONDUCTOR does not ship a banlist of libraries or a fixed set of token names — those belong in the adopter project. This recipe enforces only the *principle*: a token over a literal. The adopter supplies the concrete token vocabulary; the recipe supplies the discipline.
|
|
21
|
+
|
|
22
|
+
## 3. Shipped hookify
|
|
23
|
+
|
|
24
|
+
This recipe ships one recipe-scoped hookify rule, emitted only when `design-system` is selected via `--recipes`:
|
|
25
|
+
|
|
26
|
+
| Template | Event | Action | Trigger |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| `warn-raw-hex-instead-of-token` | file | warn | An inline raw hex color (`#rrggbb`) added to a `.tsx` / `.jsx` / `.css` / `.scss` file |
|
|
29
|
+
|
|
30
|
+
The rule warns (it never blocks): an intentional one-off outside the token system stays possible, but the author is prompted to justify it rather than drift by accident.
|