@oneie/claude 0.8.0 → 0.10.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/.claude-plugin/plugin.json +1 -1
- package/agents/abm-strategist.md +67 -1
- package/agents/ads-meta.md +67 -1
- package/agents/analyst.md +67 -1
- package/agents/animator.md +108 -0
- package/agents/architect.md +269 -20
- package/agents/brand-guardian.md +67 -1
- package/agents/brand-strategist.md +67 -1
- package/agents/campaign-content.md +67 -1
- package/agents/campaign-email.md +67 -1
- package/agents/campaign-sms.md +67 -1
- package/agents/campaign-social.md +67 -1
- package/agents/cco.md +83 -2
- package/agents/ceo.md +108 -11
- package/agents/chairman.md +197 -0
- package/agents/cmo.md +82 -2
- package/agents/community-greeter.md +67 -1
- package/agents/community-moderator.md +67 -1
- package/agents/compliance.md +67 -1
- package/agents/copywriter.md +67 -1
- package/agents/creative-strategist.md +67 -1
- package/agents/cro.md +81 -1
- package/agents/cto.md +266 -28
- package/agents/customer-interviewer.md +67 -1
- package/agents/customer-researcher.md +67 -1
- package/agents/customer-success-manager.md +67 -1
- package/agents/customer-trainer.md +67 -1
- package/agents/cxo.md +82 -1
- package/agents/demand-creator.md +67 -1
- package/agents/demo-mover.md +67 -1
- package/agents/demo-specialist.md +67 -1
- package/agents/demo-thai-family-law.md +67 -1
- package/agents/designer.md +67 -1
- package/agents/discovery-caller.md +67 -1
- package/agents/doctor.md +269 -0
- package/agents/educate-coach.md +67 -1
- package/agents/elevate-tutor.md +67 -1
- package/agents/email-lifecycle-marketer.md +67 -1
- package/agents/engage-specialist.md +67 -1
- package/agents/events-coordinator.md +67 -1
- package/agents/foundation-builder.md +67 -1
- package/agents/funnel-architect.md +67 -1
- package/agents/gift-creator.md +67 -1
- package/agents/google-ads.md +67 -1
- package/agents/guide.md +67 -1
- package/agents/helpdesk-dispatcher.md +67 -1
- package/agents/hook-specialist.md +67 -1
- package/agents/identify-optimizer.md +67 -1
- package/agents/implementer.md +313 -45
- package/agents/incident-commander.md +67 -1
- package/agents/insights-lead.md +87 -1
- package/agents/journey-runner.md +67 -1
- package/agents/linkedin-ads.md +67 -1
- package/agents/live-sales-chat.md +67 -1
- package/agents/market-researcher.md +67 -1
- package/agents/media-buyer.md +67 -1
- package/agents/memory-keeper.md +195 -0
- package/agents/movers-customer-researcher.md +67 -1
- package/agents/movers-foundation-builder.md +67 -1
- package/agents/movers-market-researcher.md +67 -1
- package/agents/movers-pricing-strategist.md +67 -1
- package/agents/nurture-architect.md +67 -1
- package/agents/offer-architect.md +67 -1
- package/agents/onboarder.md +67 -1
- package/agents/onboarding-specialist.md +67 -1
- package/agents/operations-dashboard.md +87 -1
- package/agents/perf-engineer.md +333 -37
- package/agents/playbook-writer.md +67 -1
- package/agents/plg-strategist.md +67 -1
- package/agents/positioning-architect.md +67 -1
- package/agents/press-officer.md +67 -1
- package/agents/pricing-strategist.md +67 -1
- package/agents/privacy-officer.md +67 -1
- package/agents/referral-manager.md +67 -1
- package/agents/refine-analyst.md +67 -1
- package/agents/release-manager.md +446 -39
- package/agents/renewals-upsell-rep.md +67 -1
- package/agents/review-engineer.md +319 -45
- package/agents/rewards-steward.md +67 -1
- package/agents/sales-call-coach.md +67 -1
- package/agents/sales-closer.md +67 -1
- package/agents/security-auditor.md +343 -48
- package/agents/sell-closer.md +67 -1
- package/agents/share-amplifier.md +67 -1
- package/agents/social-media-manager.md +67 -1
- package/agents/storyteller.md +301 -0
- package/agents/strategist.md +67 -1
- package/agents/strategy-aligner.md +67 -1
- package/agents/support-agent.md +67 -1
- package/agents/tagger.md +327 -0
- package/agents/tech-writer.md +195 -22
- package/agents/test-engineer.md +398 -29
- package/agents/tiktok-ads.md +67 -1
- package/agents/tracking-engineer.md +67 -1
- package/agents/trailkeeper.md +181 -0
- package/agents/upsell-strategist.md +67 -1
- package/agents/voice.md +67 -1
- package/agents/w1-recon.md +1 -1
- package/agents/w2-decide.md +1 -1
- package/agents/w3-edit.md +8 -2
- package/agents/w4-verify.md +13 -0
- package/agents/workflow-optimiser.md +81 -1
- package/commands/close.md +916 -160
- package/commands/deploy.md +102 -724
- package/commands/do.md +58 -2
- package/commands/sweep.md +159 -0
- package/commands/tasks.md +222 -0
- package/hooks/scripts/dev-only.sh +135 -0
- package/hooks/scripts/git-add-guard.sh +37 -2
- package/hooks/scripts/session-start.sh +32 -4
- package/package.json +1 -1
- package/rules/scripts.md +85 -0
- package/scripts/CLAUDE.md +315 -0
- package/scripts/ad-copy-lint.sh +656 -0
- package/scripts/agent-actor-parity.sh +129 -0
- package/scripts/blocks-manifest-cached.sh +100 -0
- package/scripts/chat-context-check.sh +89 -0
- package/scripts/chrome.mjs +18 -0
- package/scripts/close-metrics.sh +587 -0
- package/scripts/close-owner.sh +326 -0
- package/scripts/db-sync-lock-check.sh +116 -0
- package/scripts/deploy-emit.sh +311 -0
- package/scripts/deploy-gate-check.sh +155 -0
- package/scripts/deploy-ready.sh +78 -0
- package/scripts/deploy-record.sh +605 -0
- package/scripts/deploy-schema-check.sh +58 -0
- package/scripts/deploy.sh +393 -243
- package/scripts/do-auto.sh +127 -26
- package/scripts/do-board.sh +429 -0
- package/scripts/do-close.sh +1184 -0
- package/scripts/do-consumer-sweep.sh +18 -1
- package/scripts/do-decide.sh +476 -0
- package/scripts/do-fleet.sh +8 -2
- package/scripts/do-plan-json.mjs +110 -12
- package/scripts/do-prove-selftest.sh +108 -0
- package/scripts/do-prove.sh +86 -10
- package/scripts/do-rank.py +200 -3
- package/scripts/do-reconcile.sh +73 -12
- package/scripts/do-signal.sh +101 -23
- package/scripts/do-smoke.sh +18 -1
- package/scripts/do-w4-gates.sh +11 -1
- package/scripts/do-world-check.sh +153 -0
- package/scripts/download-stats.sh +172 -0
- package/scripts/factory-brief-check.sh +330 -0
- package/scripts/factory-check.sh +18 -1
- package/scripts/factory-close-check.sh +257 -0
- package/scripts/factory-emit.sh +211 -0
- package/scripts/factory-executor-check.mjs +353 -0
- package/scripts/factory-peak.sh +301 -0
- package/scripts/factory-repo.sh +71 -0
- package/scripts/factory-review-check.mjs +61 -0
- package/scripts/factory-tasks-check.sh +18 -1
- package/scripts/fixtures/factory-brief-real.md +44 -0
- package/scripts/flywheel-outcome.sh +63 -0
- package/scripts/gate-reaper-check.sh +98 -0
- package/scripts/gate-reaper.sh +9 -0
- package/scripts/gate-watchdog.sh +619 -0
- package/scripts/gc-content-check.sh +142 -0
- package/scripts/gh-traffic-capture.sh +153 -0
- package/scripts/govern-order-check.sh +202 -0
- package/scripts/governor-doors-check.sh +86 -5
- package/scripts/health.sh +448 -0
- package/scripts/id-inventory.mjs +418 -0
- package/scripts/incident.sh +212 -0
- package/scripts/land.sh +755 -45
- package/scripts/lib/gc-finished.sh +77 -0
- package/scripts/livekit-ratchet.sh +18 -1
- package/scripts/machine-check.sh +1 -1
- package/scripts/memory-index-budget.sh +79 -0
- package/scripts/npm-downloads.sh +109 -0
- package/scripts/one-agents.mjs +204 -8
- package/scripts/one-resume.sh +31 -3
- package/scripts/pr-body.sh +335 -0
- package/scripts/preview-fd-check.sh +289 -0
- package/scripts/redirect-lint.sh +169 -0
- package/scripts/release.sh +40 -6
- package/scripts/resume-lost-sessions.sh +68 -0
- package/scripts/shoot-pages.mjs +140 -0
- package/scripts/signal-meta-backfill.ts +451 -0
- package/scripts/signal-watch.sh +63 -6
- package/scripts/speed-cache-check.sh +12 -2
- package/scripts/sweep.sh +426 -0
- package/scripts/task-titles-dump.ts +101 -0
- package/scripts/test-cached.sh +47 -10
- package/scripts/test-lanes.sh +14 -0
- package/scripts/thread-name-backfill.ts +215 -0
- package/scripts/triage-shape-check.sh +149 -0
- package/scripts/tsc-cached.sh +155 -8
- package/scripts/typedb-flake-check.sh +3 -1
- package/scripts/urls-lint.sh +8 -0
- package/scripts/verify-board-doors.sh +80 -0
- package/scripts/verify-fast.sh +159 -6
- package/scripts/worktree-up.sh +21 -3
- package/skills/astro/SKILL.md +9 -3
- package/skills/astro/optimize-performance.md +3 -2
- package/skills/cloudflare/SKILL.md +3 -2
- package/skills/cloudflare-security-audit/AI-AND-LLM.md +83 -0
- package/skills/cloudflare-security-audit/ATTACK-CLASSES.md +130 -0
- package/skills/cloudflare-security-audit/CLIENT-SIDE.md +83 -0
- package/skills/cloudflare-security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
- package/skills/cloudflare-security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
- package/skills/cloudflare-security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
- package/skills/cloudflare-security-audit/HUNTING.md +251 -0
- package/skills/cloudflare-security-audit/LICENSE +21 -0
- package/skills/cloudflare-security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
- package/skills/cloudflare-security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
- package/skills/cloudflare-security-audit/PROVENANCE.md +78 -0
- package/skills/cloudflare-security-audit/RECONNAISSANCE.md +156 -0
- package/skills/cloudflare-security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
- package/skills/cloudflare-security-audit/SKILL.md +192 -0
- package/skills/cloudflare-security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
- package/skills/cloudflare-security-audit/VALIDATION-AND-REPORTING.md +186 -0
- package/skills/cloudflare-security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
- package/skills/cloudflare-security-audit/report-schema.json +461 -0
- package/skills/cloudflare-security-audit/validate-coverage-ledger.cjs +872 -0
- package/skills/cloudflare-security-audit/validate-coverage-ledger.test.cjs +740 -0
- package/skills/cloudflare-security-audit/validate-findings.cjs +773 -0
- package/skills/cloudflare-security-audit/validate-findings.test.cjs +652 -0
- package/skills/deploy/REFERENCE.md +713 -0
- package/skills/deploy/SKILL.md +140 -0
- package/skills/fleet-audit/SKILL.md +58 -0
- package/skills/meeting/SKILL.md +220 -0
- package/skills/planning/SKILL.md +256 -0
- package/skills/shadcn/SKILL.md +1 -1
- package/skills/typedb/SKILL.md +7 -0
- package/skills/voice/SKILL.md +94 -6
- package/skills/voice/corpus-check.sh +87 -0
- package/templates/template-agent.md +7 -1
- package/templates/template-feature.md +9 -0
- package/templates/template-todo.md +29 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: planning
|
|
3
|
+
description: Turn a whole task board into a plan, and the plan into moved rows — tasks:board to see everything, tasks:bulk to act on it. Use whenever an agent has a goal and needs to know what already exists, what is ready, what is blocked and who owns it, or needs to file a plan tree, route unowned work, sweep a stale tag, or find the rows that became claimable when something closed. Triggers — "plan this", "what should I work on", "see the whole board", "what is ready", "what is blocked", "file the plan", "break this down into tasks", "route the unassigned work", "clean up these tasks", "how many tasks are there really".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# planning — the board is the plan
|
|
7
|
+
|
|
8
|
+
**Purpose:** one loop. **See it all → decide → shape → act → close.** Every step is a
|
|
9
|
+
receiver, none is a convention you can improvise, and the whole board is ONE request.
|
|
10
|
+
|
|
11
|
+
**A page of tasks is not the board.** Measured 2026-09-13 and written into the contract
|
|
12
|
+
(`packages/sdk/src/receivers.ts:2113-2118`): an agent asked for the board, hit a 200-row page,
|
|
13
|
+
paged by six tags, found 353 more rows **by name only**, and never learned the real total.
|
|
14
|
+
`tasks:board` exists so that cannot happen again — and so you can reason about 2,000 tasks
|
|
15
|
+
while reading 0 of them.
|
|
16
|
+
|
|
17
|
+
**Use the CLI first.** `one tasks board|bulk|set` (`packages/cli/src/tasks.ts`) is the fast door —
|
|
18
|
+
it walks the pages, chunks writes at 25, and previews filter writes unless `--apply`. Pipe `--json`
|
|
19
|
+
to a file and filter it with `node -e`/`jq`; never read 2,000 rows through the context window.
|
|
20
|
+
|
|
21
|
+
node packages/cli/dist/src/index.js tasks board --workspace one --tree --summary # 1 — see it all
|
|
22
|
+
node packages/cli/dist/src/index.js tasks board --workspace one --tree --all --limit 2000 --include notes --json > board.json
|
|
23
|
+
node packages/cli/dist/src/index.js tasks set --workspace one --where-tag <t> --set-status dissolved --comment "why" # preview
|
|
24
|
+
node packages/cli/dist/src/index.js tasks bulk --file plan.json --apply # file a whole plan tree
|
|
25
|
+
node packages/cli/dist/src/index.js tasks brief --workspace one --tree # one screen + next five moves
|
|
26
|
+
node packages/cli/dist/src/index.js tasks plan <goal-tid|tag> --workspace one --tree # waves + critical path (hops)
|
|
27
|
+
node packages/cli/dist/src/index.js tasks plan <goal> --emit dispatch --out wave.json # hand-off for factory-executor / tasks:launch
|
|
28
|
+
node packages/cli/dist/src/index.js tasks sequence <tid> <tid> <tid> # chain in order; preview unless --apply
|
|
29
|
+
|
|
30
|
+
`brief`, `board` and `plan` default to `--kind work`: rows tagged `approval` are parked workflow
|
|
31
|
+
runs, left out of the counts and COUNTED as excluded. Close one with `tasks_approve` /
|
|
32
|
+
`workflow:stop`, never by status — `set --apply` refuses a match that holds one unless `--kind all`.
|
|
33
|
+
`plan` reads a blocker's state from the server's `openBlockers`, never raw `blockedBy`: a closed
|
|
34
|
+
blocker is satisfied, an open one outside the goal is `waits outside plan` and never dispatched.
|
|
35
|
+
Dispatch hints ride in notes as labelled lines — `model:` `effort:` `touches:` `accept:` — and rows
|
|
36
|
+
in one wave that share a `touches:` path are serialised. Promise + plan: `text/tasks-cli.md`.
|
|
37
|
+
|
|
38
|
+
The raw HTTP door and the MCP tools below are the same receivers; use them only without a shell.
|
|
39
|
+
If `tasks` is an unknown command the CLI `dist/` is stale — rebuild sdk then cli.
|
|
40
|
+
|
|
41
|
+
Every door: `POST https://one.ie/api/ask/<receiver>`, `Authorization: Bearer $GATEWAY_API_KEY`
|
|
42
|
+
(from `one.ie/web/.dev.vars`, **not `.env`**), body wrapped in `{"data":{…}}` or you get
|
|
43
|
+
`envelope_missing`. Via MCP, `tasks_board` / `tasks_bulk` take the same fields.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 1 — SEE IT ALL (always first, before any row read)
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{"data":{"workspace":"one","view":"summary","scope":"tree"}}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`view:"summary"` returns counts and sets and **no rows** — the cheapest way to see a 2,000-row
|
|
54
|
+
board. `scope:"tree"` is this group **and every descendant** (the CEO / agency lens); default is
|
|
55
|
+
`own`. Read the rows only once the summary told you which rows to ask for.
|
|
56
|
+
|
|
57
|
+
**Four honesty fields. Read all four before you plan.**
|
|
58
|
+
|
|
59
|
+
| Field | Means | Your next move |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `total` | rows matching the filters **before paging**. Exact — *unless* `truncated.rows` is present, then it is a **floor** | quote it as the count, or as "at least N" |
|
|
62
|
+
| `nextCursor` | present **iff** more rows match. Absent = you have them all | page until it is absent; never stop early and call it the board |
|
|
63
|
+
| `truncated` | absent = nothing was cut. `.rows` = snapshot hit its budget · `.edges` = a row may read unblocked or orphaned when it is not · `.tags` = returned rows may be missing tags | **say so in your report** before planning on it |
|
|
64
|
+
| `asOf` | ISO time the snapshot was built; rows are at most this stale | it is a KV memo, not a live read. `fresh:true` asks for a rebuild and is honoured **at most once per memo window** |
|
|
65
|
+
|
|
66
|
+
**`summary` counts are over ALL matched rows; its id lists are a SAMPLE.**
|
|
67
|
+
`summarizeBoard` counts every matched row (`one.ie/web/src/lib/tasks/board.ts:531`), but
|
|
68
|
+
`readyIds` / `blockedIds` are the **top 50 by priority** (`board.ts:559-560`) and `byTag` is the
|
|
69
|
+
**top 100 tags by count** (`board.ts:553`). A board with `ready: 300` hands you 50 ids — take the
|
|
70
|
+
count from `summary`, take the rows from a filtered `view:"rows"` call with `nextCursor`.
|
|
71
|
+
|
|
72
|
+
**Row width.** Compact rows already carry `tid,name,status,priority,tags,assignee,workspace,
|
|
73
|
+
parent,blockedBy,openBlockers,ready,dueAt` — and `blockedBy`/`openBlockers` appear only when the
|
|
74
|
+
row actually has blockers (`one.ie/web/src/lib/resolvers/task-board.ts:170`). Widen with
|
|
75
|
+
`include: ["notes","graph","dates","thread"]`; `notes` is **clipped to 2000 chars per row**
|
|
76
|
+
(`task-board.ts:182`) — read a whole goal one task at a time.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 2 — DECIDE what to do
|
|
81
|
+
|
|
82
|
+
Shipped in `summary` today (all computed in RAM over the matched set, no TypeDB):
|
|
83
|
+
|
|
84
|
+
- **`ready`** — open **and** every blocker closed; a blocker not on the board counts as open, so
|
|
85
|
+
readiness is never reported on a guess (`board.ts:463-469`). The set a director can start now.
|
|
86
|
+
- **`blocked`** — status `blocked`, or active with at least one open blocker.
|
|
87
|
+
- **`unassigned`** · **`overdue`** — work with no owner, work past its date.
|
|
88
|
+
- **`orphans`** — no parent, unreachable from any plan's containment walk.
|
|
89
|
+
- **`noNotes`** — no prose goal: the rows a puller **cannot act on**. Not work, a title.
|
|
90
|
+
|
|
91
|
+
**The unblockable row is the highest-value row on any board.** Status `blocked`, every blocker
|
|
92
|
+
now closed — claimable in fact, invisible in practice, because `ready` requires
|
|
93
|
+
`status === 'open'` (`board.ts:465`) and **nothing promotes it automatically**. Derive it today:
|
|
94
|
+
ask `{"status":"blocked"}`, keep rows whose `openBlockers` is `0` or absent, then flip them with
|
|
95
|
+
`tasks:bulk edits` (recipe D).
|
|
96
|
+
|
|
97
|
+
**Designed, not built** — `summary.decisions` (`unrouted` · `unblocked` · `stalePicked` ·
|
|
98
|
+
`deadlocked`) is **R10** of `text/tasks-inbox-plan.md` §6 and is not in the zod. So are
|
|
99
|
+
`changedSince` (R9), `include:["route"]` + `summary.routes` (R11), and the CEO digest (R12).
|
|
100
|
+
Zod **strips undeclared keys**, so sending one of those fields does not error — it silently
|
|
101
|
+
degrades to a full cold read. Do not write payloads against them.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 3 — SHAPE the work: chain before you fan out
|
|
106
|
+
|
|
107
|
+
`tasks:claim` is **blocker-gated**, and the edges you write are what that gate reads. An
|
|
108
|
+
unchained board hands every agent every row at once and nothing knows what comes first.
|
|
109
|
+
|
|
110
|
+
**One call files a whole plan tree.** `tasks:bulk` `creates` (max 25) with `ref` handles:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{"data":{"workspace":"one","creates":[
|
|
114
|
+
{"ref":"plan","title":"Launch the pricing page","notes":"Done when /pricing is live and converts"},
|
|
115
|
+
{"ref":"copy","title":"Write pricing copy","parent":"plan","notes":"Three tiers, no jargon"},
|
|
116
|
+
{"title":"Ship pricing page","parent":"plan","blockedBy":["copy"],"notes":"Deploy after copy lands"}]}}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Ref rules — earlier-only.** A ref must be created **earlier in the same `creates` array** and
|
|
120
|
+
its own create must have succeeded. A forward ref, a self ref, or a ref whose create failed is
|
|
121
|
+
`unknown_ref`, and **nothing is written for that row** — a typo never reaches the substrate as a
|
|
122
|
+
lookup (`one.ie/web/src/lib/resolvers/tasks.ts:2245-2252`). The receipt maps `ref → tid` in
|
|
123
|
+
`created`.
|
|
124
|
+
|
|
125
|
+
`tasks:subtask` does the same job **one row at a time** (row, notes, tags, containment edge and
|
|
126
|
+
every `blockedBy` in one pipeline) and `tasks:depend` orders rows that already exist. **Never file
|
|
127
|
+
a child with `tasks:create`** — it lands claimable, with no parent and no ordering.
|
|
128
|
+
|
|
129
|
+
**The claim gate is wider than the board's `ready` flag.** `blockersResolved` requires every
|
|
130
|
+
`blocks` blocker **AND every `containment` child** to be done|verified (`tasks.ts:614-619`,
|
|
131
|
+
called by claim at `tasks.ts:963`), while the board's `isReady` reads `blockedBy` only
|
|
132
|
+
(`board.ts:465-469`). So **a parent whose children are still open reads `ready:true` and
|
|
133
|
+
`tasks:claim` refuses it `blocked`.** That is the design working — a plan root is unclaimable
|
|
134
|
+
until its leaves close. Claim leaves, not roots.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 4 — ACT
|
|
139
|
+
|
|
140
|
+
**`where`+`set` is a DRY RUN by default.** `dryRun` is true unless you say `false` in so many
|
|
141
|
+
words (`tasks.ts:2276-2278`). Read `matchedIds`, satisfy yourself they are the rows you meant,
|
|
142
|
+
then resend the identical call with `"dryRun":false`.
|
|
143
|
+
|
|
144
|
+
- The 25-row budget is **shared**: `where` pages at `MAX_BULK − (creates+edits)`
|
|
145
|
+
(`tasks.ts:2525`), and a `where`+`set` sent alongside a full 25 rows errors `too_many`
|
|
146
|
+
(`tasks.ts:2527`). Follow `nextCursor` to continue.
|
|
147
|
+
- On a truncated snapshot the envelope adds a `detail` saying **`matched` is a floor, not a
|
|
148
|
+
total** (`tasks.ts:2577-2578`). Quote it that way.
|
|
149
|
+
- **Put a `comment` on every change**, saying why — it lands in the task's inbox thread where the
|
|
150
|
+
humans already read. Side effect: **a comment heartbeats a `picked` lease**
|
|
151
|
+
(`tasks.ts:1943-1946`), so commenting on stale `picked` rows fights `tasks:reap`.
|
|
152
|
+
- **`ok` is the CALL's outcome, never the rows'** (`tasks.ts:2687-2693`). Read
|
|
153
|
+
`applied` / `failed` / `notAttempted` — a row never attempted says so by name. And `created`
|
|
154
|
+
means **the row exists**, not that its later priority/dueAt/edge writes applied; that row's
|
|
155
|
+
receipt in `results` can still be `ok:false` (`tasks.ts:2682-2684`).
|
|
156
|
+
- **Delegate in place** with `tasks:reassign` — never by filing a second task. Under a shared
|
|
157
|
+
gateway key a claim lands as the workspace, so follow `tasks:claim` with
|
|
158
|
+
`tasks:reassign {assignee:"<your slug>"}` or the ledger cannot say who took the row.
|
|
159
|
+
- **`tasks:announce` returns `matched`, and matched is NOT delivered** — it is `actors.length`
|
|
160
|
+
from the fan-out (`one.ie/web/src/lib/resolvers/subscriptions.ts:1245` — the cite was
|
|
161
|
+
`:990`, which is a `lane = 'explore'` branch, not a `matched` line at all; `:928` is
|
|
162
|
+
`world:announce`'s). Quote it as reach.
|
|
163
|
+
|
|
164
|
+
Claim · delegate · chat · chain as a *meeting* is the `meeting` skill and
|
|
165
|
+
`.claude/agents/ceo.md § The four verbs`. Go there; don't restate it here.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 5 — CLOSE THE LOOP
|
|
170
|
+
|
|
171
|
+
The three locked rules, applied to a board turn:
|
|
172
|
+
|
|
173
|
+
1. **Every signal closes** with `mark`, `warn` or `dissolve` — `tasks:bulk` marks on `applied`
|
|
174
|
+
and warns on `failed` (`tasks.ts:2679-2680`); your *report* closes too.
|
|
175
|
+
2. **Structural time.** Tasks → waves → cycles. Never days, hours or weeks.
|
|
176
|
+
3. **Deterministic numbers, from the RECEIPT.** `applied` / `failed` / `notAttempted` are
|
|
177
|
+
authoritative. **Do not re-read the board to verify your own write** — it is a KV memo stamped
|
|
178
|
+
`asOf` and `fresh:true` is rate-limited, so it can answer with rows that predate your edit.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## The five mistakes
|
|
183
|
+
|
|
184
|
+
1. **Reading a page as the board** — six tag pages, 353 rows by name, no total. `view:"summary"` first, every time.
|
|
185
|
+
2. **Quoting `matched` as delivered** — `tasks:announce` reports reach, not action.
|
|
186
|
+
3. **Planning on a truncated board without saying so** — an unmentioned `truncated` turns a floor into a total.
|
|
187
|
+
4. **A bulk `ok:true` that hid failed rows** — `ok` is the call; rows live in `applied`/`failed`/`notAttempted`.
|
|
188
|
+
5. **Filing a child with `tasks:create`** — claimable, no parent, no ordering. Use `creates` or `tasks:subtask`.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Recipes (valid against the zod)
|
|
193
|
+
|
|
194
|
+
**A — Plan a feature.** One call, whole tree, ordering included.
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{"data":{"workspace":"one","creates":[
|
|
198
|
+
{"ref":"root","title":"Ship voice in chat","notes":"Done when a user can talk to a page and hear a reply","tags":["voice"],"priority":70},
|
|
199
|
+
{"ref":"api","title":"Wire the TTS receiver","parent":"root","notes":"Receiver + contract + test"},
|
|
200
|
+
{"title":"Voice bubble UI","parent":"root","blockedBy":["api"],"notes":"Push-to-talk and hands-free"}]}}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**B — Route unowned ready work.** Dry run, read `matchedIds`, then apply.
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{"data":{"workspace":"one","where":{"status":"open","ready":true,"assignee":"","tags":["launch"]},
|
|
207
|
+
"set":{"assignee":"cmo","comment":"Routing unowned ready launch work to marketing"},"dryRun":true}}
|
|
208
|
+
```
|
|
209
|
+
Then the same body with `"dryRun":false`. Follow `nextCursor` until absent; read `applied`.
|
|
210
|
+
|
|
211
|
+
**C — Sweep a stale tag.** See it first, then dissolve with a reason.
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{"data":{"workspace":"one","tags":["q3-experiment"],"status":"active","view":"both","limit":100}}
|
|
215
|
+
```
|
|
216
|
+
```json
|
|
217
|
+
{"data":{"workspace":"one","where":{"tags":["q3-experiment"],"status":"active"},
|
|
218
|
+
"set":{"status":"dissolved","comment":"Superseded by the Q4 plan — dissolved, not done"},"dryRun":false}}
|
|
219
|
+
```
|
|
220
|
+
A `picked` row in that sweep gets its lease heartbeat by the comment; reap it with `tasks:reap`
|
|
221
|
+
rather than commenting it back to life.
|
|
222
|
+
|
|
223
|
+
**D — Find what is unblockable.** The highest-value rows nobody knows are claimable.
|
|
224
|
+
|
|
225
|
+
```json
|
|
226
|
+
{"data":{"workspace":"one","scope":"tree","status":"blocked","limit":200}}
|
|
227
|
+
```
|
|
228
|
+
`openBlockers` is already on the compact row — no `include` needed. Keep rows whose
|
|
229
|
+
`openBlockers` is `0` or absent, then promote them by name:
|
|
230
|
+
```json
|
|
231
|
+
{"data":{"workspace":"one","edits":[
|
|
232
|
+
{"tid":"task:<24hex>","status":"open","comment":"Every blocker closed — open and claimable"}]}}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**E — The CEO's turn, in its SHIPPED form.** Three calls.
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{"data":{"workspace":"one","scope":"tree","view":"summary"}}
|
|
239
|
+
```
|
|
240
|
+
```json
|
|
241
|
+
{"data":{"workspace":"one","where":{"status":"open","ready":true,"assignee":"","scope":"tree"},
|
|
242
|
+
"set":{"assignee":"cto","comment":"Unowned and ready — routing to engineering"},"dryRun":true}}
|
|
243
|
+
```
|
|
244
|
+
…then the same call with `"dryRun":false`. **Designed, not built:** §6's faster turn
|
|
245
|
+
(`changedSince` watermark, `include:["route"]`, `summary.routes` ranked by who staked the tags)
|
|
246
|
+
is R9/R11/R12 of `text/tasks-inbox-plan.md` — until those ship, the CEO routes from its keyword
|
|
247
|
+
table and its own judgment, and unstaked work stays the CEO's call.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## See also
|
|
252
|
+
|
|
253
|
+
`packages/sdk/src/receivers.ts` — the contract; its `describe()` text is the spec, never invent a
|
|
254
|
+
field · `.claude/skills/meeting/SKILL.md` — the room where rows move ·
|
|
255
|
+
`.claude/agents/ceo.md § Seeing the whole board` · `text/tasks-inbox-plan.md` §5-§6 — the decided
|
|
256
|
+
doctrine and the unbuilt rungs.
|
package/skills/shadcn/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: shadcn
|
|
3
|
-
description: shadcn/ui primitives in `one.ie/web` under the ONE 6-token design system. Covers the `src/components/ui/` inventory, why shadcn's own `-foreground` names survive the `--color-*: initial` palette wipe via the Layout.astro aliases, adding a primitive with the CLI, and Button/Badge/Card/Dialog variants. Use when adding or editing a `src/components/ui/` primitive, when a shadcn component renders transparent or invisible after the wipe, or when picking between a token utility and an alias.
|
|
3
|
+
description: "shadcn/ui primitives in `one.ie/web` under the ONE 6-token design system. Covers the `src/components/ui/` inventory, why shadcn's own `-foreground` names survive the `--color-*: initial` palette wipe via the Layout.astro aliases, adding a primitive with the CLI, and Button/Badge/Card/Dialog variants. Use when adding or editing a `src/components/ui/` primitive, when a shadcn component renders transparent or invisible after the wipe, or when picking between a token utility and an alias."
|
|
4
4
|
user-invocable: true
|
|
5
5
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
6
6
|
---
|
package/skills/typedb/SKILL.md
CHANGED
|
@@ -129,6 +129,13 @@ anything but `read`. `GET /v1/databases/one/schema` dumps the live schema —
|
|
|
129
129
|
the fastest way to answer "is this fun actually deployed?". `GET /v1/version`
|
|
130
130
|
returns the running build.
|
|
131
131
|
|
|
132
|
+
**A timeout arrives as HTTP 500, not 408 or 503.** The body carries
|
|
133
|
+
`"The operation was aborted due to timeout"` — and that string was absent from
|
|
134
|
+
`RETRYABLE` in `one.ie/web/src/lib/substrate.ts` until 2026-09-14, so every timed-out
|
|
135
|
+
read failed hard on the first try. Reads now retry it; **writes deliberately do
|
|
136
|
+
not** — a write that timed out may already have committed, so retrying it is a
|
|
137
|
+
duplicate, not a recovery. Classify by the message, never by the status code.
|
|
138
|
+
|
|
132
139
|
The Python driver (`TypeDB.driver(...)`, `driver.transaction(...)`) is covered in
|
|
133
140
|
the *Python Driver* section for reading upstream docs. **No code in this repo
|
|
134
141
|
uses it** — there is no `typedb-driver` dependency in any `package.json` or
|
package/skills/voice/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: voice
|
|
3
|
-
description: Write in Anthony O'Connell's voice. Use whenever prose will go out under Anthony's or ONE's name and must sound like him, not like a generic assistant — books, essays, whitepapers, manifestos, blog posts, landing-page and marketing copy, founder updates, social posts, newsletters, client emails, playbook chapters, README and doc prose, or any rewrite where the note is "this doesn't sound like me". Its first job is picking the register: book/essay (patient, observational, no visible author, never sells) or commercial (first person, receipts, product names, sells). Invoke AFTER `writer` (craft) and alongside `product-marketing.md` (product context). Triggers — "write this in my voice", "in Anthony's voice/tone", "make it sound like me", "this reads like AI", "too corporate", "sounds generic", "write the book/chapter/essay/whitepaper", "write the blog post/landing page", "rewrite this properly".
|
|
3
|
+
description: "Write in Anthony O'Connell's voice. Use whenever prose will go out under Anthony's or ONE's name and must sound like him, not like a generic assistant — books, essays, whitepapers, manifestos, blog posts, landing-page and marketing copy, founder updates, social posts, newsletters, client emails, playbook chapters, README and doc prose, or any rewrite where the note is \"this doesn't sound like me\". Its first job is picking the register: book/essay (patient, observational, no visible author, never sells) or commercial (first person, receipts, product names, sells). Invoke AFTER `writer` (craft) and alongside `product-marketing.md` (product context). Triggers — \"write this in my voice\", \"in Anthony's voice/tone\", \"make it sound like me\", \"this reads like AI\", \"too corporate\", \"sounds generic\", \"write the book/chapter/essay/whitepaper\", \"write the blog post/landing page\", \"rewrite this properly\"."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# voice — Anthony O'Connell's register
|
|
@@ -33,7 +33,7 @@ Everything else — observe don't assert, specific numbers or none, short senten
|
|
|
33
33
|
|
|
34
34
|
## Step 2 — the sources, in order of authority
|
|
35
35
|
|
|
36
|
-
1. **`text/voice-and-tone.md`** — the specification. **Authored by Anthony.** Vendored from `apps/ants/docs/book/files/01-voice-and-tone.md`; edit the original, re-vendor here. Demonstrated across
|
|
36
|
+
1. **`text/voice-and-tone.md`** — the specification. **Authored by Anthony.** Vendored from `apps/ants/docs/book/files/01-voice-and-tone.md`; edit the original, re-vendor here. Demonstrated across `apps/ants/docs/book/manuscript/` — 96,540 words of directory, 93,032 of them the 25 chapters the section below measures. **Senior to everything else. Where anything disagrees with it, it wins.**
|
|
37
37
|
2. **`text/writing-style-guide.md`** — derived. Splits universal from book-only, and documents the commercial register the spec doesn't cover.
|
|
38
38
|
3. **`.claude/product-marketing.md`** — product context: offer, audience, thesis, the measured-numbers table. Commercial only.
|
|
39
39
|
|
|
@@ -51,22 +51,110 @@ If it performs urgency, expertise, contrarianism, or aspiration — rewrite it.
|
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
+
## What the corpus actually does — measured
|
|
55
|
+
|
|
56
|
+
`text/voice-and-tone.md` says what the voice must never do. The 25 chapters of
|
|
57
|
+
*100 Million Years Ahead* show what it does. Measured 2026-09-09 over
|
|
58
|
+
`apps/ants/docs/book/manuscript/*.md` — 93,032 words, 6,163 sentences, 1,441
|
|
59
|
+
paragraphs. Re-measure any time with `bash .claude/skills/voice/corpus-check.sh --corpus`.
|
|
60
|
+
|
|
61
|
+
| Signature | Measured | What it means for a draft |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| **"I"** | **0** in 93,032 words | Absolute, not a preference. One occurrence is a defect. |
|
|
64
|
+
| **Contractions** (`n't`) | **5** in the whole book | Effectively never. Write *does not*, *is not*, *will not*. The spec never states this; the corpus is unanimous. |
|
|
65
|
+
| **`###` headings inside a chapter** | **0**, across all 25 | Confirmed absolute. |
|
|
66
|
+
| **Horizontal rules** (`---`) | **median 5 per chapter**, up to 10 | The derived guide's "once or twice" is **wrong**. The scene break is a primary structural tool, not a rarity. |
|
|
67
|
+
| **One-sentence paragraphs** | **371 of 1,441 — 25.7%** | One paragraph in four is a single sentence. That is the rhythm, not an occasional flourish. |
|
|
68
|
+
| **Sentence length** | median **12** words · mean 15.1 · p10 **4** · p90 30 · max 82 | Wide range on purpose; 22.2% of sentences are 6 words or fewer. A draft of uniform 20-word sentences is not this voice. |
|
|
69
|
+
| **Final sentence of a chapter** | median **10** words; three chapters end in 3 | Land short. *"The soil will."* · *"In the substrate."* · *"The architecture, running."* |
|
|
70
|
+
| **"the reader"** vs **"you"** | 134 vs 113 — and **50 of the 113 sit in the epilogue alone** | The standing device is third-person *"the reader."* Direct *you* is held back and spent at the end, where the book turns to face the reader. |
|
|
71
|
+
| **Digits** | 5.8 per 10k words | Numbers are rare and therefore load-bearing. A number earns its place or is cut. |
|
|
72
|
+
| **Hedges** | *on the order of* ×12 · *roughly* ×23 · *approximately* ×3 | Precise when the evidence is sharp, *on the order of* when it is not. Never a fake decimal. |
|
|
73
|
+
| **Em dashes** | 89.6 per 10k | Book register uses them freely. The "3 or fewer" rule is **commercial only** — do not carry it across. |
|
|
74
|
+
| **Question marks** | 5.3 per 10k — 49 in the whole book | A rhetorical question is a rationed move. Two chapters end on one. |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## The three sentence shapes
|
|
79
|
+
|
|
80
|
+
These are the shapes the corpus reaches for. They are not decoration. They are how an
|
|
81
|
+
observation gets made without being asserted.
|
|
82
|
+
|
|
83
|
+
**1. The negative-definition fragment.** A statement, then a fragment that names the
|
|
84
|
+
obvious alternative and refuses it. The most characteristic sentence in the book.
|
|
85
|
+
|
|
86
|
+
> *"This is the thing to look at. Not the ant."*
|
|
87
|
+
> *"This is where the colony's memory lives. Not in any ant."*
|
|
88
|
+
> *"The colony regulates the queen. Not the other way around."*
|
|
89
|
+
> *"That eighth one ran in fifteen years what the desert ran in a hundred million. Not because it was better designed."*
|
|
90
|
+
|
|
91
|
+
The fragment is deliberate. It does the work an em dash and a subordinate clause would
|
|
92
|
+
do, and it lands harder because it stops.
|
|
93
|
+
|
|
94
|
+
**2. "It is not X. It is Y."** Two flat copulas. The first clears the ground, the second
|
|
95
|
+
puts the thing down. No connective, no *rather*, no *instead*.
|
|
96
|
+
|
|
97
|
+
> *"It is not chemistry. It is not soil."*
|
|
98
|
+
> *"It is not a stored recipe retrieved on cue. It is constructed for the case in front of it."*
|
|
99
|
+
> *"It was not built as a substrate for collective intelligence. It was built to record grain shipments and tax debts."*
|
|
100
|
+
|
|
101
|
+
**3. The copula-forward declarative.** *It is* appears 683 times — 73.5 per 10k. The
|
|
102
|
+
voice states what a thing is and then stops, rather than explaining that it is about to
|
|
103
|
+
state it. This is what "confidence without assertion" looks like structurally.
|
|
104
|
+
|
|
105
|
+
**And one shape to avoid:** the interpretive paragraph after a clear observation. The
|
|
106
|
+
corpus makes the observation and leaves a blank line. The reader is given room to feel
|
|
107
|
+
the implication before the next paragraph arrives.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Openings and closings
|
|
112
|
+
|
|
113
|
+
**Every one of the 25 chapters opens on a concrete particular.** Never on an argument,
|
|
114
|
+
never on a thesis, never on a summary of what the chapter will do.
|
|
115
|
+
|
|
116
|
+
They open on: a temperature on dirt · a nine-month-old on a kitchen floor · dawn in the
|
|
117
|
+
Chihuahuan Desert · a corridor a centimetre wide · a freshly emerged ant · a stretch of
|
|
118
|
+
high desert near Rodeo · *"She is the largest animal in the nest, and she is doing the
|
|
119
|
+
least."* · a man opening a coffee shop · a person selling four hundred shares · Vienna,
|
|
120
|
+
1847 · a scrape on a knee · one and a half kilograms of tissue · the year 1300 · 2008 ·
|
|
121
|
+
*"The desert is still there."*
|
|
122
|
+
|
|
123
|
+
Three reliable opening moves: **a place and a temperature**; **a date, a person, an
|
|
124
|
+
action**; **a flat short sentence holding a contradiction** ("largest… doing the least").
|
|
125
|
+
Pick one and begin. Do not announce.
|
|
126
|
+
|
|
127
|
+
**The closings are short, and they return.** Median 10 words. The dominant move is a
|
|
128
|
+
recontextualised return to the chapter's own opening image — chapter 22 opens *"The
|
|
129
|
+
desert is still there"* and closes *"The architecture, running."* Two chapters close on a
|
|
130
|
+
question. Several close on a fragment that lands on one noun and nothing else.
|
|
131
|
+
|
|
132
|
+
Never close on a summary. Never close on an implication the reader can draw alone.
|
|
133
|
+
|
|
134
|
+
---
|
|
54
135
|
## Book-register checklist
|
|
55
136
|
|
|
56
137
|
- [ ] **Opens on a scene** — a place, a person, a moment, a number. Never on an argument.
|
|
57
138
|
- [ ] **No "I", no editorial "we", no visible author.** The camera is there; the camera is not the subject.
|
|
58
139
|
- [ ] **Observes; does not assert.** "The intelligence was not in any of the ants," not "intelligence is a property of substrates."
|
|
59
140
|
- [ ] **Sells nothing.** Names no company, product, or technology. Quotes no code.
|
|
60
|
-
- [ ] **No
|
|
61
|
-
- [ ] **
|
|
141
|
+
- [ ] **No contractions.** *does not*, not *doesn't*. Five in 92,894 words of corpus.
|
|
142
|
+
- [ ] **No `###` subheadings** — zero across 25 chapters. But **use the horizontal rule**: median 5 scene breaks per chapter, up to 10.
|
|
143
|
+
- [ ] **"The reader", not "you"** — 134 to 116, and 50 of the *you*s are in the epilogue. Direct address is saved for the end.
|
|
144
|
+
- [ ] **One paragraph in four is a single sentence** (25.7% measured). Vary sentence length hard: median 12 words, but 22.2% are ≤6.
|
|
145
|
+
- [ ] **Specific numbers, or honest hedging** (*on the order of*, *roughly*). Never false specificity. Digits appear only 5.8 times per 10k words — each one is load-bearing.
|
|
62
146
|
- [ ] **Never defines a technical term** — makes its meaning land through use.
|
|
63
|
-
- [ ] **
|
|
147
|
+
- [ ] **Opens on a concrete particular** — a place and a temperature, a date and a person and an action, or a short flat sentence holding a contradiction. Never on the thesis.
|
|
148
|
+
- [ ] **Closes short** — median 10 words — often a recontextualised return to the opening image. Never a summary.
|
|
149
|
+
- [ ] **Reaches for the three shapes** — the negative-definition fragment, "It is not X. It is Y.", the copula-forward declarative.
|
|
150
|
+
- [ ] **Leaves the observation alone.** No interpretive paragraph after a clear one.
|
|
64
151
|
- [ ] **Passes both the "your mum" and the "Demis Hassabis" test.**
|
|
65
152
|
- [ ] **The emotion is recognition, not awe.** No "this changes everything."
|
|
153
|
+
- [ ] **Run `bash .claude/skills/voice/corpus-check.sh <draft.md>`** — it counts the mechanical half against the corpus and cannot judge the rest.
|
|
66
154
|
|
|
67
155
|
## Commercial-register checklist
|
|
68
156
|
|
|
69
|
-
- [ ] **Em dashes: 3 or fewer.** Count them.
|
|
157
|
+
- [ ] **Em dashes: 3 or fewer.** Count them. (Book register is the opposite — 89.6 per 10k. Do not carry this rule across.)
|
|
70
158
|
- [ ] **Every quality adjective replaced by a number** — or the claim cut, or the gap stated.
|
|
71
159
|
- [ ] **No fabricated proof.** Every metric, quote, logo, benchmark, file path real or marked unproven.
|
|
72
160
|
- [ ] **Speed claims carry a measured number** from `product-marketing.md`'s table.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# corpus-check.sh — measure book-register prose against the corpus that defines it.
|
|
3
|
+
#
|
|
4
|
+
# bash .claude/skills/voice/corpus-check.sh --corpus re-derive the SKILL.md table
|
|
5
|
+
# bash .claude/skills/voice/corpus-check.sh <draft.md> ... check a draft
|
|
6
|
+
# bash .claude/skills/voice/corpus-check.sh --self-test prove the checker goes RED
|
|
7
|
+
#
|
|
8
|
+
# It counts the MECHANICAL half of the voice only: the things a machine can see.
|
|
9
|
+
# It cannot tell whether a sentence observes or asserts, and it never claims to.
|
|
10
|
+
# A green run is a draft that has not broken a countable rule. It is not a good draft.
|
|
11
|
+
#
|
|
12
|
+
# manifest: monorepo-only (the corpus lives in the sibling repo apps/ants)
|
|
13
|
+
set -o pipefail
|
|
14
|
+
|
|
15
|
+
CORPUS="${VOICE_CORPUS:-/Users/toc/Server/apps/ants/docs/book/manuscript}"
|
|
16
|
+
|
|
17
|
+
measure() { # measure <label> <file...>
|
|
18
|
+
python3 - "$@" <<'PY'
|
|
19
|
+
import re,sys,statistics
|
|
20
|
+
label=sys.argv[1]; files=sys.argv[2:]
|
|
21
|
+
txt=[]
|
|
22
|
+
for f in files:
|
|
23
|
+
try: t=open(f, encoding="utf-8").read()
|
|
24
|
+
except OSError as e: print(f" cannot read {f}: {e}"); continue
|
|
25
|
+
txt.append(t)
|
|
26
|
+
raw="\n".join(txt)
|
|
27
|
+
raw=re.sub(r'\A---\n.*?\n---\n','',raw,flags=re.S) # YAML frontmatter is metadata, not prose
|
|
28
|
+
body="\n".join(l for l in raw.split("\n") if not l.startswith("#"))
|
|
29
|
+
words=len(body.split())
|
|
30
|
+
if not words: print(" EMPTY — nothing to measure"); sys.exit(2)
|
|
31
|
+
sents=[s.strip() for s in re.split(r'(?<=[.!?])\s+',body) if len(s.strip())>1]
|
|
32
|
+
wl=[len(s.split()) for s in sents]
|
|
33
|
+
paras=[p.strip() for p in body.split("\n\n") if p.strip() and p.strip()!="---"]
|
|
34
|
+
psent=[len(re.split(r'(?<=[.!?])\s+',p)) for p in paras]
|
|
35
|
+
per10k=lambda n: 10000*n/words
|
|
36
|
+
CONTRACTION=r"n[\u2019']t\b"
|
|
37
|
+
c=lambda pat: len(re.findall(pat,body))
|
|
38
|
+
craw=lambda pat: len(re.findall(pat,raw)) # headings live only in raw
|
|
39
|
+
one=sum(1 for x in psent if x==1)
|
|
40
|
+
short=sum(1 for x in wl if x<=6)
|
|
41
|
+
last=re.split(r'(?<=[.!?])\s+',paras[-1].replace("\n"," "))[-1] if paras else ""
|
|
42
|
+
print(f" {label}: {words} words · {len(sents)} sentences · {len(paras)} paragraphs")
|
|
43
|
+
print(f" I {c(r'(?<![A-Za-z])I[ ,.]'):6d} target 0")
|
|
44
|
+
print(f" contractions n\'t {c(CONTRACTION):6d} target ~0 (corpus 0.5/10k)")
|
|
45
|
+
print(f" ### headings {craw(r'(?m)^#{3,}'):6d} target 0")
|
|
46
|
+
sb=[len(re.findall(r'(?m)^---\s*$',t)) for t in txt]
|
|
47
|
+
print(f" --- scene breaks {sum(sb):6d} median {statistics.median(sb) if sb else 0:.0f}/file corpus median 5")
|
|
48
|
+
print(f" 1-sentence paras {one:6d} {100*one/len(paras):5.1f}% corpus 25.7%")
|
|
49
|
+
print(f" sentences <=6 words {short:6d} {100*short/len(sents):5.1f}% corpus 22.4%")
|
|
50
|
+
print(f" sentence median {statistics.median(wl):6.0f} words corpus 12 (mean {statistics.mean(wl):.1f}, corpus 15.1)")
|
|
51
|
+
print(f" 'the reader' {c(r'(?i)\bthe reader\b'):6d}")
|
|
52
|
+
print(f" 'you' {c(r'(?i)\byou\b'):6d} corpus favours 'the reader'")
|
|
53
|
+
print(f" digits per10k {per10k(c(r'\b\d')):6.1f} corpus 5.8")
|
|
54
|
+
print(f" em dash per10k {per10k(c(chr(8212))):6.1f} corpus 89.8")
|
|
55
|
+
print(f" final sentence {len(last.split()):6d} words corpus median 10")
|
|
56
|
+
if last: print(f" > {last[:100]}")
|
|
57
|
+
PY
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
case "${1:-}" in
|
|
61
|
+
--corpus)
|
|
62
|
+
if [ ! -d "$CORPUS" ]; then
|
|
63
|
+
echo "corpus not found: $CORPUS"
|
|
64
|
+
echo "It lives in the sibling repo apps/ants and does not ship. Set VOICE_CORPUS to point at it."
|
|
65
|
+
exit 4 # unavailable — NOT a pass
|
|
66
|
+
fi
|
|
67
|
+
measure "corpus" "$CORPUS"/[0-9][0-9]-*.md ;;
|
|
68
|
+
|
|
69
|
+
--self-test)
|
|
70
|
+
d=$(mktemp -d); trap 'rm -rf "$d"' EXIT
|
|
71
|
+
printf '### A heading\n\nI think this is fine. It doesn'"'"'t matter.\n\nYou will see that you agree, you really will.\n' > "$d/bad.md"
|
|
72
|
+
out=$(measure "red-proof" "$d/bad.md")
|
|
73
|
+
echo "$out"
|
|
74
|
+
fail=0
|
|
75
|
+
echo "$out" | grep -qE '^ +I +[1-9]' || { echo "RED PROOF FAILED: 'I' not counted"; fail=1; }
|
|
76
|
+
echo "$out" | grep -qE "contractions n't +[1-9]" || { echo "RED PROOF FAILED: contraction not counted"; fail=1; }
|
|
77
|
+
echo "$out" | grep -qE '### headings +[1-9]' || { echo "RED PROOF FAILED: heading not counted"; fail=1; }
|
|
78
|
+
[ $fail -eq 0 ] && echo "SELF-TEST ok — the checker sees all three violations" || exit 1 ;;
|
|
79
|
+
|
|
80
|
+
""|-h|--help)
|
|
81
|
+
sed -n '2,14p' "$0" | sed 's/^# \{0,1\}//' ;;
|
|
82
|
+
|
|
83
|
+
*)
|
|
84
|
+
measure "draft" "$@"
|
|
85
|
+
echo
|
|
86
|
+
echo " Counted, not judged. The uncountable half is the checklist in SKILL.md." ;;
|
|
87
|
+
esac
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
name: {kebab-name}
|
|
7
7
|
description: {One sentence — what this agent does and when to spawn it}
|
|
8
8
|
tools: {comma-separated tool list}
|
|
9
|
-
model: {haiku | sonnet | opus}
|
|
9
|
+
model: {haiku | sonnet | opus} # OPTIONAL — omit to inherit the default
|
|
10
10
|
effort: {none | low | medium | high | xhigh}
|
|
11
11
|
skills: {comma-separated skill list}
|
|
12
12
|
subscribes: [{tag}, {tag}] # the agent's stake — these tags route matching
|
|
@@ -39,6 +39,12 @@ You are the {name} agent. {One sentence role statement.}
|
|
|
39
39
|
|
|
40
40
|
**Default:** pick the cheapest model that can answer. Stop at the first that decides.
|
|
41
41
|
|
|
42
|
+
**`model:` is optional — omit it unless you are OVERRIDING.** It is `z.string().optional()` in the schema (`one.ie/web/src/lib/agent-schema.ts:236`), and an absent value resolves by the walk this whole estate resolves by — **agent → group → ancestor → platform** (`resolveModel`, `packages/sdk/src/billing.ts:179`) — ending at `DEFAULT_MODEL` = `x-ai/grok-4.5` (`billing.ts:138`), filled for `one.ie/ai/agents` by **channels** (`context.ts:592` → `personas.one`, `channels/src/personas.ts:61`) and for the separate `one.ie/web/ai/agents` tree by the web loaders (`agent-loader.ts:64`, `agents.ts:91`) — two trees, one `web/` apart, so check which glob covers your file before citing a loader. Declaring the default buys nothing and hides the walk, so write the line only when the answer differs from it.
|
|
43
|
+
|
|
44
|
+
**The `kind: agent` genus has its own spec — `text/agents-spec.md`** — the field table across the six readers, the required set (`name` · `kind: agent` · a non-empty body), and the shapes the runtime cannot read; `oneie agent validate <path>` enforces it. This template is the other genus and is not validated by it.
|
|
45
|
+
|
|
46
|
+
**Which spelling depends on which genus you are writing, and they are not interchangeable.** This template is the **Claude Code** shape (root-level `one.ie/ai/agents/<name>.md`, with `tools:`/`effort:`/scalar `skills:`) — it is spawned through the Agent tool, which accepts only the bare aliases `opus | sonnet | haiku | fable`, so those are what belongs above. A **`kind: agent`** file under `one.ie/ai/agents/<name>/agent.md` is the other genus and takes a full **OpenRouter id** instead — and OpenRouter versions ids with **dots**: `anthropic/claude-sonnet-4.5`, never `anthropic/claude-sonnet-4-5`. Nothing normalises between them (no `normalizeModel`/`MODEL_ALIAS` exists in web, sdk or channels), so a wrong-genus or hyphenated value fails silently at `gateway()` rather than at parse. Measured 2026-09-17: 78 of 105 `kind: agent` files carried an id `/api/openrouter-models` does not serve. Verify before you write one — `curl -s localhost:4321/api/openrouter-models | jq -r '.models[].id'`.
|
|
47
|
+
|
|
42
48
|
## The Three Locked Rules
|
|
43
49
|
|
|
44
50
|
1. **Closed loop** — every output closes with a result, warn, or dissolve. No silent returns.
|
|
@@ -155,6 +155,15 @@ world: # the runtime the kept promise puts into the world
|
|
|
155
155
|
workflow: [] # "{kind}: …" — kinds (LOCKED): trigger·tool·skill·agent·condition·human·delay·sell
|
|
156
156
|
agents: [] # { name, subscribes: [tags] } — the tags are the stake (routing + inbox Space)
|
|
157
157
|
skills: [] # "{skill}: what it lets an agent do"
|
|
158
|
+
code: # the CODE the tag's family owns — every value a path relative to
|
|
159
|
+
# the repo root, presence-checked EXACTLY like agents: a declared
|
|
160
|
+
# path that does not exist → a cycle in the todo; present → skip.
|
|
161
|
+
# Gate: `bash .claude/scripts/do-world-check.sh <slug>`.
|
|
162
|
+
ts: [] # ["one.ie/web/src/lib/{slug}/tasks.ts"] — libs, resolvers, receivers
|
|
163
|
+
astro: [] # ["one.ie/web/src/pages/{slug}.astro"] — pages the tag ships
|
|
164
|
+
tql: [] # ["schema/{slug}.tql"] — the tag asked as a query
|
|
165
|
+
panel: [] # ["one.ie/web/src/components/{Slug}Panel.tsx"] — what a view mounts
|
|
166
|
+
command: [] # [".claude/commands/{slug}.md"] — the operator's door
|
|
158
167
|
tasks:
|
|
159
168
|
tags: ["slug:{slug}"] # the todo enters the world as a tagged weighted signal
|
|
160
169
|
tracking:
|
|
@@ -16,6 +16,35 @@ tags: [] # drives pheromone routing + W2 context triggers
|
|
|
16
16
|
priority: 0 # 0 none · 1 should · 2 important · 3 critical — human override; do-rank.py reads it
|
|
17
17
|
depends_on: [] # [other-slug, …] — plans that must be DONE before this is READY; powers do-rank.py's blocked/ready buckets + do-fleet conflict ordering
|
|
18
18
|
|
|
19
|
+
# ─── BOARD CONTRACT (the plan and the board are ONE graph) ───────────
|
|
20
|
+
# A plan's cycles and the board's rows are the same work in two renderings.
|
|
21
|
+
# Until this block existed they were two graphs that drifted: `batches:` held
|
|
22
|
+
# the ordering in markdown, D1 held it in `blocks` edges, and nothing joined
|
|
23
|
+
# them — so a head reading the board could claim C5 while C1 was still open.
|
|
24
|
+
#
|
|
25
|
+
# THE JOIN IS NOT DECORATION. `tasks:claim` is BLOCKER-GATED and reads the very
|
|
26
|
+
# `blocks` edge `tasks:depend` writes. So a plan whose batch DAG is mirrored onto
|
|
27
|
+
# the board CANNOT be claimed out of order — the gate enforces the plan. A plan
|
|
28
|
+
# that is not mirrored hands every agent every cycle at once, and the fan-out is
|
|
29
|
+
# a race. Chain before you fan out.
|
|
30
|
+
#
|
|
31
|
+
# ONE GRAPH, TWO RENDERINGS:
|
|
32
|
+
# batches: [[C1],[C2,C3],[C4]] == C2.blockedBy=[C1] · C3.blockedBy=[C1] · C4.blockedBy=[C2,C3]
|
|
33
|
+
# If the two ever disagree, the BOARD is truth (the gate reads it) and the
|
|
34
|
+
# batches list is stale — `do-plan-json.sh` emits both so the drift is visible.
|
|
35
|
+
|
|
36
|
+
anchor: "" # task:<24hex> — the board row this plan answers to. The parent every
|
|
37
|
+
# cycle row hangs off. Empty = the plan is not on the board and no
|
|
38
|
+
# agent can find it: file the anchor FIRST, then write the plan.
|
|
39
|
+
board_workspace: one # where the rows live. Platform work lives in `one`; a client plan
|
|
40
|
+
# lives in that client's slug.
|
|
41
|
+
cycle_rows: [] # [{cycle: C1, tid: "task:…"}, …] — WRITTEN BY `do-board.sh <slug>`,
|
|
42
|
+
# never by hand: it mints each row with tasks:subtask (parent = anchor,
|
|
43
|
+
# blockedBy = the batch predecessors, tags slug:<slug>-c<n> + plan:<slug>)
|
|
44
|
+
# and this list is the ONLY record of a cycle's tid — the cycle frames
|
|
45
|
+
# below do not repeat it. `do-board.sh <slug> --status` reads it back.
|
|
46
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
47
|
+
|
|
19
48
|
# ─── GOAL CONTRACT (the only thing that matters) ─────────────────────
|
|
20
49
|
# PROMISE FAN-OUT: this file is spawned by the promise's derives.todo
|
|
21
50
|
# at PLAN (text/<slug>.md is the promise). `outcome:` MUST be the
|