Files
waggle-os/docs/ux-refactor/p5-skill-governance-plan.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

112 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P5 — D4 Skill-Write Governance · Build Plan
> Phase sequence (open-questions.md:574): P1=D3 ✅ · P2=verify+J08 ✅ · P3=D2 ✅ ·
> P4=D11/D12 ✅ · **P5=D4** ← here · P7=D15 (card risk-taxonomy alignment, deferred).
> Decision text: `docs/ux-refactor/deltas/open-questions.md` §D4 (lines 537543).
## What D4 ratified (four bindings)
- **(i) Policy.** `create_skill` — normal = ask (in-chat approval card), trusted/yolo =
auto-execute. `delete_skill` — always ask, every autonomy level. `read_skill` ungated.
Always-audit all three with `initiator:'agent'`.
- **(ii) Surface.** In-chat SSE approval card is canonical. Card↔`ui/approval-modal.tsx`
risk-taxonomy alignment is **D15/P7 — explicitly deferred, NOT P5.**
- **(iii) One write path.** Do NOT route the agent tool through HTTP. Extract a **shared
skill-write service module** (create/update/delete + redaction + audit inside the
service), consumed by both `routes/skills.ts` and `skill-tools.ts`. One module, one
audit trail, two callers.
- **(iv) Endpoint consolidation (absorbs D14).** `POST /api/skills` delegates to the
audited service. `PUT`/`DELETE /api/skills/:name` enter the audit trail. **Provenance:**
frontmatter `initiator`/`source` + `GET /api/skills` returns it + Skills Hub badge
("created by agent — review"), replacing the name-heuristic "Custom" classification.
- **Persona exception** (already shipped): read-only personas keep losing
`create_skill`/`delete_skill`, retain `read_skill`.
- **PM residual** (no code): skill creation stays FREE at launch — tier gate unchanged.
## Recon — current seams (verified 2026-06-12)
| Seam | File | State |
|------|------|-------|
| Agent tool | `packages/agent/src/skill-tools.ts` | create/delete write to disk + redact; **no audit, no provenance, no gate** |
| HTTP routes | `packages/server/src/local/routes/skills.ts` | `POST /api/skills`, `PUT`/`DELETE /:name` redact but **don't audit**; `POST /api/skills/create` (structured) DOES audit `action:'installed'` |
| Autonomy gate | `packages/agent/src/confirmation.ts` | declarative sets; chat.ts:900 calls `needsConfirmationWithAutonomy` |
| Frontmatter | `packages/agent/src/skill-frontmatter.ts` | parser+serializer; has name/description/scope/promoted_from/permissions — **no initiator/source** |
| Audit store | `packages/core/src/install-audit.ts` | `record()`; action enum **lacks a delete value** |
| Skills Hub UI | `apps/web/src/components/os/apps/skills/SkillRow.tsx`, `routes/SkillsRoute.tsx` | `custom` badge driven by name-heuristic |
## Decisions
### DEC-1 — Audit `action` for delete (the one real fork)
`AuditAction = 'proposed'|'approved'|'installed'|'rejected'|'failed'|'blocked'` — no
delete/uninstall value. The CHECK is duplicated in `packages/core/src/install-audit.ts`
**and** `packages/hive-mind-core/src/mind/schema.ts` (OSS-synced, §7.5). SQLite CHECK
can't be ALTERed → widening needs a table-rebuild migration on existing installs.
- create / update → `action:'installed'` (established convention — `routes/skills.ts`
structured-create already does this; a skill on disk = installed).
- delete → **needs a decision** (see status note). Options:
- **A (recommended): add `'uninstalled'`** to `AuditAction` + both schema CHECKs +
a rebuild migration. Fills a genuine pre-existing gap (no uninstall of ANY capability
is auditable today); additive/backward-compatible; honest trail. Cost: migration in
2 files + OSS drift check.
- **B: reuse `'rejected'`** with `detail:'deleted by agent'`. Zero migration, but
semantically muddy and pollutes rejection queries.
### DEC-2 — Shared service location
`packages/agent/src/skill-write-service.ts`. The agent package is already a server
dependency (`@waggle/agent` imported by `routes/skills.ts`), so one module serves both
callers. Signature (pure, deps injected — no hidden globals):
```
createSkillWrite({ skillsDir, name, content, initiator, source, auditStore?,
skillHashStore?, onChange? }) → { path, redactions, action }
updateSkillWrite({ … }) ; deleteSkillWrite({ skillsDir, name, initiator, auditStore?, … })
```
Redaction (`redactSkillContent`) + provenance frontmatter stamp + audit `record()` all
live inside the service. Callers stop doing these by hand.
### DEC-3 — Provenance frontmatter
Add `initiator?: 'agent'|'user'` and `source?: string` to `SkillFrontmatter` + parser +
`serializeFrontmatter`. The service stamps them on create (preserves on update). Legacy
skills with no frontmatter → treated as `initiator:'user'` (no badge). Name-heuristic
"Custom" classification retired in favor of `initiator==='agent'`.
## Build order (TDD, commit per step)
1.**D4(i) gating**`confirmation.ts` sets + tests. (`73f2ed5`)
2.**DEC-1 audit enum** — founder picked **Option A**: `'uninstalled'` + widen-CHECK
migration in core `install-audit.ts` (belt-and-suspenders rebuild) AND hive-mind-core
`db.ts` runMigrations sentinel + `schema.ts` DDL. (`658884f`)
3.**DEC-3 frontmatter**`initiator`/`source` in parser/serializer. (`f3bda5b`)
4.**DEC-2 service**`skill-write-service.ts` (lossless provenance stamp). (`2b56b78`)
5.**Rewire agent**`skill-tools.ts` create/delete via service. (`2b56b78`)
6.**Rewire HTTP**`routes/skills.ts` POST/create/PUT/DELETE via service; `GET
/api/skills` returns provenance. (`29313a9`)
7. ✅ **UI badge** — `SkillRow.tsx` "agent · review" off provenance. (`48292ef`)
8. ⏳ Adversarial review workflow → record → final gates. (pending — needs opt-in)
## Status — implementation COMPLETE (2026-06-12)
All four D4 bindings shipped in 7 commits (`73f2ed5`→`48292ef`), NOT pushed.
Gates: tsc 0 across shared/hive-mind-core/core/agent/server/apps-web · 147 P5 tests
green (agent 96, core 22, server 20, FE 9) · lint 0.
**Remaining for P5 closeout:**
- **OSS re-split (§7.5):** `hive-mind-core/src/mind/{schema.ts,db.ts}` changed here first
(the `'uninstalled'` CHECK + migration sentinel). The `marolinik/hive-mind` mirror must
be regenerated via subtree-split before the next OSS release.
- **Adversarial review** (step 8) — every prior P-phase ran a multi-agent review workflow;
deferred pending explicit opt-in.
- **Decision-log + open-questions** phase-line update marking P5 done.
- **D4(ii)** card↔modal risk-taxonomy alignment stays **P7/D15** (out of P5 scope).
## Out of scope (ledgered)
- D4(ii) card↔modal risk-taxonomy alignment → **P7/D15**.
- Marketplace install PRO-gate (unchanged).
- `promote_skill`/`auto_extract_skills`/`retire_skills` audit (not named by D4; leave).