From b5820a9a20a04d9ba91b160012c497161196861c Mon Sep 17 00:00:00 2001 From: Blake Wood Date: Fri, 25 Sep 2026 15:40:07 -0700 Subject: [PATCH 1/2] docs(skills): add writing style guides and rewrite base skills in that style - tasks.md: add a Writing style section for thread comments - ai-wiki.md: add a Writing style section for wiki pages - Rewrite all base skills: task-named headings, tables for enumerations, fenced code blocks, no hard wraps, no em dashes - specs.md: spec template headings use / and : instead of em dashes --- .../templates/skills/ai-wiki.md | 49 ++++++++--- .../templates/skills/engine-api.md | 59 +++++++------ .../modula_services/templates/skills/specs.md | 55 ++++++------ .../modula_services/templates/skills/tasks.md | 87 ++++++++++++------- .../templates/skills/workflows.md | 53 ++++++----- .../templates/skills/worktrees.md | 38 ++++---- 6 files changed, 194 insertions(+), 147 deletions(-) diff --git a/crates/modula_services/templates/skills/ai-wiki.md b/crates/modula_services/templates/skills/ai-wiki.md index a30e7d8..5cb5ccc 100644 --- a/crates/modula_services/templates/skills/ai-wiki.md +++ b/crates/modula_services/templates/skills/ai-wiki.md @@ -1,12 +1,41 @@ ## Skill: AI Wiki -The workspace `wiki/` is an agent-maintained knowledge base of durable codebase -facts — architecture, conventions, quirks — **never** task-specific commentary. - -- **Before working**, read `wiki/index.md` and any pages relevant to the - projects/components you'll touch. Cite pages as `[[link]]` in specs. -- **When your work surfaces a durable fact** that contradicts, fills a gap in, - or extends the wiki: **read `wiki/SCHEMA.md` first**, then update the relevant - page(s), keep `wiki/index.md` in sync, and append an entry to `wiki/log.md`. -- Keep it durable: if a fact only matters to this task, it belongs in the spec - or a thread comment, not the wiki. +The workspace `wiki/` is an agent-maintained knowledge base of durable codebase facts: architecture, conventions, quirks. It **never** holds task-specific commentary. + +- **Before you work**, read `wiki/index.md` and the pages for the projects and components you'll touch. Cite pages as `[[link]]` in specs. +- **When you find a durable fact** that contradicts, fills a gap in, or extends the wiki, **read `wiki/SCHEMA.md` first**. Then update the relevant pages, keep `wiki/index.md` in sync, and append an entry to `wiki/log.md`. +- **Keep it durable.** A fact that matters only to this task belongs in the spec or a thread comment, not the wiki. + +### Writing style + +Agents read wiki pages to act. Write terse, factual, instructional pages. + +**Page shape** + +- H1 title in sentence case, then a 1–2 sentence intro stating what the page covers and when it's relevant. +- Order sections: what it is → reference → how to → when it breaks. Skip any that don't apply. +- Name sections by task: "Run the migrations", not "Migrations". Don't restate the heading in the first sentence. Add the next fact. +- Keep one topic per page. Split a page when it covers two things, and link the halves. + +**Sentences** + +- Lead with the fact. Cut the lead-in ("In order to understand…"). +- Imperative and second person: "Run `make db`", not "We run `make db`" or "`make db` should be run". +- One idea per sentence. Split a rule from its exception. +- Cut filler: `simply`, `just`, `easily`, `powerful`, `robust`, `note that`, `it's important to`. +- No em dashes. Use a full stop, colon, or comma. + +**Formatting** + +- Numbered lists for ordered steps, bullets for everything else. +- Tables for anything that enumerates: flags, env vars, fields, states, exit codes. +- Code, paths, commands, and identifiers in backticks. Placeholders in ALL-CAPS: `modula task get TASK_ID`. +- Fenced code blocks carry a language tag. +- Link text describes the target. Link once, where the topic comes up. +- No callouts or alert boxes unless ignoring the point breaks something. + +**Accuracy** + +- Write only what you verified in code or by running it. If something is unknown, leave it out or mark it `unverified`. +- Show real commands and real output. Invented output goes stale unnoticed. +- Document the failure: error text, cause, fix. A happy-path-only page is half a page. diff --git a/crates/modula_services/templates/skills/engine-api.md b/crates/modula_services/templates/skills/engine-api.md index 89ea9de..f955eaf 100644 --- a/crates/modula_services/templates/skills/engine-api.md +++ b/crates/modula_services/templates/skills/engine-api.md @@ -1,29 +1,34 @@ ## Skill: Engine CLI -All workspace state lives in the engine and is reached through the `modula` CLI. -The engine URL and the current workspace are detected automatically — you never -pass them. - -Reads print formatted text (read it directly; do not parse as JSON): - - modula task list # all tasks - modula task get # one task with its variants - modula config get # pipeline keys, projects, providers, agents - modula comment list # a task's thread - -Writes take a single JSON body argument: - - modula task create '{ … }' - modula task patch '{"status":""}' - modula variant create '{"count":2}' - modula variant patch '{"status":"in_progress"}' - modula variant patch '{"action":"accept"}' - modula comment create '{"author":"","kind":"comment","content":"…"}' - -Conventions: -- Fill `` / `` from the **Inputs for this run** block in your - prompt. Ids are UUIDs minted by the engine — never invent them. -- Read valid pipeline keys from `modula config get`; never hardcode status keys. -- A non-zero exit means the call failed — stop and surface the error. -- Every write emits an event the dispatcher routes to the next agent; you never - spawn other agents yourself. +All workspace state lives in the engine. Reach it through the `modula` CLI. The CLI detects the engine URL and the current workspace, so never pass them. + +### Read state + +Reads print formatted text. Read it directly; don't parse it as JSON. + +```sh +modula task list # all tasks +modula task get # one task with its variants +modula config get # pipeline keys, projects, providers, agents +modula comment list # a task's thread +``` + +### Write state + +Writes take one JSON body argument. + +```sh +modula task create '{ … }' +modula task patch '{"status":""}' +modula variant create '{"count":2}' +modula variant patch '{"status":"in_progress"}' +modula variant patch '{"action":"accept"}' +modula comment create '{"author":"","kind":"comment","content":"…"}' +``` + +### Rules + +- Take `` and `` from the **Inputs for this run** block in your prompt. The engine mints ids as UUIDs. Never invent one. +- Read valid pipeline keys from `modula config get`. Never hardcode status keys. +- A non-zero exit means the call failed. Stop and report the error. +- Every write emits an event, and the dispatcher routes it to the next agent. Never spawn agents yourself. diff --git a/crates/modula_services/templates/skills/specs.md b/crates/modula_services/templates/skills/specs.md index 9b61e57..378a1d1 100644 --- a/crates/modula_services/templates/skills/specs.md +++ b/crates/modula_services/templates/skills/specs.md @@ -1,33 +1,29 @@ ## Skill: Specs -Spec folders are the durable record of a task's design and progress. They live -under the workspace root, named by human-readable slug (never UUIDs): +A spec folder is the durable record of one variant's design and progress. It lives under the workspace root and is named by slug, never by UUID. -``` +```text specs//v/ - phases.md # variant overview + phase checklist (source of truth) - phase-1-plan.md # scope / approach / notes for phase 1 + phases.md # variant overview and phase checklist (source of truth) + phase-1-plan.md # scope, approach, and notes for phase 1 phase-1-task.md # actionable checklist for phase 1 phase-2-plan.md phase-2-task.md ... ``` -`` is the task's external id + title, slugified (e.g. -`mod-0001-some-new-adjustment`); `` is the variant's 1-based position. -Your run's prompt names the exact folder ("This run's spec folder is …") — use -that path; don't construct it yourself. `phases.md` lists phases as `- [ ]` -(pending) / `- [x]` (done) and names every project under "Projects touched". - -### Templates +- `` is the task's external id and title, slugified: `mod-0001-some-new-adjustment`. +- `` is the variant's 1-based position. +- Your prompt names the exact folder ("This run's spec folder is …"). Use that path. Don't construct it yourself. +- `phases.md` marks phases `- [ ]` (pending) or `- [x]` (done) and lists every project under "Projects touched". -`phases.md`: +### Write `phases.md` ```markdown # ## Problem -What is broken / missing / requested. Quote the task. +What is broken, missing, or requested. Quote the task. ## Approach The high-level approach this variant takes. One paragraph. @@ -37,11 +33,11 @@ Names must match `projects[].name` in `/config`. If none, say so and stop. - project: changes: - - path/to/file — what changes + - path/to/file: what changes ## Phases -- [ ] phase-1 — -- [ ] phase-2 — +- [ ] phase-1: +- [ ] phase-2: ## Risks & tradeoffs - vs other variants: … @@ -52,13 +48,13 @@ Names must match `projects[].name` in `/config`. If none, say so and stop. - integration / manual: … ``` -`phase-N-plan.md`: +### Write `phase-N-plan.md` ```markdown -# — — phase-N — +# / / phase-N: ## Scope -What this phase delivers; what it intentionally defers. +What this phase delivers and what it defers. ## Approach One paragraph. @@ -67,22 +63,21 @@ One paragraph. Implementation hints, edge cases, references. ``` -`phase-N-task.md`: +### Write `phase-N-task.md` ```markdown -# — — phase-N — Tasks +# / / phase-N: Tasks - [ ] - [ ] -- [ ] Lint / typecheck / tests pass +- [ ] Lint, typecheck, and tests pass - [ ] Self-review diff ``` -### Ownership +### Who edits what -- `phases.md` — the worker checks phases off and appends "Done" / "Rework round - N" sections; never rewrite the researcher's design. -- `phase-N-plan.md` — append-only for the worker (add a `## Deviations` section - if needed). -- `phase-N-task.md` — the worker mutates freely: tick items, add discovered - sub-tasks, strike abandoned ones with a one-line reason. +| File | Worker may | +| --- | --- | +| `phases.md` | Tick phases and append "Done" or "Rework round N" sections. Never rewrite the researcher's design. | +| `phase-N-plan.md` | Append only. Add a `## Deviations` section if needed. | +| `phase-N-task.md` | Edit freely: tick items, add discovered sub-tasks, strike abandoned ones with a one-line reason. | diff --git a/crates/modula_services/templates/skills/tasks.md b/crates/modula_services/templates/skills/tasks.md index 9e0e938..901365d 100644 --- a/crates/modula_services/templates/skills/tasks.md +++ b/crates/modula_services/templates/skills/tasks.md @@ -1,46 +1,71 @@ ## Skill: Tasks, Variants & Comments -### Reading tasks and variants +### Read tasks and variants - modula task get # one task with its variants - modula variant get # one variant (status, position) + owning task - modula comment list # the task thread, then each variant's thread +```sh +modula task get # one task with its variants +modula variant get # one variant (status, position) and its owning task +modula comment list # the task thread, then each variant's thread +``` -A task carries human-owned fields (`approved`, `max_variants`, `worktree`) and a -`variants[]` block. Each variant has a `status` that drives the pipeline. Read -the printed `status:`, `approved:`, and per-variant lines directly. +A task carries human-owned fields (`approved`, `max_variants`, `worktree`) and a `variants[]` block. Each variant's `status` drives the pipeline. Read the printed `status:`, `approved:`, and per-variant lines directly. -### Registering variants (researcher only) +### Register variants (researcher only) - modula variant create '{"count":2}' +```sh +modula variant create '{"count":2}' +``` -The engine mints the UUIDs and prints the created variants (id + position). A -freshly registered variant has NO status and is NOT workable until promoted. +The engine mints the UUIDs and prints each created variant's id and position. A new variant has **no status** and is not workable until promoted. -### Variant status +### Set a variant's status - # Set a status directly. - modula variant patch '{"status":"in_progress"}' +```sh +# Set a status directly. +modula variant patch '{"status":"in_progress"}' - # Code-reviewer applies a verdict via an action (not a raw status). - modula variant patch '{"action":"accept"}' - # or '{"action":"rework"}' +# Code-reviewer applies a verdict through an action, not a raw status. +modula variant patch '{"action":"accept"}' +modula variant patch '{"action":"rework"}' +``` -`variant patch` takes only the variant id — the CLI resolves the owning task. +`variant patch` takes only the variant id. The CLI resolves the owning task. -### Comments / thread entries +### Post a comment -Threads are **append-only**. Post entries with an `author`, a `kind`, and -`content`. Variant-scoped entries carry `variant` + `round`; task-scoped entries -omit `variant`. +Threads are **append-only**. Every entry has an `author`, a `kind`, and `content`. Variant-scoped entries add `variant` and `round`. Task-scoped entries omit `variant`. - modula comment create \ - '{"author":"","kind":"comment","variant":"","round":N,"content":"…"}' +```sh +modula comment create '{"author":"","kind":"comment","variant":"","round":N,"content":"…"}' +``` -`kind` values: -- `comment` — an observation or note. -- `question` — a question for the human (code-reviewer must post at least one). -- `verdict` — a decision; requires `verdict` set to the agent's allowed values - (e.g. `ACCEPT` / `REQUEST_CHANGES` for code-reviewer, `APPROVE` / `KICK_BACK` - for reviewer; `KICK_BACK` requires `affected_variants`). -- `rework` — the worker's summary of what a rework round fixed. +| `kind` | Use | +| --- | --- | +| `comment` | An observation or note. | +| `question` | A question for the human. Code-reviewer must post at least one. | +| `verdict` | A decision. Set `verdict` to a value your role allows: `ACCEPT` or `REQUEST_CHANGES` for code-reviewer, `APPROVE` or `KICK_BACK` for reviewer. `KICK_BACK` requires `affected_variants`. | +| `rework` | The worker's summary of what a rework round fixed. | + +#### Writing style + +Humans skim threads. Write each entry to be read in seconds. + +- **Lead with the point.** The first line is the finding, question, or decision. No preamble ("I reviewed…", "After looking at…"), no closing recap. +- **One point per entry.** Two unrelated findings are two entries. +- **Bullets over paragraphs.** Numbered list only for ordered steps. Keep formatting flat: no headings, tables, or nested lists. Bold only the single fact the reader must not miss. +- **Short, direct sentences.** Imperative and active voice: "Rename `foo`", not "It might be worth considering renaming `foo`". +- **Cut filler.** Drop `simply`, `just`, `clearly`, `robust`, `note that`, `it's important to`, and hedges like `I think` or `it seems`. +- **Be concrete.** Cite `file:line` and quote only the lines that matter in a fenced block. Put code, paths, and commands in backticks. Give the fix, not only the problem. +- **State only what you verified.** Don't guess at causes or behavior. If you didn't check something, say so in one line. +- **Add new information only.** Don't restate the task, the diff, or earlier entries. Reference them instead. +- **Make questions answerable.** Ask one question and offer the options: "Keep the old endpoint? (a) yes, deprecate later (b) no, remove now". +- **No em dashes.** Use a full stop, colon, or comma. + +Before: + +> After carefully reviewing the changes in this variant, I noticed that there might potentially be an issue with how errors are handled in the sync path. It seems like the error is simply being swallowed, which could make debugging harder down the line, so it would probably be good to consider logging it. + +After: + +> `sync.rs:88` swallows the error from `fetch()`. +> - Log it with `tracing::warn!` or return it. diff --git a/crates/modula_services/templates/skills/workflows.md b/crates/modula_services/templates/skills/workflows.md index 5499d33..2cead6d 100644 --- a/crates/modula_services/templates/skills/workflows.md +++ b/crates/modula_services/templates/skills/workflows.md @@ -1,41 +1,38 @@ ## Skill: Workflows & Roadmap -The roadmap moves a task through a config-driven pipeline. **Never hardcode -status keys** — read the valid keys from config: +The roadmap moves a task through a pipeline defined in config. **Never hardcode status keys.** Read them from config: - modula config get # the `pipeline` section lists every status key +```sh +modula config get # the `pipeline` section lists every status key +``` -### Claiming and transitioning +### Claim and transition work -Claim work by advancing the roadmap (task-level) and/or a variant status before -doing anything else, so concurrent runs don't double-work. +Claim work before doing anything else, so concurrent runs don't duplicate it. Claim by advancing the roadmap (task-level) status, a variant status, or both. - # Roadmap (task-level) status. A body with status / notes / depends_on - # routes to the roadmap; the task's current pipeline status is shown in - # `modula task get`. - modula task patch '{"status":""}' +```sh +# Set the roadmap status. A body with status, notes, or depends_on routes to the roadmap. +modula task patch '{"status":""}' - # Read the task's current roadmap status. - modula task get +# Read the task's current roadmap status. +modula task get +``` -### Typical pipeline flow +### Follow the pipeline -`planning` → `ready_for_research` → `researching` → `ready_for_workers` -(per-variant) → `in_progress` → `ready_for_review` → `in_review` → -`ready_for_acceptance` → human acceptance. Each agent advances only the -transitions it owns; check your role's instructions for which. +`planning` → `ready_for_research` → `researching` → `ready_for_workers` (per variant) → `in_progress` → `ready_for_review` → `in_review` → `ready_for_acceptance` → human acceptance. -### Status semantics +Each agent advances only the transitions it owns. Your role's instructions list yours. -- `needs_clarification` — soft pause; a human answers and flips the task back to - `ready_for_research`. -- `blocked` — hard stop; the task can't proceed as written. Set it with a - `notes` body explaining why (`'{"status":"blocked","notes":"…"}'`); don't - abandon the row silently. +### Pause or stop a task -### Discipline +| Status | Meaning | +| --- | --- | +| `needs_clarification` | Soft pause. A human answers and sets the task back to `ready_for_research`. | +| `blocked` | Hard stop: the task can't proceed as written. Set it with a `notes` body that says why: `'{"status":"blocked","notes":"…"}'`. Never abandon the task silently. | -- Make **one** roadmap-claim write per run (only if not already claimed). -- Only emit transitions your role is allowed to make. -- After your writes, the dispatcher routes the resulting events to the next - agent — don't spawn anything yourself. +### Rules + +- Make **one** roadmap claim per run, and only if the task isn't already claimed. +- Emit only the transitions your role owns. +- The dispatcher routes your writes to the next agent. Never spawn agents yourself. diff --git a/crates/modula_services/templates/skills/worktrees.md b/crates/modula_services/templates/skills/worktrees.md index ea9527f..710a428 100644 --- a/crates/modula_services/templates/skills/worktrees.md +++ b/crates/modula_services/templates/skills/worktrees.md @@ -1,42 +1,39 @@ ## Skill: Worktrees -Each task carries a `worktree` flag (default **true**). +Each task carries a `worktree` flag. It defaults to **true**. -- **Worktree mode** (`worktree: true` or unset): every project gets a dedicated - git worktree + branch, so variants stay isolated. -- **Direct mode** (`worktree: false`): work directly on `base_branch`, no new - branch. The researcher should have produced exactly one variant. +| Mode | When | Behavior | +| --- | --- | --- | +| Worktree | `worktree: true` or unset | Each project gets its own git worktree and branch, so variants stay isolated. | +| Direct | `worktree: false` | Work on `base_branch` with no new branch. The researcher should have produced exactly one variant. | -Branch name: `feature/-v` (slug-based, never UUIDs) — -`` and `` are the same ones in this run's spec folder -(`specs//v/`, named in your prompt). E.g. spec folder -`specs/mod-0001-some-new-adjustment/v1/` → branch -`feature/mod-0001-some-new-adjustment-v1`. +Name the branch `feature/-v`. Use slugs, never UUIDs. `` and `` match your spec folder (`specs//v/`, named in your prompt). Spec folder `specs/mod-0001-some-new-adjustment/v1/` gives branch `feature/mod-0001-some-new-adjustment-v1`. -### Setting up (worker) +`` and `` come from `.projects` in `/config`. -```bash +### Set up (worker) + +```sh cd + # Worktree mode: git worktree add .worktrees/ -b # fresh -git worktree add .worktrees/ # rework / reuse +git worktree add .worktrees/ # rework or reuse # Direct mode: git checkout && git pull --ff-only git tag -f modula/-v/start # fresh only; tree must be clean ``` -`` and `` come from `/config` `.projects`. - -### Inspecting the diff (reviewer) +### Inspect the diff (reviewer) -```bash +```sh # Worktree mode: cd /.worktrees/ git log .. git diff .. -# Direct mode (the start tag marks the pre-work commit): +# Direct mode. The start tag marks the commit before work began. cd git log modula/-v/start.. git diff modula/-v/start.. @@ -45,6 +42,5 @@ git diff modula/-v/start.. ### Rules - **Never push to a remote** (`git push`, `gh pr create`, …). -- Stay scoped to your own variant's worktree(s) / checkout; treat every other - variant's worktree as read-only. -- Commit incrementally per each project's commit style. +- Work only in your own variant's worktrees or checkout. Treat every other variant's worktree as read-only. +- Commit incrementally, following each project's commit style. From 8c8db269562acdf6b6681f6b1e4378722398fb84 Mon Sep 17 00:00:00 2001 From: Blake Wood Date: Fri, 25 Sep 2026 15:41:06 -0700 Subject: [PATCH 2/2] docs: rewrite CLAUDE.md in the skills writing style --- CLAUDE.md | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c7b3874..10fcb96 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,22 +1,21 @@ -# Modula — Dashboard repo (Rust) +# Modula: dashboard repo (Rust) -One-binary desktop app for the Modula AI software factory. Structured state lives -in a single global SQLite DB at `~/.modula/db.sqlite`; markdown artifacts (spec -folders, logs, wiki) live under `~/.modula//`. +One-binary desktop app for the Modula AI software factory. -The engine serves gRPC over a local IPC socket — no TCP port. The desktop app and -the `modula` CLI are both clients of it. +- Structured state lives in one global SQLite DB at `~/.modula/db.sqlite`. +- Markdown artifacts (spec folders, logs, wiki) live under `~/.modula//`. +- The engine serves gRPC over a local IPC socket, not a TCP port. The desktop app and the `modula` CLI are both its clients. ## Read before editing -- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — crate layout, where things - live, and the rules that govern edits. **Start here.** -- [`docs/PLUGINS.md`](docs/PLUGINS.md) — the plugin seam and the - open-source/proprietary split (`plugins/remote`, `../modula-plugins`). -- [`docs/CLI.md`](docs/CLI.md) — the `modula` command reference. -- [`docs/MODULA.md`](docs/MODULA.md) — requirements, packaging, configuration. +| Doc | Covers | +| --- | --- | +| [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | Crate layout, where things live, and the rules for edits. **Start here.** | +| [`docs/PLUGINS.md`](docs/PLUGINS.md) | The plugin seam and the open-source/proprietary split (`plugins/remote`, `../modula-plugins`). | +| [`docs/CLI.md`](docs/CLI.md) | The `modula` command reference. | +| [`docs/MODULA.md`](docs/MODULA.md) | Requirements, packaging, configuration. | -## Run / dev +## Run and develop ```bash bash scripts/dev.sh # engine + Vite + Tauri shell @@ -28,25 +27,24 @@ cargo test --workspace -- --test-threads=1 # single-threaded: each E2E test bo cargo tauri dev --manifest-path apps/desktop/src-tauri/Cargo.toml # shell only ``` -## Before committing +## Pass CI before committing -Run what CI gates on, or the PR will fail: +Run what CI gates on, or the PR fails. -- Rust: `cargo fmt --all`, then `cargo clippy --workspace --all-targets -- -D warnings` -- Frontend (`apps/desktop`): `pnpm exec biome check --write .`, then `pnpm build` +- Rust: `cargo fmt --all`, then `cargo clippy --workspace --all-targets -- -D warnings`. +- Frontend (`apps/desktop`): `pnpm exec biome check --write .`, then `pnpm build`. -### Commit messages +### Write the commit message -- Conventional Commits: `[optional scope]: ` (`feat`, `fix`, - `docs`, `refactor`, `chore`, `test`, `perf`, `ci`). -- One line; add a short body only when the *why* isn't obvious from the diff. +- Use Conventional Commits: `[optional scope]: `. Types: `feat`, `fix`, `docs`, `refactor`, `chore`, `test`, `perf`, `ci`. +- Write one line. Add a short body only when the diff doesn't show the *why*. - No `Co-Authored-By` trailer. -``` +```text feat(conversations): derive chat title from first user message fix(spawn): validate provider config_dir before launching child ``` -### Pull requests +### Write the pull request -Concise: what changed and why, not a play-by-play. No co-author line. +State what changed and why, not a play-by-play. No co-author line.