diff --git a/.agents/reports/archive/TASK-074-sidecar-audit-report.md b/.agents/reports/archive/sidecar-audit.md similarity index 100% rename from .agents/reports/archive/TASK-074-sidecar-audit-report.md rename to .agents/reports/archive/sidecar-audit.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2380e5274..0f53ba7a7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: inputs: tag: - description: 'Release tag to publish, for example v2.0.0-dev.49' + description: 'Release tag to publish, for example v2.0.0' required: true update_tap: description: 'Update levifig/homebrew-tap after uploading assets' diff --git a/AGENTS.md b/AGENTS.md index da6953292..e40fad3e7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,8 +4,7 @@ Guidelines for maintaining and extending Loaf - An Opinionated Agentic Framework See [README.md](README.md) for what Loaf is and how to install it. - -> **Transition in progress — the Change model is landing.** New work is shaped as a Change: `/shape` → `docs/changes/YYYYMMDD-slug/change.md`, validated by `loaf change check` (see `loaf change --help`). The contract lives in `docs/changes/20260704-shape-first-change-workflow/change.md`. Existing `SPEC-*` work continues under `loaf spec`/`loaf task` until the conversion pass; skill guidance below that still reads "spec-first" predates the sweep and loses to this note. +> **New work is Change-first.** `/shape` creates `docs/changes/YYYYMMDD-slug/change.md`, and `loaf change check` validates its structure and derived executability (see `loaf change --help`). Existing `SPEC-*` and task records remain supported compatibility surfaces under `loaf spec` and `loaf task` until they are deliberately converted; their continued support does not make them the default artifact for new work. ## Quick Start @@ -120,6 +119,22 @@ Use domain-focused names in gerund or noun-phrase form: - No reserved words: `anthropic`, `claude` - Directory name must match `name` field +### Artifact Names Never Cite Their Work Unit + +Artifacts are named for what they are, never for the work unit that produced them. Reference runs one way: a Change, spec, task, or issue points at its artifacts; an artifact never points back. The containing directory already supplies the provenance, so a work identity in the filename is both redundant and doomed — it has to be renamed to stay true, and the number outlives everyone's memory of what it meant. + +| Instead of | Write | +|------------|-------| +| `research/u8-target-capability-survey.md` | `research/target-capability-survey.md` | +| `cli/scripts/u8-codex-smoke.mjs` | `cli/scripts/smoke-codex-startup.mjs` | +| `reports/report-spec-053-signoff.md` | `reports/taxonomy-signoff.md` | + +Record provenance in a front-matter field such as `source:` instead, where it is readable and updatable. + +These are identity rather than citation and stay as they are: a **version** (`claude-code-2.1.218-plugin-startup-smoke.json`), a **timestamp** (`20260620-214448-skills-audit.md`), and a numbered record inside the directory that owns it (`.agents/specs/SPEC-042-slug.md`, `docs/decisions/ADR-007-slug.md`). + +`loaf check --hook artifact-names` enforces this at commit. It judges tracked paths only, matches artifact directories by basename so relocating them needs no change, and grandfathers artifacts already marked `final` or `archived`. + ### SKILL.md Structure Follow the [Agent Skills](https://agentskills.io) open standard: diff --git a/README.md b/README.md index 13e87d7b5..e818a0a0c 100644 --- a/README.md +++ b/README.md @@ -2,72 +2,72 @@ > "Why have just a slice when you can get the whole loaf?" -Loaf is an opinionated agentic framework that gives AI coding assistants structured knowledge, enforced tool boundaries, and a complete pipeline from idea to implementation to learning. Write your skills once, deploy to Claude Code, OpenCode, Cursor, Codex, and Amp. +Loaf is an opinionated agentic framework that gives AI coding assistants structured knowledge, enforced tool boundaries, and a coherent workflow from idea to implementation to learning. Write your skills once, deploy to Claude Code, OpenCode, Cursor, Codex, and Amp. ## Why Loaf? -**Portable knowledge** — 33 skills (31 active, 2 deprecated) covering workflows, engineering standards, and language expertise. Build once, deploy to five AI coding tools without rewriting anything. +**Portable knowledge** — Skills cover workflows, engineering standards, and language expertise. Build once, deploy to supported AI coding tools without rewriting anything. **Project journal model** — A single SQLite-backed journal captures decisions and progress across every conversation, project-scoped and correlated by an opaque harness id. There is no session entity to open or close, so concurrent conversations across branches and worktrees stay conflict-free. Handoff artifacts live separately in `.agents/handoffs/`. Work survives context loss, compaction, and `/clear`. -**Spec-first pipeline** — Ideas are shaped into bounded specs before any code is written. Every change flows: Idea → Spec → Tasks → Code → Learnings. Nothing gets lost. +**Change-first workflow** — Ideas may be explored before `/shape` creates a bounded Change in `docs/changes/YYYYMMDD-slug/change.md`. `loaf change check` validates the contract before implementation, review, and shipping. -**Profile-based agents** — Three functional profiles defined by tool access, not job titles. A Smith with `python-development` skills becomes a backend engineer; the same Smith with `infrastructure-management` becomes a DevOps engineer. Skills determine what an agent knows; the profile determines what it can touch. +**Profile-based agents** — Functional profiles are defined by tool access, not job titles. A Smith with `python-development` skills becomes a backend engineer; the same Smith with `infrastructure-management` becomes a DevOps engineer. Skills determine what an agent knows; the profile determines what it can touch. -**Session continuity** — Pick up exactly where you left off with full traceability. The project journal captures decisions and progress in SQLite; a derived, ephemeral digest (latest wrap + recent branch entries + open tasks) is emitted at conversation start. Explicit transfer packets live in `.agents/handoffs/` until housekeeping deletes them after deprecation. +**Conversation continuity** — Pick up exactly where you left off with full traceability. The project journal captures decisions and progress in SQLite; a derived, ephemeral digest (latest wrap + recent branch entries + open tasks) is emitted at conversation start. Explicit transfer packets live in `.agents/handoffs/` until housekeeping deletes them after deprecation. **Hooks as quality gates** — Two hook types: enforcement hooks (pre-commit secrets scanning, pre-push linting) block bad commits automatically; skill instruction hooks inject context at tool invocation time. Language-aware and automatic. -## The Pipeline +## Workflow -Loaf's commands form a three-phase workflow that mirrors how good software gets built: +Loaf keeps intent, implementation, and learning connected: ``` ┌─────────────────────────────────────────────────────────────┐ -│ PHASE 1: SHAPE │ +│ EXPLORE AND SHAPE │ │ │ -│ /idea → /brainstorm → /shape → SPEC │ +│ /idea or /brainstorm → /shape → Change │ │ │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ -│ PHASE 2: BUILD │ +│ IMPLEMENT AND SHIP │ │ │ -│ /breakdown → /implement → /ship → /release │ +│ /implement → review → /ship │ │ │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ -│ PHASE 3: LEARN │ +│ PRESERVE LEARNING │ │ │ -│ /housekeeping → /reflect → /wrap │ +│ journal · /reflect · optional /wrap │ │ │ └─────────────────────────────────────────────────────────────┘ ``` -### Phase 1: Shape +### Explore and Shape -Transform raw ideas into implementable specs with clear boundaries. +Explore uncertainty when useful, then create an implementable Change with explicit boundaries and verification. | Command | What It Does | |---------|--------------| -| `/idea` | Quick capture of rough ideas into `.agents/ideas/` | +| `/idea` | Quick capture of rough ideas for later evaluation | | `/brainstorm` | Deep exploration of a problem space | -| `/shape` | Rigorous shaping into bounded spec (what's IN and OUT) | +| `/shape` | Create `docs/changes/YYYYMMDD-slug/change.md` with a bounded product and implementation contract | | `/strategy` | Discover and document strategic direction | -### Phase 2: Build +### Implement and Ship -Decompose specs into atomic tasks and execute with specialized agents. +Implement a coherent Change through contained branches and pull requests, review the result, and land it deliberately. | Command | What It Does | |---------|--------------| -| `/breakdown` | Split spec into agent-sized atomic tasks | -| `/implement` | Execute tasks with orchestrated agent delegation | +| `/breakdown` | Decompose existing spec or task records when that compatibility workflow is in use | +| `/implement` | Execute a Change or compatible task/spec record with orchestrated agent delegation | | `/ship` | Review, verify, and land one PR | | `/release` | Publish a version from already-landed work | -### Phase 3: Learn +### Preserve Learning Integrate outcomes into strategic knowledge. @@ -75,12 +75,12 @@ Integrate outcomes into strategic knowledge. |---------|--------------| | `/housekeeping` | Review and archive or delete lifecycle-complete artifacts | | `/reflect` | Integrate learnings into strategic documents | -| `/handoff` | Package context for another agent, branch, task, or future session | -| `/wrap` | Session summary: what shipped, what's pending, what's next | +| `/handoff` | Package context for another agent, branch, task, or future conversation | +| `/wrap` | Optional checkpoint for synthesis that is not otherwise derivable from the journal | -### Pipeline Commands +### Supporting Commands -CLI commands that support the workflow pipeline: +CLI commands that support the workflow: | Command | What It Does | |---------|--------------| @@ -89,8 +89,9 @@ CLI commands that support the workflow pipeline: | `loaf config check` | Validate project config and installed Loaf-managed hooks | | `loaf check` | Run enforcement hooks manually | | `loaf project` | Manage durable project identity (show, rename, move) | +| `loaf change` | Scaffold, validate, and inspect Change artifacts | | `loaf task` | Manage project tasks (list, show, update, archive) | -| `loaf spec` | Manage spec lifecycle | +| `loaf spec` | Manage existing spec records retained for compatibility | | `loaf kb` | Knowledge base management | | `loaf journal` | Project journal: log, recent, search, show, context, export | | `loaf housekeeping` | Review and archive agent artifacts | @@ -98,7 +99,7 @@ CLI commands that support the workflow pipeline: ## Profiles -Loaf uses four functional profiles defined by mechanically enforced tool boundaries — not role titles, not domain labels. What an agent *can do* is fixed by its profile. What it *knows* comes from skills loaded at spawn time. +Loaf uses functional profiles defined by mechanically enforced tool boundaries — not role titles, not domain labels. What an agent *can do* is fixed by its profile. What it *knows* comes from skills loaded at spawn time. | Profile | Role | Tool Access | What It Does | |---------|------|-------------|--------------| @@ -107,7 +108,7 @@ Loaf uses four functional profiles defined by mechanically enforced tool boundar | **Ranger** | Researcher | Read + web | Scouts far, gathers intelligence, reports structured findings. | | **Librarian** | Librarian | Read + Edit (.agents/) | Tends the project journal and durable `.agents/` artifacts, including wrap checkpoints. Does not forge code or scout. | -The main session is the **Warden** — it coordinates and delegates but never implements directly. See [SOUL.md](.agents/SOUL.md) for the full fellowship identity. +The main conversation is the **Warden** — it coordinates and delegates but never implements directly. See [SOUL.md](.agents/SOUL.md) for the full fellowship identity. ## Skills @@ -117,9 +118,9 @@ Skills you invoke directly to drive work forward. | Skill | Activates When | |-------|----------------| -| `shape` | Shaping ideas into bounded specs | -| `breakdown` | Decomposing specs into atomic tasks | -| `implement` | Starting task or spec implementation | +| `shape` | Shaping ideas into bounded Changes | +| `breakdown` | Decomposing existing compatible spec/task records | +| `implement` | Implementing a Change or compatible task/spec record | | `ship` | Reviewing, verifying, and landing one PR | | `release` | Publishing a version from already-landed work | | `brainstorm` | Deep exploration of a problem space | @@ -184,8 +185,6 @@ Build once, deploy everywhere. Skills are the universal layer; profiles and hook | Codex | — | ✓ | Fallback | Skills + opt-in basic command policy | | Amp | — | ✓ | — | Skills + runtime plugin | -*Note: `council-session` skill renamed to `council` for consistency. Removed skills: `resume-session`, `reference-session`.* - ## Getting Started ### Homebrew diff --git a/bin/native/darwin-arm64/loaf b/bin/native/darwin-arm64/loaf index f3beae887..a2de1b2de 100755 Binary files a/bin/native/darwin-arm64/loaf and b/bin/native/darwin-arm64/loaf differ diff --git a/cli/scripts/eval-skill-routing.mjs b/cli/scripts/eval-skill-routing.mjs index 2d247467e..c309f82c5 100755 --- a/cli/scripts/eval-skill-routing.mjs +++ b/cli/scripts/eval-skill-routing.mjs @@ -266,7 +266,7 @@ const CONFLICT_PROBES = [ group: "strategy-reflect", choices: ["strategy", "reflect"], expected: "strategy", - prompt: "Define the product direction and personas before the next wave", + prompt: "Define the product direction and personas before the next delivery", }, { group: "strategy-reflect", diff --git a/cmd/loaf/content_hygiene_test.go b/cmd/loaf/content_hygiene_test.go index b55120925..a266f0c06 100644 --- a/cmd/loaf/content_hygiene_test.go +++ b/cmd/loaf/content_hygiene_test.go @@ -3,6 +3,7 @@ package main import ( "os" "path/filepath" + "regexp" "sort" "strconv" "strings" @@ -195,13 +196,242 @@ func TestCliReferenceCatalogsJournalFamily(t *testing.T) { if !strings.Contains(body, "log, recent, search, show, context, export") { t.Fatalf("%s missing the journal subcommand family in the command index", filepath.ToSlash(rel)) } - // Journal-first (SPEC-056): the session entity is gone; no session command - // should survive in the generated CLI reference. + // The journal is the supported conversation-continuity namespace; no retired + // lifecycle command should survive in the generated CLI reference. if strings.Contains(body, "loaf session") { t.Fatalf("%s still references the deleted `loaf session` namespace", filepath.ToSlash(rel)) } } +func TestPlanningVocabularyConverged(t *testing.T) { + root := repoRoot(t) + cases := []struct { + rel string + forbidden []string + required []string + }{ + { + rel: "AGENTS.md", + forbidden: []string{ + "TRANSITIONAL:", + "Transition in progress — the Change model is landing.", + "until the conversion pass", + "spec-conversion-and-guidance-sweep", + }, + required: []string{ + "**New work is Change-first.**", + "Existing `SPEC-*` and task records remain supported compatibility surfaces", + "their continued support does not make them the default artifact for new work", + }, + }, + { + rel: "README.md", + forbidden: []string{ + "**Spec-first pipeline**", + "## The Pipeline", + "PHASE 1:", + "PHASE 2:", + "PHASE 3:", + "### Phase 1:", + "### Phase 2:", + "### Phase 3:", + }, + required: []string{ + "**Change-first workflow**", + "## Workflow", + "### Explore and Shape", + "### Implement and Ship", + "### Preserve Learning", + }, + }, + { + rel: "docs/VISION.md", + forbidden: []string{ + "Every change flows through a deliberate pipeline", + "Idea, Spec, Tasks, Code, Learnings", + "pipeline's three-artifact model", + "A pipeline that prevents scope creep", + }, + required: []string{ + "Ideas may be explored before `/shape` turns the chosen direction into a bounded Change.", + "Change artifacts and compatible task records keep intent and execution inspectable", + "Changes define the intended outcome, boundaries, and proof before implementation", + }, + }, + { + rel: "docs/STRATEGY.md", + forbidden: []string{ + "## What Has Been Proven", + "24 specs shipped, 6 in progress.", + "1. **Journal continuity** (proven: SPEC-056", + "4. **Agent routing enforcement** (next: SPEC-022)", + "## What We Do Not Know Yet", + }, + required: []string{ + "## Proven Principles", + "**Continuity belongs to the project journal, not a session lifecycle.**", + "**Change-first workflow consistency.**", + "Existing spec and task records remain supported compatibility surfaces", + "## Open Questions", + }, + }, + { + rel: "docs/knowledge/task-system.md", + forbidden: []string{ + "# Task System", + "Loaf implements a Shape Up-inspired task management system", + "## Pipeline", + "/shape → SPEC file", + "## Journal Model (SPEC-056)", + "One concern per task.", + }, + required: []string{ + "# Work Records", + "Loaf uses Change artifacts for new bounded work.", + "## Current Workflow", + "Primary bounded-work contract for new work", + "These identifiers document provenance, not current workflow instructions.", + }, + }, + { + rel: "docs/ARCHITECTURE.md", + forbidden: []string{ + "### Stateful Runtime Migration (ADR-014)", + "The transition shape is a Go front controller", + "### Mode-Aware Skills (Linear-Native Mode, ADR-011)", + "The project journal is the **only** session-related structure (SPEC-056).", + }, + required: []string{ + "### Native Stateful Runtime (ADR-014)", + "ADR and SPEC identifiers cited in this document serve only as decision and work provenance.", + "### Work Records and Optional Linear Tasks (ADR-011)", + "## Change-First Execution Model", + "New bounded work uses a Change as its primary contract.", + }, + }, + { + rel: ".github/workflows/release.yml", + forbidden: []string{"v2.0.0-dev.49"}, + required: []string{"Release tag to publish, for example v2.0.0"}, + }, + { + rel: "content/skills/loaf-reference/SKILL.md", + forbidden: []string{"Markdown-to-native transition"}, + required: []string{"`transitional-tasks`", "Open task-board records retained for compatibility."}, + }, + { + rel: "content/skills/loaf-reference/references/command-routing.md", + forbidden: []string{ + "TRANSITIONAL", + "conversion pass", + "spec-conversion-and-guidance-sweep", + "CLAUDE.md", + }, + required: []string{ + "Shape new bounded work", + "Start implementing new bounded work", + "Continue an existing task or spec record", + "`loaf task` and `loaf spec` remain supported for existing records", + }, + }, + { + rel: "content/skills/orchestration/references/context-management.md", + forbidden: []string{"transitional tasks", "Markdown-to-native transition"}, + required: []string{"`transitional-tasks`", "Open task-board records retained for compatibility.", "Changes, task-board records, reports, ADRs, and commits"}, + }, + { + rel: "content/skills/orchestration/references/parallel-agents.md", + forbidden: []string{"dependency-wave orchestration"}, + required: []string{"dependency-aware orchestration"}, + }, + { + rel: "config/hooks.yaml", + forbidden: []string{"Journal-first (SPEC-056)", "active specs"}, + required: []string{"Journal-first continuity has no session entity", "Block tracked ephemeral Markdown and dangling references from retained spec records"}, + }, + { + rel: "internal/state/journal_context.go", + forbidden: []string{"during U6", "open transitional task"}, + // Split around the alignment padding: gofmt re-pads this block whenever a + // longer constant name joins it, and the padding is not the contract. + required: []string{"JournalContextLayerTasks", `= "transitional_tasks"`, `json:"transitional_tasks"`, "these keep existing callers source-compatible.", "open task-board record retained for compatibility"}, + }, + } + + for _, tc := range cases { + t.Run(tc.rel, func(t *testing.T) { + body := readTextFile(t, filepath.Join(root, filepath.FromSlash(tc.rel))) + for _, forbidden := range tc.forbidden { + if strings.Contains(body, forbidden) { + t.Fatalf("%s still contains leaked planning vocabulary %q", tc.rel, forbidden) + } + } + for _, required := range tc.required { + if !strings.Contains(body, required) { + t.Fatalf("%s missing semantic replacement %q", tc.rel, required) + } + } + }) + } +} + +func TestOperationalArtifactsUseSemanticFilenames(t *testing.T) { + root := repoRoot(t) + implementationUnitPrefix := regexp.MustCompile(`(?i)^u[0-9]+[-_]`) + developmentUnitFixtureLabel := regexp.MustCompile(`(?i)loaf-u[0-9]+`) + var filenameFailures []string + var fixtureFailures []string + + for _, relRoot := range []string{"cli/scripts", "docs/changes", "internal"} { + walkRoot := filepath.Join(root, filepath.FromSlash(relRoot)) + err := filepath.WalkDir(walkRoot, func(path string, entry os.DirEntry, err error) error { + if err != nil { + return err + } + if entry.IsDir() { + return nil + } + rel := relToRoot(t, root, path) + isResearchEvidence := relRoot == "docs/changes" && strings.Contains(filepath.ToSlash(rel), "/research/") + checkFilename := relRoot == "cli/scripts" || isResearchEvidence + checkFixtureContent := relRoot == "cli/scripts" || relRoot == "internal" + if !checkFilename && !checkFixtureContent { + return nil + } + if checkFilename && implementationUnitPrefix.MatchString(entry.Name()) { + filenameFailures = append(filenameFailures, rel) + } + if checkFixtureContent { + content, err := os.ReadFile(path) + if err != nil { + return err + } + if developmentUnitFixtureLabel.Match(content) { + fixtureFailures = append(fixtureFailures, rel) + } + } + return nil + }) + if err != nil { + t.Fatalf("WalkDir(%s) error = %v", walkRoot, err) + } + } + + // Change contracts and historical SPEC/ADR provenance remain valid; only operational runners and retained research evidence must use semantic filenames. + sort.Strings(filenameFailures) + sort.Strings(fixtureFailures) + if len(filenameFailures) > 0 || len(fixtureFailures) > 0 { + var failures []string + if len(filenameFailures) > 0 { + failures = append(failures, "implementation-unit filename prefixes:\n"+strings.Join(filenameFailures, "\n")) + } + if len(fixtureFailures) > 0 { + failures = append(failures, "development-unit fixture labels:\n"+strings.Join(fixtureFailures, "\n")) + } + t.Fatalf("operational artifacts still expose planning vocabulary:\n%s", strings.Join(failures, "\n")) + } +} + func hasShellScripts(t *testing.T, dir string) bool { t.Helper() entries, err := os.ReadDir(dir) diff --git a/cmd/loaf/main_test.go b/cmd/loaf/main_test.go index b6fff1f7d..b26f01f6c 100644 --- a/cmd/loaf/main_test.go +++ b/cmd/loaf/main_test.go @@ -183,7 +183,7 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { if exitCode(err) == 2 { t.Fatalf("loaf doctor in identical worktree hit pre-A3 refusal\n%s", output) } - if strings.Contains(output, "SPEC-036 centralizes") { + if strings.Contains(output, "Linked worktrees keep .agents/") { t.Fatalf("identical worktree output = %q, want no pre-A3 refusal", output) } raw, err := os.ReadFile(filepath.Join(linked, ".agents", ".moved-to")) @@ -204,7 +204,7 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { if exitCode(err) != 2 { t.Fatalf("loaf journal recent divergent exit = %d, want 2\n%s", exitCode(err), output) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(output, want) { t.Fatalf("divergent refusal output = %q, want %q", output, want) } @@ -217,7 +217,7 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { if exitCode(err) != 2 { t.Fatalf("loaf journal recent exit = %d, want 2\n%s", exitCode(err), output) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage", "LOAF_DEBUG_RESOLVE"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage", "LOAF_DEBUG_RESOLVE"} { if !strings.Contains(output, want) { t.Fatalf("refusal output = %q, want %q", output, want) } @@ -230,7 +230,7 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { if exitCode(err) != 2 { t.Fatalf("loaf not-a-command exit = %d, want 2\n%s", exitCode(err), output) } - for _, want := range []string{"unknown command 'not-a-command'", "SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"unknown command 'not-a-command'", "Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(output, want) { t.Fatalf("unknown-command refusal output = %q, want %q", output, want) } @@ -243,7 +243,7 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { if err != nil { t.Fatalf("loaf migrate worktree-storage error = %v\n%s", err, output) } - if !strings.Contains(output, "Dry run") || strings.Contains(output, "SPEC-036 centralizes") { + if !strings.Contains(output, "Dry run") || strings.Contains(output, "Linked worktrees keep .agents/") { t.Fatalf("migrate allowlist output = %q, want dry-run without refusal", output) } @@ -255,14 +255,14 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { if err != nil { t.Fatalf("loaf %v error = %v\n%s", allowed, err, output) } - if strings.Contains(output, "SPEC-036 centralizes") { + if strings.Contains(output, "Linked worktrees keep .agents/") { t.Fatalf("allowlisted %v output = %q, want no refusal", allowed, output) } } main = createMainRepo(t, "nudge-main") output, err = runBinary(binary, main, envWith(), "version") - if exitCode(err) == 2 || strings.Contains(output, "SPEC-036 centralizes") { + if exitCode(err) == 2 || strings.Contains(output, "Linked worktrees keep .agents/") { t.Fatalf("main checkout output = %q, error = %v, want no pre-A3 refusal", output, err) } @@ -275,7 +275,7 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { t.Fatalf("WriteFile(.moved-to) error = %v", err) } output, err = runBinary(binary, linked, envWith(), "version") - if exitCode(err) == 2 || strings.Contains(output, "SPEC-036 centralizes") { + if exitCode(err) == 2 || strings.Contains(output, "Linked worktrees keep .agents/") { t.Fatalf("migrated linked worktree output = %q, error = %v, want no pre-A3 refusal", output, err) } @@ -286,7 +286,7 @@ func TestPublicBinaryPreA3WorktreeRefusalNudgeNatively(t *testing.T) { t.Fatalf("WriteFile(stale .moved-to) error = %v", err) } output, err = runBinary(binary, linked, envWith(), "journal", "recent") - if exitCode(err) != 2 || !strings.Contains(output, "SPEC-036") { + if exitCode(err) != 2 || !strings.Contains(output, "Linked worktrees keep .agents/") { t.Fatalf("stale pointer output = %q, error = %v, want pre-A3 refusal", output, err) } } diff --git a/cmd/loaf/routing_eval_content_test.go b/cmd/loaf/routing_eval_content_test.go index 92e2e8d6b..679e17412 100644 --- a/cmd/loaf/routing_eval_content_test.go +++ b/cmd/loaf/routing_eval_content_test.go @@ -3,6 +3,7 @@ package main import ( "os/exec" "path/filepath" + "regexp" "strings" "testing" ) @@ -22,14 +23,22 @@ func TestRoutingEvalDryRunValidatesCurrentSkillSuite(t *testing.T) { t.Fatalf("dry-run routing eval failed: %v\n%s", err, output) } - for _, want := range []string{ - "Loaded 35 skills", - "Selected cases: 127", - "Suite validation passed.", - } { - if !strings.Contains(output, want) { - t.Fatalf("dry-run output missing %q:\n%s", want, output) - } + // Assert the invariant, never a snapshot: a pinned skill or case count turns + // every skill addition into a test edit, and the number proves nothing that + // the loaded/expected agreement does not already prove. + loaded := regexp.MustCompile(`Loaded (\d+) skills`).FindStringSubmatch(output) + expected := regexp.MustCompile(`Expected skill count: (\d+)`).FindStringSubmatch(output) + if loaded == nil || expected == nil { + t.Fatalf("dry-run output does not report both loaded and expected skill counts:\n%s", output) + } + if loaded[1] != expected[1] { + t.Fatalf("dry-run loaded %s skills but the suite expects %s:\n%s", loaded[1], expected[1], output) + } + if !regexp.MustCompile(`Selected cases: [1-9]\d*`).MatchString(output) { + t.Fatalf("dry-run selected no routing cases:\n%s", output) + } + if !strings.Contains(output, "Suite validation passed.") { + t.Fatalf("dry-run output missing suite validation:\n%s", output) } } @@ -49,13 +58,20 @@ func TestRoutingEvalContentHasNoPhantomSkillCases(t *testing.T) { } } -func TestSkillArchitectureCountMatchesCurrentTaxonomy(t *testing.T) { +func TestSkillArchitectureDescribesSemanticTaxonomy(t *testing.T) { root := repoRoot(t) body := readTextFile(t, filepath.Join(root, "docs", "knowledge", "skill-architecture.md")) - if !strings.Contains(body, "35 skills total: 19 workflow/default-invocable, 16 non-invocable") { - t.Fatalf("skill architecture doc missing current 34-skill taxonomy") + for _, want := range []string{ + "## Categories", + "| Category | `user-invocable` | Examples |", + "| Reference/Knowledge | `false` |", + "| Workflow/Process | `true` (default) |", + } { + if !strings.Contains(body, want) { + t.Fatalf("skill architecture doc missing semantic taxonomy %q", want) + } } - if strings.Contains(body, "33 skills") || strings.Contains(body, "34 skills") { - t.Fatalf("skill architecture doc still contains stale skill count") + if regexp.MustCompile(`(?i)\b[0-9]+\s+skills\s+total\b`).MatchString(body) { + t.Fatal("skill architecture doc publishes a volatile exact skill-count snapshot") } } diff --git a/cmd/loaf/session_convergence_content_test.go b/cmd/loaf/session_convergence_content_test.go index 27a66caef..4cc8b2e5e 100644 --- a/cmd/loaf/session_convergence_content_test.go +++ b/cmd/loaf/session_convergence_content_test.go @@ -39,7 +39,7 @@ func TestSessionModelConvergenceContentGuards(t *testing.T) { } } -// TestJournalFirstContentNamespaceConverged is the SPEC-056 Track 4 grep gate: +// TestJournalFirstContentNamespaceConverged is the content namespace grep gate: // zero `loaf session` references across skills, agents, hooks, templates, and // docs source. The `loaf session` namespace was deleted with no alias, so any // surviving reference resolves to "unknown command." loaf-reference/SKILL.md is @@ -63,7 +63,7 @@ func TestJournalFirstContentNamespaceConverged(t *testing.T) { } // TestJournalFirstHookSurfacesConverged asserts the hook definition and -// generated hook artifacts carry no session-entity commands (SPEC-056 Track 3). +// generated hook artifacts carry no session-entity commands. // Scope is deliberately limited to hook config surfaces; skill/template bodies // are covered by TestJournalFirstContentNamespaceConverged (Track 4). func TestJournalFirstHookSurfacesConverged(t *testing.T) { diff --git a/config/hooks.yaml b/config/hooks.yaml index a6479e8ef..5f8eff15c 100644 --- a/config/hooks.yaml +++ b/config/hooks.yaml @@ -6,7 +6,7 @@ # post-tool: Runs AFTER tool execution (informational) # session: Conversation hooks (SessionStart, UserPromptSubmit, PreCompact, PostCompact, TaskCompleted) # -# Journal-first (SPEC-056): there is no session entity. Conversation hooks emit +# Journal-first continuity has no session entity. Conversation hooks emit # the layered continuity digest and journal-flush guidance, or evaluate # normalized event envelopes for result-aware capture. All journal hooks read # the harness payload on stdin and exit silently for subagent invocations @@ -64,7 +64,16 @@ hooks: blocking: true timeout: 30000 failClosed: true - description: Block active specs from pointing at deleted ephemeral Markdown after cutover + description: Block tracked ephemeral Markdown and dangling references from retained spec records + + - id: artifact-names + skill: foundations + matcher: "Bash" + if: "Bash(git commit:*)" + blocking: true + timeout: 30000 + failClosed: true + description: Block artifact filenames that name the work unit that produced them - id: github-account skill: git-workflow diff --git a/content/skills/architecture/SKILL.md b/content/skills/architecture/SKILL.md index 62e83b80a..5fdfef8ec 100644 --- a/content/skills/architecture/SKILL.md +++ b/content/skills/architecture/SKILL.md @@ -43,7 +43,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/content/skills/bootstrap/SKILL.md b/content/skills/bootstrap/SKILL.md index e7a8c7bf2..2c26f51df 100644 --- a/content/skills/bootstrap/SKILL.md +++ b/content/skills/bootstrap/SKILL.md @@ -217,7 +217,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -226,14 +226,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -243,9 +243,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/content/skills/bootstrap/references/interview-guide.md b/content/skills/bootstrap/references/interview-guide.md index ad67e1947..3313798f0 100644 --- a/content/skills/bootstrap/references/interview-guide.md +++ b/content/skills/bootstrap/references/interview-guide.md @@ -5,10 +5,10 @@ A structured interview framework for helping builders go from a vague idea to a ## Contents - How This Guide Works - Framework Foundations -- Phase 1: Excavation (The Spark) -- Phase 2: Sharpening (The Shape) -- Phase 3: Grounding (The Architecture) -- Phase 4: Synthesis (The Documents) +- Excavation (The Spark) +- Sharpening (The Shape) +- Grounding (The Architecture) +- Synthesis (The Documents) - Adapting Interview Depth - Anti-Patterns - Transitioning to Document Drafting @@ -17,16 +17,16 @@ A structured interview framework for helping builders go from a vague idea to a This is a **builder interview**, not a user research interview. The interviewer (the agent) is helping the builder crystallize their own thinking -- not extracting requirements from a stakeholder. The builder has context, intuition, and taste that need to be surfaced, challenged, and structured. -The interview flows through four phases, each producing progressively sharper artifacts: +The interview flows through four sections, each producing progressively sharper artifacts: -| Phase | Focus | Primary Output | Frameworks | +| Section | Focus | Primary Output | Frameworks | |-------|-------|----------------|------------| -| 1. Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | -| 2. Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | -| 3. Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | -| 4. Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | +| Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | +| Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | +| Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | +| Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | -Phases are not rigid walls. A strong answer in Phase 1 might skip half of Phase 2. A weak answer in Phase 2 might loop back to Phase 1. Follow the energy. +Sections are not rigid walls. A strong answer in Excavation might skip half of Sharpening. A weak answer in Sharpening might loop back to Excavation. Follow the energy. --- @@ -80,7 +80,7 @@ What each framework contributes and what to skip. **What to skip:** Customer interview logistics, meeting scheduling advice. The Mom Test is about question quality, not interview operations. -**Connection to documents:** Informs the quality of every answer in every phase. The Mom Test isn't a phase -- it's a lens applied to ALL questioning. It keeps the interview honest. +**Connection to documents:** Informs the quality of every answer in every section. The Mom Test isn't a section -- it's a lens applied to ALL questioning. It keeps the interview honest. ### Design Sprint - Understand Phase (Google Ventures) @@ -120,7 +120,7 @@ What each framework contributes and what to skip. --- -## Phase 1: Excavation (The Spark) +## Excavation (The Spark) **Goal:** Understand what exists, why it matters, and whether the problem is real. @@ -157,9 +157,9 @@ The builder's own experience with the problem is the richest source of insight. - "Have you seen anyone spend money or significant time on this problem?" *(Mom Test: evidence of pain)* - "Is this problem getting worse or better over time? Why?" *(Wardley: movement awareness)* -### Phase 1 Signals +### Excavation Signals -**Strong signal (move to Phase 2):** Builder can describe a specific person with a specific problem and knows what they do about it today. +**Strong signal (move to Sharpening):** Builder can describe a specific person with a specific problem and knows what they do about it today. **Weak signal (dig deeper):** Builder describes a category ("developers need better tools") without specifics. Ask for a story: "Tell me about a specific moment when this problem was most painful." @@ -167,13 +167,13 @@ The builder's own experience with the problem is the richest source of insight. --- -## Phase 2: Sharpening (The Shape) +## Sharpening (The Shape) **Goal:** Define who this is for, what it does, and -- critically -- what it does NOT do. Set complexity and boundaries. -**Mood:** Constructive pressure. Phase 1 was expansive; Phase 2 is reductive. The builder will want to include everything. Your job is to help them cut. +**Mood:** Constructive pressure. Excavation was expansive; Sharpening is reductive. The builder will want to include everything. Your job is to help them cut. -**Duration:** This is typically the longest phase. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. +**Duration:** This is typically the longest section. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. ### Must-Ask Questions @@ -210,17 +210,17 @@ Surface the riskiest assumptions. "Will users actually switch from their current - "How might we make [the hardest part] effortless?" *(Design Sprint: HMW)* - "What would definitely make this fail?" *(First Principles: inversion)* -### Phase 2 Signals +### Sharpening Signals -**Strong signal (move to Phase 3):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. +**Strong signal (move to Grounding):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. **Weak signal (iterate):** Builder keeps expanding scope. "It should also..." is a signal to tighten. Ask: "If you could only do ONE thing, what would it be?" -**Red flag (loop back to Phase 1):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" +**Red flag (loop back to Excavation):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" --- -## Phase 3: Grounding (The Architecture) +## Grounding (The Architecture) **Goal:** Establish technical direction, identify what to build vs. buy, and surface hidden complexity. @@ -257,19 +257,19 @@ These become the rabbit holes in the spec. The builder often knows where the dra - "If you had to ship something in one week, what would you cut?" *(Shape Up: scope pressure test)* - "Are there regulatory, legal, or compliance considerations?" *(Often forgotten at 0-to-1)* -### Phase 3 Signals +### Grounding Signals -**Strong signal (move to Phase 4):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. +**Strong signal (move to Synthesis):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. **Weak signal (iterate):** Builder wants to build everything from scratch. Challenge: "What's the thing ONLY YOU can build? Build that. Use existing solutions for the rest." -**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Phase 3 and note that ARCHITECTURE.md will be populated later when technical decisions are made. +**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Grounding and note that ARCHITECTURE.md will be populated later when technical decisions are made. --- -## Phase 4: Synthesis (The Documents) +## Synthesis (The Documents) -**Goal:** Transform interview insights into draft documents. This is NOT a phase of the interview -- it's the transition from interviewing to drafting. +**Goal:** Transform interview insights into draft documents. This is NOT an interview section -- it's the transition from interviewing to drafting. **Mood:** Collaborative, iterative. The agent drafts, the builder reacts and refines. @@ -319,11 +319,11 @@ Allow the builder to approve all remaining sections at once if they're satisfied ## Adapting Interview Depth -The interview adapts to three contexts, per SPEC-013's mode detection: +The interview adapts to three contexts based on the detected project mode: ### Greenfield + Empty (Full Interview) -Run all four phases in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all phases. This is where the interview guide earns its keep. +Run all four sections in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all sections. This is where the interview guide earns its keep. **Key adaptation:** Be patient. The builder may circle back, contradict themselves, or get stuck. That's normal. Let them think out loud. Silence after a question is productive, not awkward. @@ -332,9 +332,9 @@ Run all four phases in full. The builder has minimal clarity and needs the most Read and analyze the brief first. Then run a compressed interview that: - Confirms understanding ("Here's what I extracted -- is this right?") - Challenges assumptions ("Your brief says X, but have you considered Y?") -- Fills gaps (which phases have missing information?) +- Fills gaps (which sections have missing information?) -Expect 8-12 questions total, concentrated in whichever phases the brief is weakest. +Expect 8-12 questions total, concentrated in whichever sections the brief is weakest. **Key adaptation:** Don't re-ask what the brief already answers well. Quote the brief back and ask "Is this still accurate?" to confirm, then move to gaps. @@ -345,7 +345,7 @@ The project exists. Code exists. Docs may exist. The interview focuses on: - What the builder wants to CHANGE (current pain, technical debt, strategic shifts) - What conventions and preferences exist but aren't documented -Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered by the existing codebase. +Expect 6-10 questions total, mostly in Excavation and Sharpening. Grounding is largely answered by the existing codebase. **Key adaptation:** Show the builder what you learned from their code. "I see a Python/FastAPI project with PostgreSQL and Docker. The test suite uses pytest. Is that the intended stack going forward?" Let the codebase speak first, then fill gaps. @@ -361,13 +361,13 @@ Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered b **The Therapist.** "And how does that make you feel about your product?" No. This is a builder interview, not a feelings exploration. Emotions matter (JTBD switching forces), but ask about user emotions, not builder emotions. -**Premature Architecture.** Jumping to "What database should we use?" in Phase 1. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. +**Premature Architecture.** Jumping to "What database should we use?" during Excavation. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. **The Echo Chamber.** Reflecting back everything the builder says without challenging anything. The Mom Test exists because people are too polite. Be constructive, not agreeable. "That's a big scope. Are you sure you need ALL of that for v1?" **Solution-First Questioning.** "What features should it have?" is the wrong question. "What job does it do for the user?" is the right one. Features are an output of the interview, not an input. -**Asking for Permission to Proceed.** Don't ask "Should we move to the next phase?" Just move when the signals are strong. If the builder has more to say, they'll say it. +**Asking for Permission to Proceed.** Don't ask "Should we move to the next section?" Just move when the signals are strong. If the builder has more to say, they'll say it. **Over-Indexing on Frameworks.** Don't say "Let's do a JTBD analysis" or "Let me apply Wardley Mapping here." The frameworks are lenses for the interviewer, not vocabulary for the builder. Just ask good questions. @@ -413,12 +413,12 @@ The bootstrap interview creates the foundation. Other skills deepen specific are ## Framework Attribution -| Framework | Primary Contribution | Phase(s) | +| Framework | Primary Contribution | Section(s) | |-----------|---------------------|----------| -| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | 2, 3 | -| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | 1, 2 | -| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | 1, 2 | -| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All phases | -| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | 2, 3 | -| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | 3 | -| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | 1, 3 | +| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | Sharpening, Grounding | +| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | Excavation, Sharpening | +| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | Excavation, Sharpening | +| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All sections | +| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | Sharpening, Grounding | +| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | Grounding | +| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | Excavation, Grounding | diff --git a/content/skills/breakdown/SKILL.md b/content/skills/breakdown/SKILL.md index 932aa4e96..c98113103 100644 --- a/content/skills/breakdown/SKILL.md +++ b/content/skills/breakdown/SKILL.md @@ -88,7 +88,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/content/skills/foundations/SKILL.md b/content/skills/foundations/SKILL.md index f144c8043..ea1c5b7ea 100644 --- a/content/skills/foundations/SKILL.md +++ b/content/skills/foundations/SKILL.md @@ -112,6 +112,22 @@ Engineering foundations for consistent, high-quality code. | Constants | `UPPER_SNAKE` | `UPPER_SNAKE` | | Tests | `test___` | `describe/it` blocks | +### Artifact Names Never Cite Their Work Unit + +Name an artifact for what it is, never for the work unit that produced it. The directory or Change that contains it already records that provenance, so repeating it in the filename inverts the reference and rots the moment the work closes: a work unit points at its artifacts, artifacts never point back. + +| Instead of | Write | +|------------|-------| +| `u8-claude-smoke.mjs` | `smoke-claude-code-startup.mjs` | +| `report-spec-053-taxonomy-signoff.md` | `taxonomy-signoff.md` | +| `TASK-074-sidecar-audit-report.md` | `sidecar-audit.md` | + +Provenance belongs in a front-matter field such as `source:`, where it can be read and updated, not in a name that has to be renamed to stay true. + +Two look-alikes are correct and stay. A **version** is identity, not reference: `claude-code-2.1.218-plugin-startup-smoke.json`. A **timestamp** records when, not which work unit: `20260620-214448-skills-audit.md`. And a numbered record living in the directory that owns it *is* that entity, so `.agents/specs/SPEC-042-slug.md` and `docs/decisions/ADR-007-slug.md` are its own name rather than a citation. + +`loaf check --hook artifact-names` enforces this at commit time over tracked artifacts, grandfathering anything already `final` or `archived`. + ## Test Patterns Scenario-based fixture naming: diff --git a/content/skills/git-workflow/references/commits.md b/content/skills/git-workflow/references/commits.md index 5ed2ba9e1..d6a48ab9b 100644 --- a/content/skills/git-workflow/references/commits.md +++ b/content/skills/git-workflow/references/commits.md @@ -185,7 +185,7 @@ Internal terms that have no meaning outside the team's working context: - Spec IDs and task IDs (`SPEC-024`, `TASK-042`) - Session, sprint, or branch references - Internal terminology from skills/docs that isn't part of the user's mental model — e.g. `Q1`/`Q2`/`Q3` question numbers from a Triage Gate, internal gate-logic notation like `(Q1 OR Q2) AND Q3`, hook IDs that aren't user-facing -- "How the work got done" framing — interview steps, breakdown phases, review gates +- "How the work got done" framing — interview steps, breakdown steps, review gates ### Keep @@ -252,7 +252,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE] Four hooks automatically enforce the conventions documented in this file: -| Hook | Phase | Behavior | +| Hook | Timing | Behavior | |------|-------|----------| | `github-account` | Pre-tool (Bash) | Force-switch: switches the active `gh` account to the configured one before `gh` commands run (passes with a warning), exempting `gh auth` administration, and blocks only when the switch fails. It writes the shared global account pointer on every mismatched `gh` call -- read-only ones included -- so concurrent sessions on different identities collide on that pointer more often. | | `workflow-pre-pr` | Pre-tool (Bash) | Advisory: reminds about CHANGELOG [Unreleased] entries and PR format. Non-blocking. | @@ -269,26 +269,14 @@ BREAKING CHANGE: Description of breaking change. ### Pre-Release Versions -When developing toward a major version, use pre-release suffixes to mark development milestones: - -``` -2.0.0-dev.0 → dev.1 → dev.2 → ... → 2.0.0 - ↑ ↑ ↑ ↑ - start dev milestone milestone stable release -``` - | Suffix | Meaning | When to use | |--------|---------|-------------| -| `-dev.N` | Development milestone | Active development toward a target version | | `-alpha.N` | Alpha pre-release | Feature-complete but untested broadly | | `-beta.N` | Beta pre-release | Testing with wider audience | | `-rc.N` | Release candidate | Final validation before stable | **Convention:** -- Set the target version with `-dev.0` when starting a major effort (e.g. `2.0.0-dev.0`) -- Bump the dev counter (`-dev.N` → `-dev.N+1`) when a meaningful batch of landed work is ready to publish — a completed spec, a related feature group, or a release train -- Don't bump for every commit — that's what git history is for -- Strip the suffix (`-dev.N` → `2.0.0`) when all planned work is complete +- Use standard SemVer pre-release identifiers (`alpha`, `beta`, or `rc`) when publishing pre-release versions. - `loaf release` handles all bump types: `prerelease`, `release`, `major`, `minor`, `patch` -**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects with multi-milestone development cycles. +**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects publishing staged pre-releases before stable releases. diff --git a/content/skills/handoff/SKILL.md b/content/skills/handoff/SKILL.md index 5e8b05d94..10a44bcd2 100644 --- a/content/skills/handoff/SKILL.md +++ b/content/skills/handoff/SKILL.md @@ -119,3 +119,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/content/skills/housekeeping/SKILL.md b/content/skills/housekeeping/SKILL.md index 5b16cb910..db271a8db 100644 --- a/content/skills/housekeeping/SKILL.md +++ b/content/skills/housekeeping/SKILL.md @@ -136,3 +136,7 @@ After housekeeping, suggest `/reflect` if the session produced key decisions or | Report Template | [templates/report.md](templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/content/skills/implement/SKILL.md b/content/skills/implement/SKILL.md index 01a3901d4..f09a95ef2 100644 --- a/content/skills/implement/SKILL.md +++ b/content/skills/implement/SKILL.md @@ -89,9 +89,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -343,7 +343,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/content/skills/implement/references/batch-orchestration.md b/content/skills/implement/references/batch-orchestration.md index 4610769c8..1605537f1 100644 --- a/content/skills/implement/references/batch-orchestration.md +++ b/content/skills/implement/references/batch-orchestration.md @@ -2,63 +2,63 @@ ## Contents - Orchestration Options -- Batch Resolution and Wave Planning +- Batch Resolution and Dependency-Ready Scheduling - Option Handling - Batch Execution Model - Blocked-State Recovery -Detailed reference for running specs, task ranges, or task lists with dependency waves. +Detailed reference for running specs, task ranges, or task lists with dependency-ready scheduling. ## Orchestration Options | Option | Behavior | |--------|----------| -| `--dry-run` | Show dependency/wave execution plan, do not run agents | -| `--parallel` | Run tasks in the same wave concurrently (max 3 at once) | -| `--continue` | Resume a blocked orchestration from the recorded task/wave | +| `--dry-run` | Show dependency-ready execution plan, do not run agents | +| `--parallel` | Run tasks in the same dependency-ready group concurrently (max 3 at once) | +| `--continue` | Resume a blocked orchestration from the recorded task/group | | `--skip TASK-XXX` | Mark one blocked task as skipped and continue | | `--abort` | Mark orchestration as aborted and stop remaining work | -## Batch Resolution and Wave Planning +## Batch Resolution and Dependency-Ready Scheduling For `SPEC-XXX`, `TASK-XXX..YYY`, and `TASK-XXX,YYY,ZZZ`: 1. Resolve selected tasks and validate each task file exists. 2. Extract `depends_on` from each task and build a dependency graph. -3. Group tasks into dependency waves: - - Wave 1: tasks with no unresolved dependencies - - Wave N: tasks whose dependencies are completed in earlier waves -4. If `--parallel` is set, allow parallel execution only within a wave and only for non-conflicting tasks. -5. Present execution plan (tasks, waves, mode, total count) and ask for confirmation unless `--dry-run`. -6. Track progress in the journal and in task statuses: log wave boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. +3. Group tasks into dependency-ready rounds: + - First round: tasks with no unresolved dependencies + - Each subsequent round: tasks whose dependencies are completed in earlier rounds +4. If `--parallel` is set, allow parallel execution only within a dependency-ready round and only for non-conflicting tasks. +5. Present execution plan (tasks, dependency-ready rounds, mode, total count) and ask for confirmation unless `--dry-run`. +6. Track progress in the journal and in task statuses: log round boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. ## Option Handling (`--continue`, `--skip`, `--abort`) 1. Recover batch progress from the journal: `loaf journal recent --since-last-wrap` (or `loaf journal context`) plus `loaf task list --json` to see which tasks are still open. -2. If `--continue`: resume from the last logged wave and task. -3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same wave. +2. If `--continue`: resume from the last logged dependency-ready round and task. +3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same dependency-ready round. 4. If `--abort`: log `block(orchestration): aborted`, print a summary, and stop. 5. If no in-flight batch is evident from the journal, report that and ask for fresh selection input. ## Batch Execution Model -When input resolves to multiple tasks, run a wave-based loop: +When input resolves to multiple tasks, run a dependency-ready round loop: 1. Set orchestration mode (`sequential` by default, `parallel` only with `--parallel`). -2. For each wave: - - Log the wave start with `loaf journal log` +2. For each dependency-ready round: + - Log the round start with `loaf journal log` - Run each task (sequentially, or concurrently within safety limits) - For each task: set `in_progress` -> spawn agent -> run task verification -> mark `done`/`failed` via `loaf task update` 3. If any task fails verification, stop immediately and log `block(orchestration): failed `. -4. Consider a wave complete only when all its tasks are `done` or skipped. -5. Continue until all waves complete, then log a closing entry summarizing the batch. +4. Consider a round complete only when all its tasks are `done` or skipped. +5. Continue until all rounds complete, then log a closing entry summarizing the batch. ## Blocked-State Recovery When blocked, always print: - Failed task ID and title -- Wave number and current progress +- Dependency-ready round and current progress - Failure reason + key error output - Recovery commands: @@ -71,5 +71,5 @@ When blocked, always print: Use these semantics: - `--continue`: after fixes are applied, retry from the blocked task -- `--skip`: skip only the specified task and continue remaining tasks in the current wave +- `--skip`: skip only the specified task and continue remaining tasks in the current dependency-ready round - `--abort`: finalize the orchestration as aborted with no further execution diff --git a/content/skills/implement/references/branch-and-completion.md b/content/skills/implement/references/branch-and-completion.md index 0f715e4c5..250c8cdca 100644 --- a/content/skills/implement/references/branch-and-completion.md +++ b/content/skills/implement/references/branch-and-completion.md @@ -195,7 +195,7 @@ never implement through open `blockedBy`. **Print the current date and timestamp when:** - Waiting for user input or decision -- Completing a phase of work +- Completing a coherent unit of work - Encountering a blocker - Wrapping up the conversation diff --git a/content/skills/loaf-reference/SKILL.md b/content/skills/loaf-reference/SKILL.md index ff8c854aa..729f5a2a5 100644 --- a/content/skills/loaf-reference/SKILL.md +++ b/content/skills/loaf-reference/SKILL.md @@ -40,7 +40,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic. diff --git a/content/skills/loaf-reference/references/command-routing.md b/content/skills/loaf-reference/references/command-routing.md index 646de1213..bcf6893ca 100644 --- a/content/skills/loaf-reference/references/command-routing.md +++ b/content/skills/loaf-reference/references/command-routing.md @@ -6,8 +6,9 @@ Which command a task needs. For exact flags, run `loaf --help`. | Intent | Route | |--------|-------| -| Shape new work | `loaf change init `, then `loaf change check` | -| Start working on a task | the implement workflow ({{IMPLEMENT_CMD}}); `loaf task`/`loaf spec` stay transitional until the conversion pass — see the TRANSITIONAL note in CLAUDE.md | +| Shape new bounded work | `loaf change init `, then `loaf change check` | +| Start implementing new bounded work | the implement workflow ({{IMPLEMENT_CMD}}) after shaping and validating its Change | +| Continue an existing task or spec record | `loaf task` and `loaf spec` remain supported for existing records | | Continue after a restart | `loaf journal context` | | Skills or content changed | `loaf build && loaf install --to ` | | See what is in progress | `loaf task list --active` | diff --git a/content/skills/orchestration/SKILL.md b/content/skills/orchestration/SKILL.md index 3f6649c33..a6af2e4b6 100644 --- a/content/skills/orchestration/SKILL.md +++ b/content/skills/orchestration/SKILL.md @@ -17,7 +17,7 @@ description: >- - Philosophy - Configuration - Artifact Locations -- Three-Phase Workflow +- Workflow by Lifecycle Comprehensive patterns for orchestration: coordinating multi-agent work, keeping the project journal current, running councils, delegating to specialized agents, and integrating with Linear. @@ -129,7 +129,7 @@ This skill uses paths from `.agents/loaf.json`: **Rule:** Agents write artifacts to disk, orchestrator reasons over artifacts, users retrieve from disk. -## Three-Phase Workflow +## Workflow by Lifecycle ### BEFORE (Planning) - Create/check external issue (Linear, GitHub) diff --git a/content/skills/orchestration/references/context-management.md b/content/skills/orchestration/references/context-management.md index 4a577309f..fd07ec254 100644 --- a/content/skills/orchestration/references/context-management.md +++ b/content/skills/orchestration/references/context-management.md @@ -19,7 +19,7 @@ Patterns for keeping long work resumable while using the project journal as exte Compaction is normal in long workflows. Design work that spans many exchanges so important state is already outside chat context. 1. **The journal is external memory.** Record decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. **Artifacts carry detail.** Changes, transitional tasks, reports, ADRs, and commits hold rich detail; journal entries point to them. +2. **Artifacts carry detail.** Changes, task-board records, reports, ADRs, and commits hold rich detail; journal entries point to them. 3. **Delegated work absorbs exploration.** Use delegated agents for broad investigation and return concise findings to the main context. 4. **`wrap` captures synthesis.** When meaningful work holds intentions or abandoned paths worth saving, write an optional `wrap` journal entry. @@ -36,7 +36,7 @@ Compaction is normal in long workflows. Design work that spans many exchanges so | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent branch entries after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records retained during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each returned layer includes `source_available`, `available_count`, `shown_count`, `truncated`, and `expand_command`; paginated layers also include a cursor. Treat `source_available: false` as an explicit unavailable source, never as “nothing is active.” If Change discovery is unavailable, `active-changes` and `active-lineage` are unavailable and the digest carries a diagnostic. @@ -60,7 +60,7 @@ Use `/clear` when starting a completely new task, after the previous task is com PreCompact: 1. Flush unrecorded decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. Reference Changes, transitional tasks, reports, commits, and files by stable ID or path. +2. Reference Changes, task-board records, reports, commits, and files by stable ID or path. 3. On an exact target mode with supported PreCompact delivery, let the hook nudge the flush; otherwise flush manually before compacting. PostCompact: diff --git a/content/skills/orchestration/references/linear.md b/content/skills/orchestration/references/linear.md index 22d55b3ce..26ba14472 100644 --- a/content/skills/orchestration/references/linear.md +++ b/content/skills/orchestration/references/linear.md @@ -103,7 +103,7 @@ In Linear-native mode (`integrations.linear.enabled: true`), each spec produces one parent **rollup issue** and N sub-issues under it. ``` -[SPEC-024] Agent framework alignment ← parent, label: `spec` +Agent framework alignment ← parent, label: `change` ├── Split reviewer profile into reviewer/auditor ← sub-issue, label: type/refactor ├── Harden MCP fallback path ← sub-issue, label: type/feature └── Migrate legacy task references ← sub-issue, label: type/refactor @@ -127,8 +127,8 @@ researcher). Consolidate historical profile variants and add tool-boundary tests so profiles can't drift without a test failing. ## Context -See `.agents/specs/SPEC-024-agent-framework-alignment.md` for full text, -council references, rabbit holes, and strategic tensions. +See the canonical change file in the repository for full text, council +references, rabbit holes, and strategic tensions. ## Progress Sub-issues track execution. @@ -213,7 +213,7 @@ None currently. |-------|---------| | `Working on API` | `- [ ] API implementation` | | `Done with schema` | `- [x] Schema updated` | -| `Phase 1: Discovery` | `Discovery - COMPLETE` | +| `Discovery: IN PROGRESS` | `Discovery: COMPLETE` | | `Journal entry: ...` | *(omit entirely)* | | `Council decision: ...` | *(omit entirely)* | | `Week 1 deliverables` | `Initial deliverables` | @@ -373,6 +373,6 @@ Use `scripts/suggest-team.py "task desc"` to get suggestions. ### DON'T - Use emoji in progress lists - Reference local files (sessions, councils, plans) -- Use phase/stage/week terminology +- Use numbered development-stage terminology - Include absolute file paths - Duplicate issue titles after IDs diff --git a/content/skills/orchestration/references/local-tasks.md b/content/skills/orchestration/references/local-tasks.md index b3be1b591..1fe2364d6 100644 --- a/content/skills/orchestration/references/local-tasks.md +++ b/content/skills/orchestration/references/local-tasks.md @@ -167,7 +167,7 @@ project journal (`loaf journal recent`, `loaf journal search`). 1. Can a single specialized agent complete this? → If no, split by agent type 2. Does it touch multiple unrelated concerns? → If yes, split by concern -3. Will the agent need too much context? → If yes, split into phases +3. Will the agent need too much context? → If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? → If yes, merge back ### Agent Scope diff --git a/content/skills/orchestration/references/parallel-agents.md b/content/skills/orchestration/references/parallel-agents.md index 63cb39340..5fbec2b93 100644 --- a/content/skills/orchestration/references/parallel-agents.md +++ b/content/skills/orchestration/references/parallel-agents.md @@ -119,7 +119,7 @@ When streams complete: |---------|---------------------| | `/breakdown` | Identify parallelizable tasks during decomposition | | `/implement` | Single task, usually sequential | -| `/implement` | Runs dependency-wave orchestration, including parallel-safe tasks | +| `/implement` | Runs dependency-aware orchestration, including parallel-safe tasks | ## Conflict Resolution diff --git a/content/skills/refactor-deepen/SKILL.md b/content/skills/refactor-deepen/SKILL.md index d59db29a4..5d41d685f 100644 --- a/content/skills/refactor-deepen/SKILL.md +++ b/content/skills/refactor-deepen/SKILL.md @@ -82,12 +82,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -148,11 +148,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -209,7 +210,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -309,7 +310,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/content/skills/refactor-deepen/references/interface-design.md b/content/skills/refactor-deepen/references/interface-design.md index ca6b79df1..401ffced5 100644 --- a/content/skills/refactor-deepen/references/interface-design.md +++ b/content/skills/refactor-deepen/references/interface-design.md @@ -1,6 +1,6 @@ # Interface Design — Parallel Sub-Agent Pattern -The INTERFACE-DESIGN phase of `/refactor-deepen` proposes the public surface +The Interface Design activity of `/refactor-deepen` proposes the public surface of a deepened module by sampling three independent design attempts and presenting all three to the user. Variety must come from sampling, not from manufactured opposition. @@ -31,10 +31,8 @@ optimizes for minimalism, Agent 2 for flexibility, Agent 3 for the common-caller path. That choice is reasonable when the agents are domain-agnostic and the orchestrator wants guaranteed surface variety. -Loaf rejects that choice. The decision is captured in -[SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md), -specifically in the Rabbit Holes and No-Gos sections (lines 96 and 107). The -short version: priming manufactures diversity rather than letting it emerge, +Loaf rejects that choice. The active rule is to use identical briefs: priming +manufactures diversity rather than letting it emerge, and manufactured diversity is dishonest signal. If the three designs do converge, the response is more agents or rerun — not priming. See [Convergence Fallback](#convergence-fallback) below. @@ -71,7 +69,7 @@ Three reasons, in order of importance: 2. **No dominant lens upfront.** Picking which constraint each agent optimizes for is itself a design decision. Doing it pre-grilling biases - the entire phase toward whatever lens the orchestrator happened to + the entire activity toward whatever lens the orchestrator happened to pick. Loaf's grilling protocol is supposed to surface tradeoffs from the codebase and the user, not from the orchestrator's pre-commitments. @@ -91,7 +89,7 @@ Justification: researcher contract: "Return findings as structured reports: summary, options (ranked with trade-offs), evidence sources, and a recommendation." See [content/agents/researcher.md](../../../agents/researcher.md). -- Read-only access matches the phase's purpose. The INTERFACE-DESIGN phase +- Read-only access matches the activity's purpose. Interface Design proposes designs; it does not implement them. Granting write access invites scope creep into "let me just sketch the implementation" and pollutes the parallel sampling. @@ -102,14 +100,14 @@ Justification: ### When `implementer` Could Be an Alternative -If the design phase needs to write probe code — a quick spike to verify +If the design activity needs to write probe code — a quick spike to verify that a proposed interface compiles against the existing call sites, for example — the `implementer` profile becomes viable. See [content/agents/implementer.md](../../../agents/implementer.md). The default remains `researcher` because: -- Probe code at this phase is rarely necessary; the deepening review +- Probe code during this activity is rarely necessary; the deepening review catches most fatal interface mistakes before code is written. - Three implementers writing probe code in parallel risks three divergent partial implementations of the same module — a merge problem the user @@ -162,7 +160,7 @@ Inside the grilling loop, after dependency classification, only when: If the interface is obvious from the dependency category and the call sites — for example, a thin adapter over a true-external dependency — -skip the parallel phase. A single proposed interface is enough. +skip parallel exploration. A single proposed interface is enough. ## Convergence Fallback @@ -172,7 +170,7 @@ implementation strategy, same tradeoffs. Two cases: 1. **Convergence is real.** The problem has a single best answer. Accept the convergence as a genuine finding and proceed to the PLAN with that single design. Note in the PLAN's "rejected alternatives" section that - the parallel phase produced no meaningful variation. + parallel exploration produced no meaningful variation. 2. **Convergence feels accidental.** The designs are suspiciously similar, the user senses a missed branch, or the briefing was so @@ -226,7 +224,7 @@ escalates on its own. ## Cost Note -A single invocation of the parallel phase is approximately **3 × +A single invocation of parallel exploration is approximately **3 × deep-exploration cost** in tokens — three sub-agents each running a full design pass against the same context. With more-agents escalation, the cost scales linearly (4 agents = ~4 ×, 5 agents = ~5 ×). @@ -235,10 +233,10 @@ This pattern is **opt-in inside the grilling loop**. It is not auto-triggered on every `/refactor-deepen` invocation. The 3-agent default is the cost ceiling for the default settings — the skill does not scale agent count silently. If a candidate's interface is obvious, skip the -phase entirely and propose a single design. +activity entirely and propose a single design. The cost is an explicit tradeoff the user accepts when they enter the -INTERFACE-DESIGN phase for a non-obvious interface. The skill should +Interface Design activity for a non-obvious interface. The skill should surface the cost briefly before spawning: > Spawning 3 design agents in parallel (~3 × token cost). Proceed? @@ -265,7 +263,7 @@ After the three sub-agents return: | Don't | Do Instead | |-------|------------| | Prime agents with opposing constraints by default | Use identical briefs; let sampling produce variety | -| Auto-trigger the parallel phase on every invocation | Invoke only when interface is non-obvious | +| Auto-trigger parallel exploration on every invocation | Invoke only when interface is non-obvious | | Use `implementer` profile for design sub-agents | Use `researcher`; switch to `implementer` only on explicit user request | | Add a "lens" to the brief silently | Surface the tradeoff to the user before priming | | Pre-rank the three designs in the output | Present in arbitrary order, let the user pick | @@ -283,6 +281,3 @@ After the three sub-agents return: agent profile for design sub-agents - [content/agents/implementer.md](../../../agents/implementer.md) — Alternative profile when probe code is needed -- [SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md) - — The shape decision (lines 64, 96, 107, 117) that established the - identical-brief default diff --git a/content/skills/refactor-deepen/templates/plan.md b/content/skills/refactor-deepen/templates/plan.md index 54a591e61..f564229a3 100644 --- a/content/skills/refactor-deepen/templates/plan.md +++ b/content/skills/refactor-deepen/templates/plan.md @@ -27,7 +27,7 @@ write a new file rather than updating an existing one. |-------|----------|-------| | `title` | Yes | One-line description of the deepening, not the candidate name | | `created` | Yes | ISO 8601 UTC, e.g. `2026-05-02T01:30:00Z` (must match the filename timestamp) | -| `status` | Yes | `drafting` on first write — lifecycle states are deferred to a follow-up spec | +| `status` | Yes | `drafting` on first write; this template does not define additional lifecycle states | | `spec` | Yes | `SPEC-NNN` if the plan is scoped under a spec; `null` otherwise (do not omit the key) | | `related` | No | List of related artifact IDs (`ADR-*`, `SPEC-*`, idea filenames, other plan filenames) | @@ -36,8 +36,7 @@ identity, mirroring councils and ideas. ## Required Sections -The five sections below are the *minimal shape* defined in SPEC-034. Order is -load-bearing: each section assumes the previous one is settled. Do not reorder. +The five sections below are the *minimal shape* for a PLAN. Order is load-bearing: each section assumes the previous one is settled. Do not reorder. 1. **Candidate** — what's being considered for deepening. Name the **module** verbatim (use the canonical glossary term — run `loaf kb glossary check` @@ -111,14 +110,12 @@ proportional to actual usage, matching how `.agents/specs/` behaves. ## Linear-Native Mode: Fail Fast -PLAN files are **local-only storage**. Per SPEC-034 line 81, write commands -must fail fast in Linear-native mode rather than silently degrade. The -consuming skill (`/refactor-deepen`) is responsible for: +PLAN files are **local-only storage**. Write commands must fail fast in Linear-native mode rather than silently degrade. The consuming skill (`/refactor-deepen`) is responsible for: 1. Reading `.agents/loaf.json` and checking `integrations.linear.enabled`. 2. If true: aborting before `mkdir -p .agents/plans` and before any write, with the verbatim error - `"Linear-native plan storage pending artifact-taxonomy spec — local mode only for now."` + `"Linear-native plan storage unavailable — continuing with a read-only report."` 3. If false: proceeding with the write as documented above. This template intentionally does **not** wrap the write in a diff --git a/content/skills/research/SKILL.md b/content/skills/research/SKILL.md index 2523e6b8d..9befd9aaf 100644 --- a/content/skills/research/SKILL.md +++ b/content/skills/research/SKILL.md @@ -142,3 +142,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/content/skills/shape/SKILL.md b/content/skills/shape/SKILL.md index eb7ecee08..8edfcd643 100644 --- a/content/skills/shape/SKILL.md +++ b/content/skills/shape/SKILL.md @@ -162,3 +162,7 @@ Offer to push the branch and open a draft PR, using [the PR template](templates/ | Decomposition | [references/decomposition.md](references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/content/skills/shape/references/cli-boundary.md b/content/skills/shape/references/cli-boundary.md index efb3cc1b5..7f5816b03 100644 --- a/content/skills/shape/references/cli-boundary.md +++ b/content/skills/shape/references/cli-boundary.md @@ -13,7 +13,7 @@ Folder resolution: an explicit `[folder]` argument always wins; otherwise the cu Output splits into two tiers: - **Violations** — always fail (exit code 2), regardless of flags: status-like frontmatter keys (`readiness`, `status`, `state`) or values matching the canonical change-state vocabulary; frontmatter not opening the file at byte one; malformed `YYYYMMDD-slug` folder naming; identity mismatch between `change:`/`created:` and the folder name; missing Product Contract sections (Problem, Hypothesis, Scope, Observable Workflow, Rabbit Holes and No-Gos). -- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A shaping-stage Change with open gaps is valid; the report just says what's still missing. +- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A Change with open gaps is incomplete and non-executable; the report just says what's still missing. `--require-executable` turns structural executability into a gate (exit code 1 if not structurally executable); it does not prove implementation completion. This is implement's preflight and CI's non-draft-PR check, not something shape itself passes during shaping. diff --git a/content/skills/shape/references/decomposition.md b/content/skills/shape/references/decomposition.md index edf38530b..5ffefbe74 100644 --- a/content/skills/shape/references/decomposition.md +++ b/content/skills/shape/references/decomposition.md @@ -4,7 +4,7 @@ Shaping step absorbed from the retired breakdown skill: dependency awareness, gr ## What Survives -- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into phases. Are you splitting just to have more units? If yes, merge back. +- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into smaller coherent units. Are you splitting just to have more units? If yes, merge back. - **Right-sizing rules** — one agent type per unit (completable by a single implementer), one concern per unit (one layer, service, or component), context-appropriate (fits in model context with room for exploration), not over-fragmented (don't split what naturally belongs together). - **Per-unit verification discipline** — every unit includes its own observable done condition. Never a separate "verify" unit; keep tests with the code they test. - **Own the decisions** — decide granularity and unit boundaries autonomously. Ask the user only when two orderings are genuinely equally valid with different trade-offs; otherwise decide and move on. diff --git a/dist/amp/.amp/plugins/loaf.ts b/dist/amp/.amp/plugins/loaf.ts index d48508732..cef5a419a 100644 --- a/dist/amp/.amp/plugins/loaf.ts +++ b/dist/amp/.amp/plugins/loaf.ts @@ -304,6 +304,13 @@ const preToolHooks: Record = { "failClosed": true, "if": "Bash(git push:*)" }, + { + "id": "artifact-names", + "command": "loaf check --hook artifact-names", + "timeout": 30000, + "failClosed": true, + "if": "Bash(git commit:*)" + }, { "id": "github-account", "command": "loaf check --hook github-account", diff --git a/dist/amp/.loaf-target-manifest.json b/dist/amp/.loaf-target-manifest.json index c5e33ed30..4be83d890 100644 --- a/dist/amp/.loaf-target-manifest.json +++ b/dist/amp/.loaf-target-manifest.json @@ -18,7 +18,7 @@ "kind": "plugin", "source_path": ".amp/plugins/loaf.ts", "destination": "plugins/loaf.ts", - "sha256": "4d32640ea608e077703b50026fbef3f0496aee0de10a585c686bfe605ac2af6f", + "sha256": "3aca4420a45c57928cb4484bb3793ba519b8ff87ff10c6475829a84db1cdac5e", "mode": 420 } ] diff --git a/dist/amp/skills/architecture/SKILL.md b/dist/amp/skills/architecture/SKILL.md index 65100921e..b21c3f00e 100644 --- a/dist/amp/skills/architecture/SKILL.md +++ b/dist/amp/skills/architecture/SKILL.md @@ -43,7 +43,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/dist/amp/skills/bootstrap/SKILL.md b/dist/amp/skills/bootstrap/SKILL.md index 97b4f3c30..42d37452a 100644 --- a/dist/amp/skills/bootstrap/SKILL.md +++ b/dist/amp/skills/bootstrap/SKILL.md @@ -218,7 +218,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -227,14 +227,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -244,9 +244,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/dist/amp/skills/bootstrap/references/interview-guide.md b/dist/amp/skills/bootstrap/references/interview-guide.md index ad67e1947..3313798f0 100644 --- a/dist/amp/skills/bootstrap/references/interview-guide.md +++ b/dist/amp/skills/bootstrap/references/interview-guide.md @@ -5,10 +5,10 @@ A structured interview framework for helping builders go from a vague idea to a ## Contents - How This Guide Works - Framework Foundations -- Phase 1: Excavation (The Spark) -- Phase 2: Sharpening (The Shape) -- Phase 3: Grounding (The Architecture) -- Phase 4: Synthesis (The Documents) +- Excavation (The Spark) +- Sharpening (The Shape) +- Grounding (The Architecture) +- Synthesis (The Documents) - Adapting Interview Depth - Anti-Patterns - Transitioning to Document Drafting @@ -17,16 +17,16 @@ A structured interview framework for helping builders go from a vague idea to a This is a **builder interview**, not a user research interview. The interviewer (the agent) is helping the builder crystallize their own thinking -- not extracting requirements from a stakeholder. The builder has context, intuition, and taste that need to be surfaced, challenged, and structured. -The interview flows through four phases, each producing progressively sharper artifacts: +The interview flows through four sections, each producing progressively sharper artifacts: -| Phase | Focus | Primary Output | Frameworks | +| Section | Focus | Primary Output | Frameworks | |-------|-------|----------------|------------| -| 1. Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | -| 2. Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | -| 3. Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | -| 4. Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | +| Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | +| Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | +| Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | +| Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | -Phases are not rigid walls. A strong answer in Phase 1 might skip half of Phase 2. A weak answer in Phase 2 might loop back to Phase 1. Follow the energy. +Sections are not rigid walls. A strong answer in Excavation might skip half of Sharpening. A weak answer in Sharpening might loop back to Excavation. Follow the energy. --- @@ -80,7 +80,7 @@ What each framework contributes and what to skip. **What to skip:** Customer interview logistics, meeting scheduling advice. The Mom Test is about question quality, not interview operations. -**Connection to documents:** Informs the quality of every answer in every phase. The Mom Test isn't a phase -- it's a lens applied to ALL questioning. It keeps the interview honest. +**Connection to documents:** Informs the quality of every answer in every section. The Mom Test isn't a section -- it's a lens applied to ALL questioning. It keeps the interview honest. ### Design Sprint - Understand Phase (Google Ventures) @@ -120,7 +120,7 @@ What each framework contributes and what to skip. --- -## Phase 1: Excavation (The Spark) +## Excavation (The Spark) **Goal:** Understand what exists, why it matters, and whether the problem is real. @@ -157,9 +157,9 @@ The builder's own experience with the problem is the richest source of insight. - "Have you seen anyone spend money or significant time on this problem?" *(Mom Test: evidence of pain)* - "Is this problem getting worse or better over time? Why?" *(Wardley: movement awareness)* -### Phase 1 Signals +### Excavation Signals -**Strong signal (move to Phase 2):** Builder can describe a specific person with a specific problem and knows what they do about it today. +**Strong signal (move to Sharpening):** Builder can describe a specific person with a specific problem and knows what they do about it today. **Weak signal (dig deeper):** Builder describes a category ("developers need better tools") without specifics. Ask for a story: "Tell me about a specific moment when this problem was most painful." @@ -167,13 +167,13 @@ The builder's own experience with the problem is the richest source of insight. --- -## Phase 2: Sharpening (The Shape) +## Sharpening (The Shape) **Goal:** Define who this is for, what it does, and -- critically -- what it does NOT do. Set complexity and boundaries. -**Mood:** Constructive pressure. Phase 1 was expansive; Phase 2 is reductive. The builder will want to include everything. Your job is to help them cut. +**Mood:** Constructive pressure. Excavation was expansive; Sharpening is reductive. The builder will want to include everything. Your job is to help them cut. -**Duration:** This is typically the longest phase. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. +**Duration:** This is typically the longest section. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. ### Must-Ask Questions @@ -210,17 +210,17 @@ Surface the riskiest assumptions. "Will users actually switch from their current - "How might we make [the hardest part] effortless?" *(Design Sprint: HMW)* - "What would definitely make this fail?" *(First Principles: inversion)* -### Phase 2 Signals +### Sharpening Signals -**Strong signal (move to Phase 3):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. +**Strong signal (move to Grounding):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. **Weak signal (iterate):** Builder keeps expanding scope. "It should also..." is a signal to tighten. Ask: "If you could only do ONE thing, what would it be?" -**Red flag (loop back to Phase 1):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" +**Red flag (loop back to Excavation):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" --- -## Phase 3: Grounding (The Architecture) +## Grounding (The Architecture) **Goal:** Establish technical direction, identify what to build vs. buy, and surface hidden complexity. @@ -257,19 +257,19 @@ These become the rabbit holes in the spec. The builder often knows where the dra - "If you had to ship something in one week, what would you cut?" *(Shape Up: scope pressure test)* - "Are there regulatory, legal, or compliance considerations?" *(Often forgotten at 0-to-1)* -### Phase 3 Signals +### Grounding Signals -**Strong signal (move to Phase 4):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. +**Strong signal (move to Synthesis):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. **Weak signal (iterate):** Builder wants to build everything from scratch. Challenge: "What's the thing ONLY YOU can build? Build that. Use existing solutions for the rest." -**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Phase 3 and note that ARCHITECTURE.md will be populated later when technical decisions are made. +**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Grounding and note that ARCHITECTURE.md will be populated later when technical decisions are made. --- -## Phase 4: Synthesis (The Documents) +## Synthesis (The Documents) -**Goal:** Transform interview insights into draft documents. This is NOT a phase of the interview -- it's the transition from interviewing to drafting. +**Goal:** Transform interview insights into draft documents. This is NOT an interview section -- it's the transition from interviewing to drafting. **Mood:** Collaborative, iterative. The agent drafts, the builder reacts and refines. @@ -319,11 +319,11 @@ Allow the builder to approve all remaining sections at once if they're satisfied ## Adapting Interview Depth -The interview adapts to three contexts, per SPEC-013's mode detection: +The interview adapts to three contexts based on the detected project mode: ### Greenfield + Empty (Full Interview) -Run all four phases in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all phases. This is where the interview guide earns its keep. +Run all four sections in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all sections. This is where the interview guide earns its keep. **Key adaptation:** Be patient. The builder may circle back, contradict themselves, or get stuck. That's normal. Let them think out loud. Silence after a question is productive, not awkward. @@ -332,9 +332,9 @@ Run all four phases in full. The builder has minimal clarity and needs the most Read and analyze the brief first. Then run a compressed interview that: - Confirms understanding ("Here's what I extracted -- is this right?") - Challenges assumptions ("Your brief says X, but have you considered Y?") -- Fills gaps (which phases have missing information?) +- Fills gaps (which sections have missing information?) -Expect 8-12 questions total, concentrated in whichever phases the brief is weakest. +Expect 8-12 questions total, concentrated in whichever sections the brief is weakest. **Key adaptation:** Don't re-ask what the brief already answers well. Quote the brief back and ask "Is this still accurate?" to confirm, then move to gaps. @@ -345,7 +345,7 @@ The project exists. Code exists. Docs may exist. The interview focuses on: - What the builder wants to CHANGE (current pain, technical debt, strategic shifts) - What conventions and preferences exist but aren't documented -Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered by the existing codebase. +Expect 6-10 questions total, mostly in Excavation and Sharpening. Grounding is largely answered by the existing codebase. **Key adaptation:** Show the builder what you learned from their code. "I see a Python/FastAPI project with PostgreSQL and Docker. The test suite uses pytest. Is that the intended stack going forward?" Let the codebase speak first, then fill gaps. @@ -361,13 +361,13 @@ Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered b **The Therapist.** "And how does that make you feel about your product?" No. This is a builder interview, not a feelings exploration. Emotions matter (JTBD switching forces), but ask about user emotions, not builder emotions. -**Premature Architecture.** Jumping to "What database should we use?" in Phase 1. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. +**Premature Architecture.** Jumping to "What database should we use?" during Excavation. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. **The Echo Chamber.** Reflecting back everything the builder says without challenging anything. The Mom Test exists because people are too polite. Be constructive, not agreeable. "That's a big scope. Are you sure you need ALL of that for v1?" **Solution-First Questioning.** "What features should it have?" is the wrong question. "What job does it do for the user?" is the right one. Features are an output of the interview, not an input. -**Asking for Permission to Proceed.** Don't ask "Should we move to the next phase?" Just move when the signals are strong. If the builder has more to say, they'll say it. +**Asking for Permission to Proceed.** Don't ask "Should we move to the next section?" Just move when the signals are strong. If the builder has more to say, they'll say it. **Over-Indexing on Frameworks.** Don't say "Let's do a JTBD analysis" or "Let me apply Wardley Mapping here." The frameworks are lenses for the interviewer, not vocabulary for the builder. Just ask good questions. @@ -413,12 +413,12 @@ The bootstrap interview creates the foundation. Other skills deepen specific are ## Framework Attribution -| Framework | Primary Contribution | Phase(s) | +| Framework | Primary Contribution | Section(s) | |-----------|---------------------|----------| -| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | 2, 3 | -| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | 1, 2 | -| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | 1, 2 | -| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All phases | -| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | 2, 3 | -| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | 3 | -| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | 1, 3 | +| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | Sharpening, Grounding | +| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | Excavation, Sharpening | +| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | Excavation, Sharpening | +| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All sections | +| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | Sharpening, Grounding | +| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | Grounding | +| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | Excavation, Grounding | diff --git a/dist/amp/skills/breakdown/SKILL.md b/dist/amp/skills/breakdown/SKILL.md index 94b1f3a4d..90b40fc52 100644 --- a/dist/amp/skills/breakdown/SKILL.md +++ b/dist/amp/skills/breakdown/SKILL.md @@ -89,7 +89,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/dist/amp/skills/foundations/SKILL.md b/dist/amp/skills/foundations/SKILL.md index 1e7d3cbcc..4c0d3bdbd 100644 --- a/dist/amp/skills/foundations/SKILL.md +++ b/dist/amp/skills/foundations/SKILL.md @@ -114,6 +114,22 @@ Engineering foundations for consistent, high-quality code. | Constants | `UPPER_SNAKE` | `UPPER_SNAKE` | | Tests | `test___` | `describe/it` blocks | +### Artifact Names Never Cite Their Work Unit + +Name an artifact for what it is, never for the work unit that produced it. The directory or Change that contains it already records that provenance, so repeating it in the filename inverts the reference and rots the moment the work closes: a work unit points at its artifacts, artifacts never point back. + +| Instead of | Write | +|------------|-------| +| `u8-claude-smoke.mjs` | `smoke-claude-code-startup.mjs` | +| `report-spec-053-taxonomy-signoff.md` | `taxonomy-signoff.md` | +| `TASK-074-sidecar-audit-report.md` | `sidecar-audit.md` | + +Provenance belongs in a front-matter field such as `source:`, where it can be read and updated, not in a name that has to be renamed to stay true. + +Two look-alikes are correct and stay. A **version** is identity, not reference: `claude-code-2.1.218-plugin-startup-smoke.json`. A **timestamp** records when, not which work unit: `20260620-214448-skills-audit.md`. And a numbered record living in the directory that owns it *is* that entity, so `.agents/specs/SPEC-042-slug.md` and `docs/decisions/ADR-007-slug.md` are its own name rather than a citation. + +`loaf check --hook artifact-names` enforces this at commit time over tracked artifacts, grandfathering anything already `final` or `archived`. + ## Test Patterns Scenario-based fixture naming: diff --git a/dist/amp/skills/git-workflow/references/commits.md b/dist/amp/skills/git-workflow/references/commits.md index 5ed2ba9e1..d6a48ab9b 100644 --- a/dist/amp/skills/git-workflow/references/commits.md +++ b/dist/amp/skills/git-workflow/references/commits.md @@ -185,7 +185,7 @@ Internal terms that have no meaning outside the team's working context: - Spec IDs and task IDs (`SPEC-024`, `TASK-042`) - Session, sprint, or branch references - Internal terminology from skills/docs that isn't part of the user's mental model — e.g. `Q1`/`Q2`/`Q3` question numbers from a Triage Gate, internal gate-logic notation like `(Q1 OR Q2) AND Q3`, hook IDs that aren't user-facing -- "How the work got done" framing — interview steps, breakdown phases, review gates +- "How the work got done" framing — interview steps, breakdown steps, review gates ### Keep @@ -252,7 +252,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE] Four hooks automatically enforce the conventions documented in this file: -| Hook | Phase | Behavior | +| Hook | Timing | Behavior | |------|-------|----------| | `github-account` | Pre-tool (Bash) | Force-switch: switches the active `gh` account to the configured one before `gh` commands run (passes with a warning), exempting `gh auth` administration, and blocks only when the switch fails. It writes the shared global account pointer on every mismatched `gh` call -- read-only ones included -- so concurrent sessions on different identities collide on that pointer more often. | | `workflow-pre-pr` | Pre-tool (Bash) | Advisory: reminds about CHANGELOG [Unreleased] entries and PR format. Non-blocking. | @@ -269,26 +269,14 @@ BREAKING CHANGE: Description of breaking change. ### Pre-Release Versions -When developing toward a major version, use pre-release suffixes to mark development milestones: - -``` -2.0.0-dev.0 → dev.1 → dev.2 → ... → 2.0.0 - ↑ ↑ ↑ ↑ - start dev milestone milestone stable release -``` - | Suffix | Meaning | When to use | |--------|---------|-------------| -| `-dev.N` | Development milestone | Active development toward a target version | | `-alpha.N` | Alpha pre-release | Feature-complete but untested broadly | | `-beta.N` | Beta pre-release | Testing with wider audience | | `-rc.N` | Release candidate | Final validation before stable | **Convention:** -- Set the target version with `-dev.0` when starting a major effort (e.g. `2.0.0-dev.0`) -- Bump the dev counter (`-dev.N` → `-dev.N+1`) when a meaningful batch of landed work is ready to publish — a completed spec, a related feature group, or a release train -- Don't bump for every commit — that's what git history is for -- Strip the suffix (`-dev.N` → `2.0.0`) when all planned work is complete +- Use standard SemVer pre-release identifiers (`alpha`, `beta`, or `rc`) when publishing pre-release versions. - `loaf release` handles all bump types: `prerelease`, `release`, `major`, `minor`, `patch` -**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects with multi-milestone development cycles. +**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects publishing staged pre-releases before stable releases. diff --git a/dist/amp/skills/handoff/SKILL.md b/dist/amp/skills/handoff/SKILL.md index c72f2382c..671e52e04 100644 --- a/dist/amp/skills/handoff/SKILL.md +++ b/dist/amp/skills/handoff/SKILL.md @@ -120,3 +120,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/amp/skills/housekeeping/SKILL.md b/dist/amp/skills/housekeeping/SKILL.md index 4dc92d49f..ca0ebb341 100644 --- a/dist/amp/skills/housekeeping/SKILL.md +++ b/dist/amp/skills/housekeeping/SKILL.md @@ -138,3 +138,7 @@ After housekeeping, suggest `/reflect` if the session produced key decisions or | Report Template | [templates/report.md](templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/amp/skills/implement/SKILL.md b/dist/amp/skills/implement/SKILL.md index 9c653c87a..a07b4d110 100644 --- a/dist/amp/skills/implement/SKILL.md +++ b/dist/amp/skills/implement/SKILL.md @@ -91,9 +91,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -345,7 +345,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/dist/amp/skills/implement/references/batch-orchestration.md b/dist/amp/skills/implement/references/batch-orchestration.md index 7b69603f5..69fe524c5 100644 --- a/dist/amp/skills/implement/references/batch-orchestration.md +++ b/dist/amp/skills/implement/references/batch-orchestration.md @@ -2,63 +2,63 @@ ## Contents - Orchestration Options -- Batch Resolution and Wave Planning +- Batch Resolution and Dependency-Ready Scheduling - Option Handling - Batch Execution Model - Blocked-State Recovery -Detailed reference for running specs, task ranges, or task lists with dependency waves. +Detailed reference for running specs, task ranges, or task lists with dependency-ready scheduling. ## Orchestration Options | Option | Behavior | |--------|----------| -| `--dry-run` | Show dependency/wave execution plan, do not run agents | -| `--parallel` | Run tasks in the same wave concurrently (max 3 at once) | -| `--continue` | Resume a blocked orchestration from the recorded task/wave | +| `--dry-run` | Show dependency-ready execution plan, do not run agents | +| `--parallel` | Run tasks in the same dependency-ready group concurrently (max 3 at once) | +| `--continue` | Resume a blocked orchestration from the recorded task/group | | `--skip TASK-XXX` | Mark one blocked task as skipped and continue | | `--abort` | Mark orchestration as aborted and stop remaining work | -## Batch Resolution and Wave Planning +## Batch Resolution and Dependency-Ready Scheduling For `SPEC-XXX`, `TASK-XXX..YYY`, and `TASK-XXX,YYY,ZZZ`: 1. Resolve selected tasks and validate each task file exists. 2. Extract `depends_on` from each task and build a dependency graph. -3. Group tasks into dependency waves: - - Wave 1: tasks with no unresolved dependencies - - Wave N: tasks whose dependencies are completed in earlier waves -4. If `--parallel` is set, allow parallel execution only within a wave and only for non-conflicting tasks. -5. Present execution plan (tasks, waves, mode, total count) and ask for confirmation unless `--dry-run`. -6. Track progress in the journal and in task statuses: log wave boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. +3. Group tasks into dependency-ready rounds: + - First round: tasks with no unresolved dependencies + - Each subsequent round: tasks whose dependencies are completed in earlier rounds +4. If `--parallel` is set, allow parallel execution only within a dependency-ready round and only for non-conflicting tasks. +5. Present execution plan (tasks, dependency-ready rounds, mode, total count) and ask for confirmation unless `--dry-run`. +6. Track progress in the journal and in task statuses: log round boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. ## Option Handling (`--continue`, `--skip`, `--abort`) 1. Recover batch progress from the journal: `loaf journal recent --since-last-wrap` (or `loaf journal context`) plus `loaf task list --json` to see which tasks are still open. -2. If `--continue`: resume from the last logged wave and task. -3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same wave. +2. If `--continue`: resume from the last logged dependency-ready round and task. +3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same dependency-ready round. 4. If `--abort`: log `block(orchestration): aborted`, print a summary, and stop. 5. If no in-flight batch is evident from the journal, report that and ask for fresh selection input. ## Batch Execution Model -When input resolves to multiple tasks, run a wave-based loop: +When input resolves to multiple tasks, run a dependency-ready round loop: 1. Set orchestration mode (`sequential` by default, `parallel` only with `--parallel`). -2. For each wave: - - Log the wave start with `loaf journal log` +2. For each dependency-ready round: + - Log the round start with `loaf journal log` - Run each task (sequentially, or concurrently within safety limits) - For each task: set `in_progress` -> spawn agent -> run task verification -> mark `done`/`failed` via `loaf task update` 3. If any task fails verification, stop immediately and log `block(orchestration): failed `. -4. Consider a wave complete only when all its tasks are `done` or skipped. -5. Continue until all waves complete, then log a closing entry summarizing the batch. +4. Consider a round complete only when all its tasks are `done` or skipped. +5. Continue until all rounds complete, then log a closing entry summarizing the batch. ## Blocked-State Recovery When blocked, always print: - Failed task ID and title -- Wave number and current progress +- Dependency-ready round and current progress - Failure reason + key error output - Recovery commands: @@ -71,5 +71,5 @@ When blocked, always print: Use these semantics: - `--continue`: after fixes are applied, retry from the blocked task -- `--skip`: skip only the specified task and continue remaining tasks in the current wave +- `--skip`: skip only the specified task and continue remaining tasks in the current dependency-ready round - `--abort`: finalize the orchestration as aborted with no further execution diff --git a/dist/amp/skills/implement/references/branch-and-completion.md b/dist/amp/skills/implement/references/branch-and-completion.md index 0f715e4c5..250c8cdca 100644 --- a/dist/amp/skills/implement/references/branch-and-completion.md +++ b/dist/amp/skills/implement/references/branch-and-completion.md @@ -195,7 +195,7 @@ never implement through open `blockedBy`. **Print the current date and timestamp when:** - Waiting for user input or decision -- Completing a phase of work +- Completing a coherent unit of work - Encountering a blocker - Wrapping up the conversation diff --git a/dist/amp/skills/loaf-reference/SKILL.md b/dist/amp/skills/loaf-reference/SKILL.md index 770deae54..526ddcbeb 100644 --- a/dist/amp/skills/loaf-reference/SKILL.md +++ b/dist/amp/skills/loaf-reference/SKILL.md @@ -46,7 +46,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic. diff --git a/dist/amp/skills/loaf-reference/references/command-routing.md b/dist/amp/skills/loaf-reference/references/command-routing.md index 14a8ded99..de4f16c02 100644 --- a/dist/amp/skills/loaf-reference/references/command-routing.md +++ b/dist/amp/skills/loaf-reference/references/command-routing.md @@ -6,8 +6,9 @@ Which command a task needs. For exact flags, run `loaf --help`. | Intent | Route | |--------|-------| -| Shape new work | `loaf change init `, then `loaf change check` | -| Start working on a task | the implement workflow (/implement); `loaf task`/`loaf spec` stay transitional until the conversion pass — see the TRANSITIONAL note in AGENTS.md | +| Shape new bounded work | `loaf change init `, then `loaf change check` | +| Start implementing new bounded work | the implement workflow (/implement) after shaping and validating its Change | +| Continue an existing task or spec record | `loaf task` and `loaf spec` remain supported for existing records | | Continue after a restart | `loaf journal context` | | Skills or content changed | `loaf build && loaf install --to ` | | See what is in progress | `loaf task list --active` | diff --git a/dist/amp/skills/orchestration/SKILL.md b/dist/amp/skills/orchestration/SKILL.md index 8998a3075..25ad69891 100644 --- a/dist/amp/skills/orchestration/SKILL.md +++ b/dist/amp/skills/orchestration/SKILL.md @@ -18,7 +18,7 @@ version: 2.0.0-alpha.13 - Philosophy - Configuration - Artifact Locations -- Three-Phase Workflow +- Workflow by Lifecycle Comprehensive patterns for orchestration: coordinating multi-agent work, keeping the project journal current, running councils, delegating to specialized agents, and integrating with Linear. @@ -130,7 +130,7 @@ This skill uses paths from `.agents/loaf.json`: **Rule:** Agents write artifacts to disk, orchestrator reasons over artifacts, users retrieve from disk. -## Three-Phase Workflow +## Workflow by Lifecycle ### BEFORE (Planning) - Create/check external issue (Linear, GitHub) diff --git a/dist/amp/skills/orchestration/references/context-management.md b/dist/amp/skills/orchestration/references/context-management.md index 4a577309f..fd07ec254 100644 --- a/dist/amp/skills/orchestration/references/context-management.md +++ b/dist/amp/skills/orchestration/references/context-management.md @@ -19,7 +19,7 @@ Patterns for keeping long work resumable while using the project journal as exte Compaction is normal in long workflows. Design work that spans many exchanges so important state is already outside chat context. 1. **The journal is external memory.** Record decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. **Artifacts carry detail.** Changes, transitional tasks, reports, ADRs, and commits hold rich detail; journal entries point to them. +2. **Artifacts carry detail.** Changes, task-board records, reports, ADRs, and commits hold rich detail; journal entries point to them. 3. **Delegated work absorbs exploration.** Use delegated agents for broad investigation and return concise findings to the main context. 4. **`wrap` captures synthesis.** When meaningful work holds intentions or abandoned paths worth saving, write an optional `wrap` journal entry. @@ -36,7 +36,7 @@ Compaction is normal in long workflows. Design work that spans many exchanges so | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent branch entries after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records retained during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each returned layer includes `source_available`, `available_count`, `shown_count`, `truncated`, and `expand_command`; paginated layers also include a cursor. Treat `source_available: false` as an explicit unavailable source, never as “nothing is active.” If Change discovery is unavailable, `active-changes` and `active-lineage` are unavailable and the digest carries a diagnostic. @@ -60,7 +60,7 @@ Use `/clear` when starting a completely new task, after the previous task is com PreCompact: 1. Flush unrecorded decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. Reference Changes, transitional tasks, reports, commits, and files by stable ID or path. +2. Reference Changes, task-board records, reports, commits, and files by stable ID or path. 3. On an exact target mode with supported PreCompact delivery, let the hook nudge the flush; otherwise flush manually before compacting. PostCompact: diff --git a/dist/amp/skills/orchestration/references/linear.md b/dist/amp/skills/orchestration/references/linear.md index 22d55b3ce..26ba14472 100644 --- a/dist/amp/skills/orchestration/references/linear.md +++ b/dist/amp/skills/orchestration/references/linear.md @@ -103,7 +103,7 @@ In Linear-native mode (`integrations.linear.enabled: true`), each spec produces one parent **rollup issue** and N sub-issues under it. ``` -[SPEC-024] Agent framework alignment ← parent, label: `spec` +Agent framework alignment ← parent, label: `change` ├── Split reviewer profile into reviewer/auditor ← sub-issue, label: type/refactor ├── Harden MCP fallback path ← sub-issue, label: type/feature └── Migrate legacy task references ← sub-issue, label: type/refactor @@ -127,8 +127,8 @@ researcher). Consolidate historical profile variants and add tool-boundary tests so profiles can't drift without a test failing. ## Context -See `.agents/specs/SPEC-024-agent-framework-alignment.md` for full text, -council references, rabbit holes, and strategic tensions. +See the canonical change file in the repository for full text, council +references, rabbit holes, and strategic tensions. ## Progress Sub-issues track execution. @@ -213,7 +213,7 @@ None currently. |-------|---------| | `Working on API` | `- [ ] API implementation` | | `Done with schema` | `- [x] Schema updated` | -| `Phase 1: Discovery` | `Discovery - COMPLETE` | +| `Discovery: IN PROGRESS` | `Discovery: COMPLETE` | | `Journal entry: ...` | *(omit entirely)* | | `Council decision: ...` | *(omit entirely)* | | `Week 1 deliverables` | `Initial deliverables` | @@ -373,6 +373,6 @@ Use `scripts/suggest-team.py "task desc"` to get suggestions. ### DON'T - Use emoji in progress lists - Reference local files (sessions, councils, plans) -- Use phase/stage/week terminology +- Use numbered development-stage terminology - Include absolute file paths - Duplicate issue titles after IDs diff --git a/dist/amp/skills/orchestration/references/local-tasks.md b/dist/amp/skills/orchestration/references/local-tasks.md index c8d03e9eb..f7fb21939 100644 --- a/dist/amp/skills/orchestration/references/local-tasks.md +++ b/dist/amp/skills/orchestration/references/local-tasks.md @@ -167,7 +167,7 @@ project journal (`loaf journal recent`, `loaf journal search`). 1. Can a single specialized agent complete this? → If no, split by agent type 2. Does it touch multiple unrelated concerns? → If yes, split by concern -3. Will the agent need too much context? → If yes, split into phases +3. Will the agent need too much context? → If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? → If yes, merge back ### Agent Scope diff --git a/dist/amp/skills/orchestration/references/parallel-agents.md b/dist/amp/skills/orchestration/references/parallel-agents.md index c7a47db06..c2998df61 100644 --- a/dist/amp/skills/orchestration/references/parallel-agents.md +++ b/dist/amp/skills/orchestration/references/parallel-agents.md @@ -119,7 +119,7 @@ When streams complete: |---------|---------------------| | `/breakdown` | Identify parallelizable tasks during decomposition | | `/implement` | Single task, usually sequential | -| `/implement` | Runs dependency-wave orchestration, including parallel-safe tasks | +| `/implement` | Runs dependency-aware orchestration, including parallel-safe tasks | ## Conflict Resolution diff --git a/dist/amp/skills/refactor-deepen/SKILL.md b/dist/amp/skills/refactor-deepen/SKILL.md index a8803d341..e1d120b94 100644 --- a/dist/amp/skills/refactor-deepen/SKILL.md +++ b/dist/amp/skills/refactor-deepen/SKILL.md @@ -83,12 +83,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -149,11 +149,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -210,7 +211,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -310,7 +311,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/dist/amp/skills/refactor-deepen/references/interface-design.md b/dist/amp/skills/refactor-deepen/references/interface-design.md index ca6b79df1..401ffced5 100644 --- a/dist/amp/skills/refactor-deepen/references/interface-design.md +++ b/dist/amp/skills/refactor-deepen/references/interface-design.md @@ -1,6 +1,6 @@ # Interface Design — Parallel Sub-Agent Pattern -The INTERFACE-DESIGN phase of `/refactor-deepen` proposes the public surface +The Interface Design activity of `/refactor-deepen` proposes the public surface of a deepened module by sampling three independent design attempts and presenting all three to the user. Variety must come from sampling, not from manufactured opposition. @@ -31,10 +31,8 @@ optimizes for minimalism, Agent 2 for flexibility, Agent 3 for the common-caller path. That choice is reasonable when the agents are domain-agnostic and the orchestrator wants guaranteed surface variety. -Loaf rejects that choice. The decision is captured in -[SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md), -specifically in the Rabbit Holes and No-Gos sections (lines 96 and 107). The -short version: priming manufactures diversity rather than letting it emerge, +Loaf rejects that choice. The active rule is to use identical briefs: priming +manufactures diversity rather than letting it emerge, and manufactured diversity is dishonest signal. If the three designs do converge, the response is more agents or rerun — not priming. See [Convergence Fallback](#convergence-fallback) below. @@ -71,7 +69,7 @@ Three reasons, in order of importance: 2. **No dominant lens upfront.** Picking which constraint each agent optimizes for is itself a design decision. Doing it pre-grilling biases - the entire phase toward whatever lens the orchestrator happened to + the entire activity toward whatever lens the orchestrator happened to pick. Loaf's grilling protocol is supposed to surface tradeoffs from the codebase and the user, not from the orchestrator's pre-commitments. @@ -91,7 +89,7 @@ Justification: researcher contract: "Return findings as structured reports: summary, options (ranked with trade-offs), evidence sources, and a recommendation." See [content/agents/researcher.md](../../../agents/researcher.md). -- Read-only access matches the phase's purpose. The INTERFACE-DESIGN phase +- Read-only access matches the activity's purpose. Interface Design proposes designs; it does not implement them. Granting write access invites scope creep into "let me just sketch the implementation" and pollutes the parallel sampling. @@ -102,14 +100,14 @@ Justification: ### When `implementer` Could Be an Alternative -If the design phase needs to write probe code — a quick spike to verify +If the design activity needs to write probe code — a quick spike to verify that a proposed interface compiles against the existing call sites, for example — the `implementer` profile becomes viable. See [content/agents/implementer.md](../../../agents/implementer.md). The default remains `researcher` because: -- Probe code at this phase is rarely necessary; the deepening review +- Probe code during this activity is rarely necessary; the deepening review catches most fatal interface mistakes before code is written. - Three implementers writing probe code in parallel risks three divergent partial implementations of the same module — a merge problem the user @@ -162,7 +160,7 @@ Inside the grilling loop, after dependency classification, only when: If the interface is obvious from the dependency category and the call sites — for example, a thin adapter over a true-external dependency — -skip the parallel phase. A single proposed interface is enough. +skip parallel exploration. A single proposed interface is enough. ## Convergence Fallback @@ -172,7 +170,7 @@ implementation strategy, same tradeoffs. Two cases: 1. **Convergence is real.** The problem has a single best answer. Accept the convergence as a genuine finding and proceed to the PLAN with that single design. Note in the PLAN's "rejected alternatives" section that - the parallel phase produced no meaningful variation. + parallel exploration produced no meaningful variation. 2. **Convergence feels accidental.** The designs are suspiciously similar, the user senses a missed branch, or the briefing was so @@ -226,7 +224,7 @@ escalates on its own. ## Cost Note -A single invocation of the parallel phase is approximately **3 × +A single invocation of parallel exploration is approximately **3 × deep-exploration cost** in tokens — three sub-agents each running a full design pass against the same context. With more-agents escalation, the cost scales linearly (4 agents = ~4 ×, 5 agents = ~5 ×). @@ -235,10 +233,10 @@ This pattern is **opt-in inside the grilling loop**. It is not auto-triggered on every `/refactor-deepen` invocation. The 3-agent default is the cost ceiling for the default settings — the skill does not scale agent count silently. If a candidate's interface is obvious, skip the -phase entirely and propose a single design. +activity entirely and propose a single design. The cost is an explicit tradeoff the user accepts when they enter the -INTERFACE-DESIGN phase for a non-obvious interface. The skill should +Interface Design activity for a non-obvious interface. The skill should surface the cost briefly before spawning: > Spawning 3 design agents in parallel (~3 × token cost). Proceed? @@ -265,7 +263,7 @@ After the three sub-agents return: | Don't | Do Instead | |-------|------------| | Prime agents with opposing constraints by default | Use identical briefs; let sampling produce variety | -| Auto-trigger the parallel phase on every invocation | Invoke only when interface is non-obvious | +| Auto-trigger parallel exploration on every invocation | Invoke only when interface is non-obvious | | Use `implementer` profile for design sub-agents | Use `researcher`; switch to `implementer` only on explicit user request | | Add a "lens" to the brief silently | Surface the tradeoff to the user before priming | | Pre-rank the three designs in the output | Present in arbitrary order, let the user pick | @@ -283,6 +281,3 @@ After the three sub-agents return: agent profile for design sub-agents - [content/agents/implementer.md](../../../agents/implementer.md) — Alternative profile when probe code is needed -- [SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md) - — The shape decision (lines 64, 96, 107, 117) that established the - identical-brief default diff --git a/dist/amp/skills/refactor-deepen/templates/plan.md b/dist/amp/skills/refactor-deepen/templates/plan.md index 54a591e61..f564229a3 100644 --- a/dist/amp/skills/refactor-deepen/templates/plan.md +++ b/dist/amp/skills/refactor-deepen/templates/plan.md @@ -27,7 +27,7 @@ write a new file rather than updating an existing one. |-------|----------|-------| | `title` | Yes | One-line description of the deepening, not the candidate name | | `created` | Yes | ISO 8601 UTC, e.g. `2026-05-02T01:30:00Z` (must match the filename timestamp) | -| `status` | Yes | `drafting` on first write — lifecycle states are deferred to a follow-up spec | +| `status` | Yes | `drafting` on first write; this template does not define additional lifecycle states | | `spec` | Yes | `SPEC-NNN` if the plan is scoped under a spec; `null` otherwise (do not omit the key) | | `related` | No | List of related artifact IDs (`ADR-*`, `SPEC-*`, idea filenames, other plan filenames) | @@ -36,8 +36,7 @@ identity, mirroring councils and ideas. ## Required Sections -The five sections below are the *minimal shape* defined in SPEC-034. Order is -load-bearing: each section assumes the previous one is settled. Do not reorder. +The five sections below are the *minimal shape* for a PLAN. Order is load-bearing: each section assumes the previous one is settled. Do not reorder. 1. **Candidate** — what's being considered for deepening. Name the **module** verbatim (use the canonical glossary term — run `loaf kb glossary check` @@ -111,14 +110,12 @@ proportional to actual usage, matching how `.agents/specs/` behaves. ## Linear-Native Mode: Fail Fast -PLAN files are **local-only storage**. Per SPEC-034 line 81, write commands -must fail fast in Linear-native mode rather than silently degrade. The -consuming skill (`/refactor-deepen`) is responsible for: +PLAN files are **local-only storage**. Write commands must fail fast in Linear-native mode rather than silently degrade. The consuming skill (`/refactor-deepen`) is responsible for: 1. Reading `.agents/loaf.json` and checking `integrations.linear.enabled`. 2. If true: aborting before `mkdir -p .agents/plans` and before any write, with the verbatim error - `"Linear-native plan storage pending artifact-taxonomy spec — local mode only for now."` + `"Linear-native plan storage unavailable — continuing with a read-only report."` 3. If false: proceeding with the write as documented above. This template intentionally does **not** wrap the write in a diff --git a/dist/amp/skills/research/SKILL.md b/dist/amp/skills/research/SKILL.md index 58600b154..1eff44a20 100644 --- a/dist/amp/skills/research/SKILL.md +++ b/dist/amp/skills/research/SKILL.md @@ -144,3 +144,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/amp/skills/shape/SKILL.md b/dist/amp/skills/shape/SKILL.md index 1020b4bbb..56e2456b0 100644 --- a/dist/amp/skills/shape/SKILL.md +++ b/dist/amp/skills/shape/SKILL.md @@ -164,3 +164,7 @@ Offer to push the branch and open a draft PR, using [the PR template](templates/ | Decomposition | [references/decomposition.md](references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/amp/skills/shape/references/cli-boundary.md b/dist/amp/skills/shape/references/cli-boundary.md index efb3cc1b5..7f5816b03 100644 --- a/dist/amp/skills/shape/references/cli-boundary.md +++ b/dist/amp/skills/shape/references/cli-boundary.md @@ -13,7 +13,7 @@ Folder resolution: an explicit `[folder]` argument always wins; otherwise the cu Output splits into two tiers: - **Violations** — always fail (exit code 2), regardless of flags: status-like frontmatter keys (`readiness`, `status`, `state`) or values matching the canonical change-state vocabulary; frontmatter not opening the file at byte one; malformed `YYYYMMDD-slug` folder naming; identity mismatch between `change:`/`created:` and the folder name; missing Product Contract sections (Problem, Hypothesis, Scope, Observable Workflow, Rabbit Holes and No-Gos). -- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A shaping-stage Change with open gaps is valid; the report just says what's still missing. +- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A Change with open gaps is incomplete and non-executable; the report just says what's still missing. `--require-executable` turns structural executability into a gate (exit code 1 if not structurally executable); it does not prove implementation completion. This is implement's preflight and CI's non-draft-PR check, not something shape itself passes during shaping. diff --git a/dist/amp/skills/shape/references/decomposition.md b/dist/amp/skills/shape/references/decomposition.md index edf38530b..5ffefbe74 100644 --- a/dist/amp/skills/shape/references/decomposition.md +++ b/dist/amp/skills/shape/references/decomposition.md @@ -4,7 +4,7 @@ Shaping step absorbed from the retired breakdown skill: dependency awareness, gr ## What Survives -- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into phases. Are you splitting just to have more units? If yes, merge back. +- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into smaller coherent units. Are you splitting just to have more units? If yes, merge back. - **Right-sizing rules** — one agent type per unit (completable by a single implementer), one concern per unit (one layer, service, or component), context-appropriate (fits in model context with room for exploration), not over-fragmented (don't split what naturally belongs together). - **Per-unit verification discipline** — every unit includes its own observable done condition. Never a separate "verify" unit; keep tests with the code they test. - **Own the decisions** — decide granularity and unit boundaries autonomously. Ask the user only when two orderings are genuinely equally valid with different trade-offs; otherwise decide and move on. diff --git a/dist/codex/skills/architecture/SKILL.md b/dist/codex/skills/architecture/SKILL.md index 65100921e..b21c3f00e 100644 --- a/dist/codex/skills/architecture/SKILL.md +++ b/dist/codex/skills/architecture/SKILL.md @@ -43,7 +43,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/dist/codex/skills/bootstrap/SKILL.md b/dist/codex/skills/bootstrap/SKILL.md index 2898e5bfc..f31c58d4c 100644 --- a/dist/codex/skills/bootstrap/SKILL.md +++ b/dist/codex/skills/bootstrap/SKILL.md @@ -218,7 +218,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -227,14 +227,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -244,9 +244,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/dist/codex/skills/bootstrap/references/interview-guide.md b/dist/codex/skills/bootstrap/references/interview-guide.md index ad67e1947..3313798f0 100644 --- a/dist/codex/skills/bootstrap/references/interview-guide.md +++ b/dist/codex/skills/bootstrap/references/interview-guide.md @@ -5,10 +5,10 @@ A structured interview framework for helping builders go from a vague idea to a ## Contents - How This Guide Works - Framework Foundations -- Phase 1: Excavation (The Spark) -- Phase 2: Sharpening (The Shape) -- Phase 3: Grounding (The Architecture) -- Phase 4: Synthesis (The Documents) +- Excavation (The Spark) +- Sharpening (The Shape) +- Grounding (The Architecture) +- Synthesis (The Documents) - Adapting Interview Depth - Anti-Patterns - Transitioning to Document Drafting @@ -17,16 +17,16 @@ A structured interview framework for helping builders go from a vague idea to a This is a **builder interview**, not a user research interview. The interviewer (the agent) is helping the builder crystallize their own thinking -- not extracting requirements from a stakeholder. The builder has context, intuition, and taste that need to be surfaced, challenged, and structured. -The interview flows through four phases, each producing progressively sharper artifacts: +The interview flows through four sections, each producing progressively sharper artifacts: -| Phase | Focus | Primary Output | Frameworks | +| Section | Focus | Primary Output | Frameworks | |-------|-------|----------------|------------| -| 1. Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | -| 2. Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | -| 3. Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | -| 4. Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | +| Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | +| Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | +| Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | +| Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | -Phases are not rigid walls. A strong answer in Phase 1 might skip half of Phase 2. A weak answer in Phase 2 might loop back to Phase 1. Follow the energy. +Sections are not rigid walls. A strong answer in Excavation might skip half of Sharpening. A weak answer in Sharpening might loop back to Excavation. Follow the energy. --- @@ -80,7 +80,7 @@ What each framework contributes and what to skip. **What to skip:** Customer interview logistics, meeting scheduling advice. The Mom Test is about question quality, not interview operations. -**Connection to documents:** Informs the quality of every answer in every phase. The Mom Test isn't a phase -- it's a lens applied to ALL questioning. It keeps the interview honest. +**Connection to documents:** Informs the quality of every answer in every section. The Mom Test isn't a section -- it's a lens applied to ALL questioning. It keeps the interview honest. ### Design Sprint - Understand Phase (Google Ventures) @@ -120,7 +120,7 @@ What each framework contributes and what to skip. --- -## Phase 1: Excavation (The Spark) +## Excavation (The Spark) **Goal:** Understand what exists, why it matters, and whether the problem is real. @@ -157,9 +157,9 @@ The builder's own experience with the problem is the richest source of insight. - "Have you seen anyone spend money or significant time on this problem?" *(Mom Test: evidence of pain)* - "Is this problem getting worse or better over time? Why?" *(Wardley: movement awareness)* -### Phase 1 Signals +### Excavation Signals -**Strong signal (move to Phase 2):** Builder can describe a specific person with a specific problem and knows what they do about it today. +**Strong signal (move to Sharpening):** Builder can describe a specific person with a specific problem and knows what they do about it today. **Weak signal (dig deeper):** Builder describes a category ("developers need better tools") without specifics. Ask for a story: "Tell me about a specific moment when this problem was most painful." @@ -167,13 +167,13 @@ The builder's own experience with the problem is the richest source of insight. --- -## Phase 2: Sharpening (The Shape) +## Sharpening (The Shape) **Goal:** Define who this is for, what it does, and -- critically -- what it does NOT do. Set complexity and boundaries. -**Mood:** Constructive pressure. Phase 1 was expansive; Phase 2 is reductive. The builder will want to include everything. Your job is to help them cut. +**Mood:** Constructive pressure. Excavation was expansive; Sharpening is reductive. The builder will want to include everything. Your job is to help them cut. -**Duration:** This is typically the longest phase. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. +**Duration:** This is typically the longest section. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. ### Must-Ask Questions @@ -210,17 +210,17 @@ Surface the riskiest assumptions. "Will users actually switch from their current - "How might we make [the hardest part] effortless?" *(Design Sprint: HMW)* - "What would definitely make this fail?" *(First Principles: inversion)* -### Phase 2 Signals +### Sharpening Signals -**Strong signal (move to Phase 3):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. +**Strong signal (move to Grounding):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. **Weak signal (iterate):** Builder keeps expanding scope. "It should also..." is a signal to tighten. Ask: "If you could only do ONE thing, what would it be?" -**Red flag (loop back to Phase 1):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" +**Red flag (loop back to Excavation):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" --- -## Phase 3: Grounding (The Architecture) +## Grounding (The Architecture) **Goal:** Establish technical direction, identify what to build vs. buy, and surface hidden complexity. @@ -257,19 +257,19 @@ These become the rabbit holes in the spec. The builder often knows where the dra - "If you had to ship something in one week, what would you cut?" *(Shape Up: scope pressure test)* - "Are there regulatory, legal, or compliance considerations?" *(Often forgotten at 0-to-1)* -### Phase 3 Signals +### Grounding Signals -**Strong signal (move to Phase 4):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. +**Strong signal (move to Synthesis):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. **Weak signal (iterate):** Builder wants to build everything from scratch. Challenge: "What's the thing ONLY YOU can build? Build that. Use existing solutions for the rest." -**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Phase 3 and note that ARCHITECTURE.md will be populated later when technical decisions are made. +**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Grounding and note that ARCHITECTURE.md will be populated later when technical decisions are made. --- -## Phase 4: Synthesis (The Documents) +## Synthesis (The Documents) -**Goal:** Transform interview insights into draft documents. This is NOT a phase of the interview -- it's the transition from interviewing to drafting. +**Goal:** Transform interview insights into draft documents. This is NOT an interview section -- it's the transition from interviewing to drafting. **Mood:** Collaborative, iterative. The agent drafts, the builder reacts and refines. @@ -319,11 +319,11 @@ Allow the builder to approve all remaining sections at once if they're satisfied ## Adapting Interview Depth -The interview adapts to three contexts, per SPEC-013's mode detection: +The interview adapts to three contexts based on the detected project mode: ### Greenfield + Empty (Full Interview) -Run all four phases in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all phases. This is where the interview guide earns its keep. +Run all four sections in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all sections. This is where the interview guide earns its keep. **Key adaptation:** Be patient. The builder may circle back, contradict themselves, or get stuck. That's normal. Let them think out loud. Silence after a question is productive, not awkward. @@ -332,9 +332,9 @@ Run all four phases in full. The builder has minimal clarity and needs the most Read and analyze the brief first. Then run a compressed interview that: - Confirms understanding ("Here's what I extracted -- is this right?") - Challenges assumptions ("Your brief says X, but have you considered Y?") -- Fills gaps (which phases have missing information?) +- Fills gaps (which sections have missing information?) -Expect 8-12 questions total, concentrated in whichever phases the brief is weakest. +Expect 8-12 questions total, concentrated in whichever sections the brief is weakest. **Key adaptation:** Don't re-ask what the brief already answers well. Quote the brief back and ask "Is this still accurate?" to confirm, then move to gaps. @@ -345,7 +345,7 @@ The project exists. Code exists. Docs may exist. The interview focuses on: - What the builder wants to CHANGE (current pain, technical debt, strategic shifts) - What conventions and preferences exist but aren't documented -Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered by the existing codebase. +Expect 6-10 questions total, mostly in Excavation and Sharpening. Grounding is largely answered by the existing codebase. **Key adaptation:** Show the builder what you learned from their code. "I see a Python/FastAPI project with PostgreSQL and Docker. The test suite uses pytest. Is that the intended stack going forward?" Let the codebase speak first, then fill gaps. @@ -361,13 +361,13 @@ Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered b **The Therapist.** "And how does that make you feel about your product?" No. This is a builder interview, not a feelings exploration. Emotions matter (JTBD switching forces), but ask about user emotions, not builder emotions. -**Premature Architecture.** Jumping to "What database should we use?" in Phase 1. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. +**Premature Architecture.** Jumping to "What database should we use?" during Excavation. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. **The Echo Chamber.** Reflecting back everything the builder says without challenging anything. The Mom Test exists because people are too polite. Be constructive, not agreeable. "That's a big scope. Are you sure you need ALL of that for v1?" **Solution-First Questioning.** "What features should it have?" is the wrong question. "What job does it do for the user?" is the right one. Features are an output of the interview, not an input. -**Asking for Permission to Proceed.** Don't ask "Should we move to the next phase?" Just move when the signals are strong. If the builder has more to say, they'll say it. +**Asking for Permission to Proceed.** Don't ask "Should we move to the next section?" Just move when the signals are strong. If the builder has more to say, they'll say it. **Over-Indexing on Frameworks.** Don't say "Let's do a JTBD analysis" or "Let me apply Wardley Mapping here." The frameworks are lenses for the interviewer, not vocabulary for the builder. Just ask good questions. @@ -413,12 +413,12 @@ The bootstrap interview creates the foundation. Other skills deepen specific are ## Framework Attribution -| Framework | Primary Contribution | Phase(s) | +| Framework | Primary Contribution | Section(s) | |-----------|---------------------|----------| -| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | 2, 3 | -| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | 1, 2 | -| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | 1, 2 | -| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All phases | -| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | 2, 3 | -| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | 3 | -| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | 1, 3 | +| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | Sharpening, Grounding | +| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | Excavation, Sharpening | +| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | Excavation, Sharpening | +| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All sections | +| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | Sharpening, Grounding | +| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | Grounding | +| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | Excavation, Grounding | diff --git a/dist/codex/skills/breakdown/SKILL.md b/dist/codex/skills/breakdown/SKILL.md index 94b1f3a4d..90b40fc52 100644 --- a/dist/codex/skills/breakdown/SKILL.md +++ b/dist/codex/skills/breakdown/SKILL.md @@ -89,7 +89,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/dist/codex/skills/foundations/SKILL.md b/dist/codex/skills/foundations/SKILL.md index 1e7d3cbcc..4c0d3bdbd 100644 --- a/dist/codex/skills/foundations/SKILL.md +++ b/dist/codex/skills/foundations/SKILL.md @@ -114,6 +114,22 @@ Engineering foundations for consistent, high-quality code. | Constants | `UPPER_SNAKE` | `UPPER_SNAKE` | | Tests | `test___` | `describe/it` blocks | +### Artifact Names Never Cite Their Work Unit + +Name an artifact for what it is, never for the work unit that produced it. The directory or Change that contains it already records that provenance, so repeating it in the filename inverts the reference and rots the moment the work closes: a work unit points at its artifacts, artifacts never point back. + +| Instead of | Write | +|------------|-------| +| `u8-claude-smoke.mjs` | `smoke-claude-code-startup.mjs` | +| `report-spec-053-taxonomy-signoff.md` | `taxonomy-signoff.md` | +| `TASK-074-sidecar-audit-report.md` | `sidecar-audit.md` | + +Provenance belongs in a front-matter field such as `source:`, where it can be read and updated, not in a name that has to be renamed to stay true. + +Two look-alikes are correct and stay. A **version** is identity, not reference: `claude-code-2.1.218-plugin-startup-smoke.json`. A **timestamp** records when, not which work unit: `20260620-214448-skills-audit.md`. And a numbered record living in the directory that owns it *is* that entity, so `.agents/specs/SPEC-042-slug.md` and `docs/decisions/ADR-007-slug.md` are its own name rather than a citation. + +`loaf check --hook artifact-names` enforces this at commit time over tracked artifacts, grandfathering anything already `final` or `archived`. + ## Test Patterns Scenario-based fixture naming: diff --git a/dist/codex/skills/git-workflow/references/commits.md b/dist/codex/skills/git-workflow/references/commits.md index 5ed2ba9e1..d6a48ab9b 100644 --- a/dist/codex/skills/git-workflow/references/commits.md +++ b/dist/codex/skills/git-workflow/references/commits.md @@ -185,7 +185,7 @@ Internal terms that have no meaning outside the team's working context: - Spec IDs and task IDs (`SPEC-024`, `TASK-042`) - Session, sprint, or branch references - Internal terminology from skills/docs that isn't part of the user's mental model — e.g. `Q1`/`Q2`/`Q3` question numbers from a Triage Gate, internal gate-logic notation like `(Q1 OR Q2) AND Q3`, hook IDs that aren't user-facing -- "How the work got done" framing — interview steps, breakdown phases, review gates +- "How the work got done" framing — interview steps, breakdown steps, review gates ### Keep @@ -252,7 +252,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE] Four hooks automatically enforce the conventions documented in this file: -| Hook | Phase | Behavior | +| Hook | Timing | Behavior | |------|-------|----------| | `github-account` | Pre-tool (Bash) | Force-switch: switches the active `gh` account to the configured one before `gh` commands run (passes with a warning), exempting `gh auth` administration, and blocks only when the switch fails. It writes the shared global account pointer on every mismatched `gh` call -- read-only ones included -- so concurrent sessions on different identities collide on that pointer more often. | | `workflow-pre-pr` | Pre-tool (Bash) | Advisory: reminds about CHANGELOG [Unreleased] entries and PR format. Non-blocking. | @@ -269,26 +269,14 @@ BREAKING CHANGE: Description of breaking change. ### Pre-Release Versions -When developing toward a major version, use pre-release suffixes to mark development milestones: - -``` -2.0.0-dev.0 → dev.1 → dev.2 → ... → 2.0.0 - ↑ ↑ ↑ ↑ - start dev milestone milestone stable release -``` - | Suffix | Meaning | When to use | |--------|---------|-------------| -| `-dev.N` | Development milestone | Active development toward a target version | | `-alpha.N` | Alpha pre-release | Feature-complete but untested broadly | | `-beta.N` | Beta pre-release | Testing with wider audience | | `-rc.N` | Release candidate | Final validation before stable | **Convention:** -- Set the target version with `-dev.0` when starting a major effort (e.g. `2.0.0-dev.0`) -- Bump the dev counter (`-dev.N` → `-dev.N+1`) when a meaningful batch of landed work is ready to publish — a completed spec, a related feature group, or a release train -- Don't bump for every commit — that's what git history is for -- Strip the suffix (`-dev.N` → `2.0.0`) when all planned work is complete +- Use standard SemVer pre-release identifiers (`alpha`, `beta`, or `rc`) when publishing pre-release versions. - `loaf release` handles all bump types: `prerelease`, `release`, `major`, `minor`, `patch` -**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects with multi-milestone development cycles. +**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects publishing staged pre-releases before stable releases. diff --git a/dist/codex/skills/handoff/SKILL.md b/dist/codex/skills/handoff/SKILL.md index c72f2382c..671e52e04 100644 --- a/dist/codex/skills/handoff/SKILL.md +++ b/dist/codex/skills/handoff/SKILL.md @@ -120,3 +120,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/codex/skills/housekeeping/SKILL.md b/dist/codex/skills/housekeeping/SKILL.md index de898abce..71790eee2 100644 --- a/dist/codex/skills/housekeeping/SKILL.md +++ b/dist/codex/skills/housekeeping/SKILL.md @@ -138,3 +138,7 @@ After housekeeping, suggest `/reflect` if the session produced key decisions or | Report Template | [templates/report.md](templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/codex/skills/implement/SKILL.md b/dist/codex/skills/implement/SKILL.md index 0da90f143..eb6164c98 100644 --- a/dist/codex/skills/implement/SKILL.md +++ b/dist/codex/skills/implement/SKILL.md @@ -91,9 +91,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -345,7 +345,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/dist/codex/skills/implement/references/batch-orchestration.md b/dist/codex/skills/implement/references/batch-orchestration.md index 7b69603f5..69fe524c5 100644 --- a/dist/codex/skills/implement/references/batch-orchestration.md +++ b/dist/codex/skills/implement/references/batch-orchestration.md @@ -2,63 +2,63 @@ ## Contents - Orchestration Options -- Batch Resolution and Wave Planning +- Batch Resolution and Dependency-Ready Scheduling - Option Handling - Batch Execution Model - Blocked-State Recovery -Detailed reference for running specs, task ranges, or task lists with dependency waves. +Detailed reference for running specs, task ranges, or task lists with dependency-ready scheduling. ## Orchestration Options | Option | Behavior | |--------|----------| -| `--dry-run` | Show dependency/wave execution plan, do not run agents | -| `--parallel` | Run tasks in the same wave concurrently (max 3 at once) | -| `--continue` | Resume a blocked orchestration from the recorded task/wave | +| `--dry-run` | Show dependency-ready execution plan, do not run agents | +| `--parallel` | Run tasks in the same dependency-ready group concurrently (max 3 at once) | +| `--continue` | Resume a blocked orchestration from the recorded task/group | | `--skip TASK-XXX` | Mark one blocked task as skipped and continue | | `--abort` | Mark orchestration as aborted and stop remaining work | -## Batch Resolution and Wave Planning +## Batch Resolution and Dependency-Ready Scheduling For `SPEC-XXX`, `TASK-XXX..YYY`, and `TASK-XXX,YYY,ZZZ`: 1. Resolve selected tasks and validate each task file exists. 2. Extract `depends_on` from each task and build a dependency graph. -3. Group tasks into dependency waves: - - Wave 1: tasks with no unresolved dependencies - - Wave N: tasks whose dependencies are completed in earlier waves -4. If `--parallel` is set, allow parallel execution only within a wave and only for non-conflicting tasks. -5. Present execution plan (tasks, waves, mode, total count) and ask for confirmation unless `--dry-run`. -6. Track progress in the journal and in task statuses: log wave boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. +3. Group tasks into dependency-ready rounds: + - First round: tasks with no unresolved dependencies + - Each subsequent round: tasks whose dependencies are completed in earlier rounds +4. If `--parallel` is set, allow parallel execution only within a dependency-ready round and only for non-conflicting tasks. +5. Present execution plan (tasks, dependency-ready rounds, mode, total count) and ask for confirmation unless `--dry-run`. +6. Track progress in the journal and in task statuses: log round boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. ## Option Handling (`--continue`, `--skip`, `--abort`) 1. Recover batch progress from the journal: `loaf journal recent --since-last-wrap` (or `loaf journal context`) plus `loaf task list --json` to see which tasks are still open. -2. If `--continue`: resume from the last logged wave and task. -3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same wave. +2. If `--continue`: resume from the last logged dependency-ready round and task. +3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same dependency-ready round. 4. If `--abort`: log `block(orchestration): aborted`, print a summary, and stop. 5. If no in-flight batch is evident from the journal, report that and ask for fresh selection input. ## Batch Execution Model -When input resolves to multiple tasks, run a wave-based loop: +When input resolves to multiple tasks, run a dependency-ready round loop: 1. Set orchestration mode (`sequential` by default, `parallel` only with `--parallel`). -2. For each wave: - - Log the wave start with `loaf journal log` +2. For each dependency-ready round: + - Log the round start with `loaf journal log` - Run each task (sequentially, or concurrently within safety limits) - For each task: set `in_progress` -> spawn agent -> run task verification -> mark `done`/`failed` via `loaf task update` 3. If any task fails verification, stop immediately and log `block(orchestration): failed `. -4. Consider a wave complete only when all its tasks are `done` or skipped. -5. Continue until all waves complete, then log a closing entry summarizing the batch. +4. Consider a round complete only when all its tasks are `done` or skipped. +5. Continue until all rounds complete, then log a closing entry summarizing the batch. ## Blocked-State Recovery When blocked, always print: - Failed task ID and title -- Wave number and current progress +- Dependency-ready round and current progress - Failure reason + key error output - Recovery commands: @@ -71,5 +71,5 @@ When blocked, always print: Use these semantics: - `--continue`: after fixes are applied, retry from the blocked task -- `--skip`: skip only the specified task and continue remaining tasks in the current wave +- `--skip`: skip only the specified task and continue remaining tasks in the current dependency-ready round - `--abort`: finalize the orchestration as aborted with no further execution diff --git a/dist/codex/skills/implement/references/branch-and-completion.md b/dist/codex/skills/implement/references/branch-and-completion.md index 0f715e4c5..250c8cdca 100644 --- a/dist/codex/skills/implement/references/branch-and-completion.md +++ b/dist/codex/skills/implement/references/branch-and-completion.md @@ -195,7 +195,7 @@ never implement through open `blockedBy`. **Print the current date and timestamp when:** - Waiting for user input or decision -- Completing a phase of work +- Completing a coherent unit of work - Encountering a blocker - Wrapping up the conversation diff --git a/dist/codex/skills/loaf-reference/SKILL.md b/dist/codex/skills/loaf-reference/SKILL.md index 770deae54..526ddcbeb 100644 --- a/dist/codex/skills/loaf-reference/SKILL.md +++ b/dist/codex/skills/loaf-reference/SKILL.md @@ -46,7 +46,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic. diff --git a/dist/codex/skills/loaf-reference/references/command-routing.md b/dist/codex/skills/loaf-reference/references/command-routing.md index 14a8ded99..de4f16c02 100644 --- a/dist/codex/skills/loaf-reference/references/command-routing.md +++ b/dist/codex/skills/loaf-reference/references/command-routing.md @@ -6,8 +6,9 @@ Which command a task needs. For exact flags, run `loaf --help`. | Intent | Route | |--------|-------| -| Shape new work | `loaf change init `, then `loaf change check` | -| Start working on a task | the implement workflow (/implement); `loaf task`/`loaf spec` stay transitional until the conversion pass — see the TRANSITIONAL note in AGENTS.md | +| Shape new bounded work | `loaf change init `, then `loaf change check` | +| Start implementing new bounded work | the implement workflow (/implement) after shaping and validating its Change | +| Continue an existing task or spec record | `loaf task` and `loaf spec` remain supported for existing records | | Continue after a restart | `loaf journal context` | | Skills or content changed | `loaf build && loaf install --to ` | | See what is in progress | `loaf task list --active` | diff --git a/dist/codex/skills/orchestration/SKILL.md b/dist/codex/skills/orchestration/SKILL.md index c3df20106..9bf4a84ca 100644 --- a/dist/codex/skills/orchestration/SKILL.md +++ b/dist/codex/skills/orchestration/SKILL.md @@ -18,7 +18,7 @@ version: 2.0.0-alpha.13 - Philosophy - Configuration - Artifact Locations -- Three-Phase Workflow +- Workflow by Lifecycle Comprehensive patterns for orchestration: coordinating multi-agent work, keeping the project journal current, running councils, delegating to specialized agents, and integrating with Linear. @@ -130,7 +130,7 @@ This skill uses paths from `.agents/loaf.json`: **Rule:** Agents write artifacts to disk, orchestrator reasons over artifacts, users retrieve from disk. -## Three-Phase Workflow +## Workflow by Lifecycle ### BEFORE (Planning) - Create/check external issue (Linear, GitHub) diff --git a/dist/codex/skills/orchestration/references/context-management.md b/dist/codex/skills/orchestration/references/context-management.md index 4a577309f..fd07ec254 100644 --- a/dist/codex/skills/orchestration/references/context-management.md +++ b/dist/codex/skills/orchestration/references/context-management.md @@ -19,7 +19,7 @@ Patterns for keeping long work resumable while using the project journal as exte Compaction is normal in long workflows. Design work that spans many exchanges so important state is already outside chat context. 1. **The journal is external memory.** Record decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. **Artifacts carry detail.** Changes, transitional tasks, reports, ADRs, and commits hold rich detail; journal entries point to them. +2. **Artifacts carry detail.** Changes, task-board records, reports, ADRs, and commits hold rich detail; journal entries point to them. 3. **Delegated work absorbs exploration.** Use delegated agents for broad investigation and return concise findings to the main context. 4. **`wrap` captures synthesis.** When meaningful work holds intentions or abandoned paths worth saving, write an optional `wrap` journal entry. @@ -36,7 +36,7 @@ Compaction is normal in long workflows. Design work that spans many exchanges so | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent branch entries after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records retained during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each returned layer includes `source_available`, `available_count`, `shown_count`, `truncated`, and `expand_command`; paginated layers also include a cursor. Treat `source_available: false` as an explicit unavailable source, never as “nothing is active.” If Change discovery is unavailable, `active-changes` and `active-lineage` are unavailable and the digest carries a diagnostic. @@ -60,7 +60,7 @@ Use `/clear` when starting a completely new task, after the previous task is com PreCompact: 1. Flush unrecorded decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. Reference Changes, transitional tasks, reports, commits, and files by stable ID or path. +2. Reference Changes, task-board records, reports, commits, and files by stable ID or path. 3. On an exact target mode with supported PreCompact delivery, let the hook nudge the flush; otherwise flush manually before compacting. PostCompact: diff --git a/dist/codex/skills/orchestration/references/linear.md b/dist/codex/skills/orchestration/references/linear.md index 22d55b3ce..26ba14472 100644 --- a/dist/codex/skills/orchestration/references/linear.md +++ b/dist/codex/skills/orchestration/references/linear.md @@ -103,7 +103,7 @@ In Linear-native mode (`integrations.linear.enabled: true`), each spec produces one parent **rollup issue** and N sub-issues under it. ``` -[SPEC-024] Agent framework alignment ← parent, label: `spec` +Agent framework alignment ← parent, label: `change` ├── Split reviewer profile into reviewer/auditor ← sub-issue, label: type/refactor ├── Harden MCP fallback path ← sub-issue, label: type/feature └── Migrate legacy task references ← sub-issue, label: type/refactor @@ -127,8 +127,8 @@ researcher). Consolidate historical profile variants and add tool-boundary tests so profiles can't drift without a test failing. ## Context -See `.agents/specs/SPEC-024-agent-framework-alignment.md` for full text, -council references, rabbit holes, and strategic tensions. +See the canonical change file in the repository for full text, council +references, rabbit holes, and strategic tensions. ## Progress Sub-issues track execution. @@ -213,7 +213,7 @@ None currently. |-------|---------| | `Working on API` | `- [ ] API implementation` | | `Done with schema` | `- [x] Schema updated` | -| `Phase 1: Discovery` | `Discovery - COMPLETE` | +| `Discovery: IN PROGRESS` | `Discovery: COMPLETE` | | `Journal entry: ...` | *(omit entirely)* | | `Council decision: ...` | *(omit entirely)* | | `Week 1 deliverables` | `Initial deliverables` | @@ -373,6 +373,6 @@ Use `scripts/suggest-team.py "task desc"` to get suggestions. ### DON'T - Use emoji in progress lists - Reference local files (sessions, councils, plans) -- Use phase/stage/week terminology +- Use numbered development-stage terminology - Include absolute file paths - Duplicate issue titles after IDs diff --git a/dist/codex/skills/orchestration/references/local-tasks.md b/dist/codex/skills/orchestration/references/local-tasks.md index 3bc1327fb..886822a1f 100644 --- a/dist/codex/skills/orchestration/references/local-tasks.md +++ b/dist/codex/skills/orchestration/references/local-tasks.md @@ -167,7 +167,7 @@ project journal (`loaf journal recent`, `loaf journal search`). 1. Can a single specialized agent complete this? → If no, split by agent type 2. Does it touch multiple unrelated concerns? → If yes, split by concern -3. Will the agent need too much context? → If yes, split into phases +3. Will the agent need too much context? → If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? → If yes, merge back ### Agent Scope diff --git a/dist/codex/skills/orchestration/references/parallel-agents.md b/dist/codex/skills/orchestration/references/parallel-agents.md index ca2d08f5e..d060546c3 100644 --- a/dist/codex/skills/orchestration/references/parallel-agents.md +++ b/dist/codex/skills/orchestration/references/parallel-agents.md @@ -119,7 +119,7 @@ When streams complete: |---------|---------------------| | `/breakdown` | Identify parallelizable tasks during decomposition | | `/implement` | Single task, usually sequential | -| `/implement` | Runs dependency-wave orchestration, including parallel-safe tasks | +| `/implement` | Runs dependency-aware orchestration, including parallel-safe tasks | ## Conflict Resolution diff --git a/dist/codex/skills/refactor-deepen/SKILL.md b/dist/codex/skills/refactor-deepen/SKILL.md index a8803d341..e1d120b94 100644 --- a/dist/codex/skills/refactor-deepen/SKILL.md +++ b/dist/codex/skills/refactor-deepen/SKILL.md @@ -83,12 +83,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -149,11 +149,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -210,7 +211,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -310,7 +311,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/dist/codex/skills/refactor-deepen/references/interface-design.md b/dist/codex/skills/refactor-deepen/references/interface-design.md index ca6b79df1..401ffced5 100644 --- a/dist/codex/skills/refactor-deepen/references/interface-design.md +++ b/dist/codex/skills/refactor-deepen/references/interface-design.md @@ -1,6 +1,6 @@ # Interface Design — Parallel Sub-Agent Pattern -The INTERFACE-DESIGN phase of `/refactor-deepen` proposes the public surface +The Interface Design activity of `/refactor-deepen` proposes the public surface of a deepened module by sampling three independent design attempts and presenting all three to the user. Variety must come from sampling, not from manufactured opposition. @@ -31,10 +31,8 @@ optimizes for minimalism, Agent 2 for flexibility, Agent 3 for the common-caller path. That choice is reasonable when the agents are domain-agnostic and the orchestrator wants guaranteed surface variety. -Loaf rejects that choice. The decision is captured in -[SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md), -specifically in the Rabbit Holes and No-Gos sections (lines 96 and 107). The -short version: priming manufactures diversity rather than letting it emerge, +Loaf rejects that choice. The active rule is to use identical briefs: priming +manufactures diversity rather than letting it emerge, and manufactured diversity is dishonest signal. If the three designs do converge, the response is more agents or rerun — not priming. See [Convergence Fallback](#convergence-fallback) below. @@ -71,7 +69,7 @@ Three reasons, in order of importance: 2. **No dominant lens upfront.** Picking which constraint each agent optimizes for is itself a design decision. Doing it pre-grilling biases - the entire phase toward whatever lens the orchestrator happened to + the entire activity toward whatever lens the orchestrator happened to pick. Loaf's grilling protocol is supposed to surface tradeoffs from the codebase and the user, not from the orchestrator's pre-commitments. @@ -91,7 +89,7 @@ Justification: researcher contract: "Return findings as structured reports: summary, options (ranked with trade-offs), evidence sources, and a recommendation." See [content/agents/researcher.md](../../../agents/researcher.md). -- Read-only access matches the phase's purpose. The INTERFACE-DESIGN phase +- Read-only access matches the activity's purpose. Interface Design proposes designs; it does not implement them. Granting write access invites scope creep into "let me just sketch the implementation" and pollutes the parallel sampling. @@ -102,14 +100,14 @@ Justification: ### When `implementer` Could Be an Alternative -If the design phase needs to write probe code — a quick spike to verify +If the design activity needs to write probe code — a quick spike to verify that a proposed interface compiles against the existing call sites, for example — the `implementer` profile becomes viable. See [content/agents/implementer.md](../../../agents/implementer.md). The default remains `researcher` because: -- Probe code at this phase is rarely necessary; the deepening review +- Probe code during this activity is rarely necessary; the deepening review catches most fatal interface mistakes before code is written. - Three implementers writing probe code in parallel risks three divergent partial implementations of the same module — a merge problem the user @@ -162,7 +160,7 @@ Inside the grilling loop, after dependency classification, only when: If the interface is obvious from the dependency category and the call sites — for example, a thin adapter over a true-external dependency — -skip the parallel phase. A single proposed interface is enough. +skip parallel exploration. A single proposed interface is enough. ## Convergence Fallback @@ -172,7 +170,7 @@ implementation strategy, same tradeoffs. Two cases: 1. **Convergence is real.** The problem has a single best answer. Accept the convergence as a genuine finding and proceed to the PLAN with that single design. Note in the PLAN's "rejected alternatives" section that - the parallel phase produced no meaningful variation. + parallel exploration produced no meaningful variation. 2. **Convergence feels accidental.** The designs are suspiciously similar, the user senses a missed branch, or the briefing was so @@ -226,7 +224,7 @@ escalates on its own. ## Cost Note -A single invocation of the parallel phase is approximately **3 × +A single invocation of parallel exploration is approximately **3 × deep-exploration cost** in tokens — three sub-agents each running a full design pass against the same context. With more-agents escalation, the cost scales linearly (4 agents = ~4 ×, 5 agents = ~5 ×). @@ -235,10 +233,10 @@ This pattern is **opt-in inside the grilling loop**. It is not auto-triggered on every `/refactor-deepen` invocation. The 3-agent default is the cost ceiling for the default settings — the skill does not scale agent count silently. If a candidate's interface is obvious, skip the -phase entirely and propose a single design. +activity entirely and propose a single design. The cost is an explicit tradeoff the user accepts when they enter the -INTERFACE-DESIGN phase for a non-obvious interface. The skill should +Interface Design activity for a non-obvious interface. The skill should surface the cost briefly before spawning: > Spawning 3 design agents in parallel (~3 × token cost). Proceed? @@ -265,7 +263,7 @@ After the three sub-agents return: | Don't | Do Instead | |-------|------------| | Prime agents with opposing constraints by default | Use identical briefs; let sampling produce variety | -| Auto-trigger the parallel phase on every invocation | Invoke only when interface is non-obvious | +| Auto-trigger parallel exploration on every invocation | Invoke only when interface is non-obvious | | Use `implementer` profile for design sub-agents | Use `researcher`; switch to `implementer` only on explicit user request | | Add a "lens" to the brief silently | Surface the tradeoff to the user before priming | | Pre-rank the three designs in the output | Present in arbitrary order, let the user pick | @@ -283,6 +281,3 @@ After the three sub-agents return: agent profile for design sub-agents - [content/agents/implementer.md](../../../agents/implementer.md) — Alternative profile when probe code is needed -- [SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md) - — The shape decision (lines 64, 96, 107, 117) that established the - identical-brief default diff --git a/dist/codex/skills/refactor-deepen/templates/plan.md b/dist/codex/skills/refactor-deepen/templates/plan.md index 54a591e61..f564229a3 100644 --- a/dist/codex/skills/refactor-deepen/templates/plan.md +++ b/dist/codex/skills/refactor-deepen/templates/plan.md @@ -27,7 +27,7 @@ write a new file rather than updating an existing one. |-------|----------|-------| | `title` | Yes | One-line description of the deepening, not the candidate name | | `created` | Yes | ISO 8601 UTC, e.g. `2026-05-02T01:30:00Z` (must match the filename timestamp) | -| `status` | Yes | `drafting` on first write — lifecycle states are deferred to a follow-up spec | +| `status` | Yes | `drafting` on first write; this template does not define additional lifecycle states | | `spec` | Yes | `SPEC-NNN` if the plan is scoped under a spec; `null` otherwise (do not omit the key) | | `related` | No | List of related artifact IDs (`ADR-*`, `SPEC-*`, idea filenames, other plan filenames) | @@ -36,8 +36,7 @@ identity, mirroring councils and ideas. ## Required Sections -The five sections below are the *minimal shape* defined in SPEC-034. Order is -load-bearing: each section assumes the previous one is settled. Do not reorder. +The five sections below are the *minimal shape* for a PLAN. Order is load-bearing: each section assumes the previous one is settled. Do not reorder. 1. **Candidate** — what's being considered for deepening. Name the **module** verbatim (use the canonical glossary term — run `loaf kb glossary check` @@ -111,14 +110,12 @@ proportional to actual usage, matching how `.agents/specs/` behaves. ## Linear-Native Mode: Fail Fast -PLAN files are **local-only storage**. Per SPEC-034 line 81, write commands -must fail fast in Linear-native mode rather than silently degrade. The -consuming skill (`/refactor-deepen`) is responsible for: +PLAN files are **local-only storage**. Write commands must fail fast in Linear-native mode rather than silently degrade. The consuming skill (`/refactor-deepen`) is responsible for: 1. Reading `.agents/loaf.json` and checking `integrations.linear.enabled`. 2. If true: aborting before `mkdir -p .agents/plans` and before any write, with the verbatim error - `"Linear-native plan storage pending artifact-taxonomy spec — local mode only for now."` + `"Linear-native plan storage unavailable — continuing with a read-only report."` 3. If false: proceeding with the write as documented above. This template intentionally does **not** wrap the write in a diff --git a/dist/codex/skills/research/SKILL.md b/dist/codex/skills/research/SKILL.md index c8e7e1ac2..8915b8634 100644 --- a/dist/codex/skills/research/SKILL.md +++ b/dist/codex/skills/research/SKILL.md @@ -144,3 +144,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/codex/skills/shape/SKILL.md b/dist/codex/skills/shape/SKILL.md index f7915f6e1..f6da9a59f 100644 --- a/dist/codex/skills/shape/SKILL.md +++ b/dist/codex/skills/shape/SKILL.md @@ -164,3 +164,7 @@ Offer to push the branch and open a draft PR, using [the PR template](templates/ | Decomposition | [references/decomposition.md](references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/codex/skills/shape/references/cli-boundary.md b/dist/codex/skills/shape/references/cli-boundary.md index efb3cc1b5..7f5816b03 100644 --- a/dist/codex/skills/shape/references/cli-boundary.md +++ b/dist/codex/skills/shape/references/cli-boundary.md @@ -13,7 +13,7 @@ Folder resolution: an explicit `[folder]` argument always wins; otherwise the cu Output splits into two tiers: - **Violations** — always fail (exit code 2), regardless of flags: status-like frontmatter keys (`readiness`, `status`, `state`) or values matching the canonical change-state vocabulary; frontmatter not opening the file at byte one; malformed `YYYYMMDD-slug` folder naming; identity mismatch between `change:`/`created:` and the folder name; missing Product Contract sections (Problem, Hypothesis, Scope, Observable Workflow, Rabbit Holes and No-Gos). -- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A shaping-stage Change with open gaps is valid; the report just says what's still missing. +- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A Change with open gaps is incomplete and non-executable; the report just says what's still missing. `--require-executable` turns structural executability into a gate (exit code 1 if not structurally executable); it does not prove implementation completion. This is implement's preflight and CI's non-draft-PR check, not something shape itself passes during shaping. diff --git a/dist/codex/skills/shape/references/decomposition.md b/dist/codex/skills/shape/references/decomposition.md index edf38530b..5ffefbe74 100644 --- a/dist/codex/skills/shape/references/decomposition.md +++ b/dist/codex/skills/shape/references/decomposition.md @@ -4,7 +4,7 @@ Shaping step absorbed from the retired breakdown skill: dependency awareness, gr ## What Survives -- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into phases. Are you splitting just to have more units? If yes, merge back. +- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into smaller coherent units. Are you splitting just to have more units? If yes, merge back. - **Right-sizing rules** — one agent type per unit (completable by a single implementer), one concern per unit (one layer, service, or component), context-appropriate (fits in model context with room for exploration), not over-fragmented (don't split what naturally belongs together). - **Per-unit verification discipline** — every unit includes its own observable done condition. Never a separate "verify" unit; keep tests with the code they test. - **Own the decisions** — decide granularity and unit boundaries autonomously. Ask the user only when two orderings are genuinely equally valid with different trade-offs; otherwise decide and move on. diff --git a/dist/cursor/.loaf-target-manifest.json b/dist/cursor/.loaf-target-manifest.json index c1762938e..6358f0ac7 100644 --- a/dist/cursor/.loaf-target-manifest.json +++ b/dist/cursor/.loaf-target-manifest.json @@ -60,7 +60,7 @@ "kind": "hook-projection", "source_path": "hooks.json", "destination": "hooks.json", - "sha256": "286b1fa0549b3e32ba642ab9e69fdd6df1bdc310dc0ee7a2ec5948872670fafb" + "sha256": "ee62210b456405c5760a2de17676a42c09e130a27c576a1967180053b9c1047b" }, { "id": "managed-instructions", diff --git a/dist/cursor/hooks.json b/dist/cursor/hooks.json index b1b1c5ece..96daef02d 100644 --- a/dist/cursor/hooks.json +++ b/dist/cursor/hooks.json @@ -39,6 +39,14 @@ "command": "loaf check --hook ephemeral-provenance", "if": "Bash(git push:*)" }, + { + "loaf-managed": true, + "timeout": 30, + "matcher": "Bash", + "failClosed": true, + "command": "loaf check --hook artifact-names", + "if": "Bash(git commit:*)" + }, { "loaf-managed": true, "timeout": 10, diff --git a/dist/cursor/skills/architecture/SKILL.md b/dist/cursor/skills/architecture/SKILL.md index 65100921e..b21c3f00e 100644 --- a/dist/cursor/skills/architecture/SKILL.md +++ b/dist/cursor/skills/architecture/SKILL.md @@ -43,7 +43,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/dist/cursor/skills/bootstrap/SKILL.md b/dist/cursor/skills/bootstrap/SKILL.md index 7baa7ecc2..af59308f2 100644 --- a/dist/cursor/skills/bootstrap/SKILL.md +++ b/dist/cursor/skills/bootstrap/SKILL.md @@ -218,7 +218,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -227,14 +227,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -244,9 +244,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/dist/cursor/skills/bootstrap/references/interview-guide.md b/dist/cursor/skills/bootstrap/references/interview-guide.md index ad67e1947..3313798f0 100644 --- a/dist/cursor/skills/bootstrap/references/interview-guide.md +++ b/dist/cursor/skills/bootstrap/references/interview-guide.md @@ -5,10 +5,10 @@ A structured interview framework for helping builders go from a vague idea to a ## Contents - How This Guide Works - Framework Foundations -- Phase 1: Excavation (The Spark) -- Phase 2: Sharpening (The Shape) -- Phase 3: Grounding (The Architecture) -- Phase 4: Synthesis (The Documents) +- Excavation (The Spark) +- Sharpening (The Shape) +- Grounding (The Architecture) +- Synthesis (The Documents) - Adapting Interview Depth - Anti-Patterns - Transitioning to Document Drafting @@ -17,16 +17,16 @@ A structured interview framework for helping builders go from a vague idea to a This is a **builder interview**, not a user research interview. The interviewer (the agent) is helping the builder crystallize their own thinking -- not extracting requirements from a stakeholder. The builder has context, intuition, and taste that need to be surfaced, challenged, and structured. -The interview flows through four phases, each producing progressively sharper artifacts: +The interview flows through four sections, each producing progressively sharper artifacts: -| Phase | Focus | Primary Output | Frameworks | +| Section | Focus | Primary Output | Frameworks | |-------|-------|----------------|------------| -| 1. Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | -| 2. Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | -| 3. Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | -| 4. Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | +| Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | +| Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | +| Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | +| Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | -Phases are not rigid walls. A strong answer in Phase 1 might skip half of Phase 2. A weak answer in Phase 2 might loop back to Phase 1. Follow the energy. +Sections are not rigid walls. A strong answer in Excavation might skip half of Sharpening. A weak answer in Sharpening might loop back to Excavation. Follow the energy. --- @@ -80,7 +80,7 @@ What each framework contributes and what to skip. **What to skip:** Customer interview logistics, meeting scheduling advice. The Mom Test is about question quality, not interview operations. -**Connection to documents:** Informs the quality of every answer in every phase. The Mom Test isn't a phase -- it's a lens applied to ALL questioning. It keeps the interview honest. +**Connection to documents:** Informs the quality of every answer in every section. The Mom Test isn't a section -- it's a lens applied to ALL questioning. It keeps the interview honest. ### Design Sprint - Understand Phase (Google Ventures) @@ -120,7 +120,7 @@ What each framework contributes and what to skip. --- -## Phase 1: Excavation (The Spark) +## Excavation (The Spark) **Goal:** Understand what exists, why it matters, and whether the problem is real. @@ -157,9 +157,9 @@ The builder's own experience with the problem is the richest source of insight. - "Have you seen anyone spend money or significant time on this problem?" *(Mom Test: evidence of pain)* - "Is this problem getting worse or better over time? Why?" *(Wardley: movement awareness)* -### Phase 1 Signals +### Excavation Signals -**Strong signal (move to Phase 2):** Builder can describe a specific person with a specific problem and knows what they do about it today. +**Strong signal (move to Sharpening):** Builder can describe a specific person with a specific problem and knows what they do about it today. **Weak signal (dig deeper):** Builder describes a category ("developers need better tools") without specifics. Ask for a story: "Tell me about a specific moment when this problem was most painful." @@ -167,13 +167,13 @@ The builder's own experience with the problem is the richest source of insight. --- -## Phase 2: Sharpening (The Shape) +## Sharpening (The Shape) **Goal:** Define who this is for, what it does, and -- critically -- what it does NOT do. Set complexity and boundaries. -**Mood:** Constructive pressure. Phase 1 was expansive; Phase 2 is reductive. The builder will want to include everything. Your job is to help them cut. +**Mood:** Constructive pressure. Excavation was expansive; Sharpening is reductive. The builder will want to include everything. Your job is to help them cut. -**Duration:** This is typically the longest phase. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. +**Duration:** This is typically the longest section. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. ### Must-Ask Questions @@ -210,17 +210,17 @@ Surface the riskiest assumptions. "Will users actually switch from their current - "How might we make [the hardest part] effortless?" *(Design Sprint: HMW)* - "What would definitely make this fail?" *(First Principles: inversion)* -### Phase 2 Signals +### Sharpening Signals -**Strong signal (move to Phase 3):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. +**Strong signal (move to Grounding):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. **Weak signal (iterate):** Builder keeps expanding scope. "It should also..." is a signal to tighten. Ask: "If you could only do ONE thing, what would it be?" -**Red flag (loop back to Phase 1):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" +**Red flag (loop back to Excavation):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" --- -## Phase 3: Grounding (The Architecture) +## Grounding (The Architecture) **Goal:** Establish technical direction, identify what to build vs. buy, and surface hidden complexity. @@ -257,19 +257,19 @@ These become the rabbit holes in the spec. The builder often knows where the dra - "If you had to ship something in one week, what would you cut?" *(Shape Up: scope pressure test)* - "Are there regulatory, legal, or compliance considerations?" *(Often forgotten at 0-to-1)* -### Phase 3 Signals +### Grounding Signals -**Strong signal (move to Phase 4):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. +**Strong signal (move to Synthesis):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. **Weak signal (iterate):** Builder wants to build everything from scratch. Challenge: "What's the thing ONLY YOU can build? Build that. Use existing solutions for the rest." -**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Phase 3 and note that ARCHITECTURE.md will be populated later when technical decisions are made. +**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Grounding and note that ARCHITECTURE.md will be populated later when technical decisions are made. --- -## Phase 4: Synthesis (The Documents) +## Synthesis (The Documents) -**Goal:** Transform interview insights into draft documents. This is NOT a phase of the interview -- it's the transition from interviewing to drafting. +**Goal:** Transform interview insights into draft documents. This is NOT an interview section -- it's the transition from interviewing to drafting. **Mood:** Collaborative, iterative. The agent drafts, the builder reacts and refines. @@ -319,11 +319,11 @@ Allow the builder to approve all remaining sections at once if they're satisfied ## Adapting Interview Depth -The interview adapts to three contexts, per SPEC-013's mode detection: +The interview adapts to three contexts based on the detected project mode: ### Greenfield + Empty (Full Interview) -Run all four phases in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all phases. This is where the interview guide earns its keep. +Run all four sections in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all sections. This is where the interview guide earns its keep. **Key adaptation:** Be patient. The builder may circle back, contradict themselves, or get stuck. That's normal. Let them think out loud. Silence after a question is productive, not awkward. @@ -332,9 +332,9 @@ Run all four phases in full. The builder has minimal clarity and needs the most Read and analyze the brief first. Then run a compressed interview that: - Confirms understanding ("Here's what I extracted -- is this right?") - Challenges assumptions ("Your brief says X, but have you considered Y?") -- Fills gaps (which phases have missing information?) +- Fills gaps (which sections have missing information?) -Expect 8-12 questions total, concentrated in whichever phases the brief is weakest. +Expect 8-12 questions total, concentrated in whichever sections the brief is weakest. **Key adaptation:** Don't re-ask what the brief already answers well. Quote the brief back and ask "Is this still accurate?" to confirm, then move to gaps. @@ -345,7 +345,7 @@ The project exists. Code exists. Docs may exist. The interview focuses on: - What the builder wants to CHANGE (current pain, technical debt, strategic shifts) - What conventions and preferences exist but aren't documented -Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered by the existing codebase. +Expect 6-10 questions total, mostly in Excavation and Sharpening. Grounding is largely answered by the existing codebase. **Key adaptation:** Show the builder what you learned from their code. "I see a Python/FastAPI project with PostgreSQL and Docker. The test suite uses pytest. Is that the intended stack going forward?" Let the codebase speak first, then fill gaps. @@ -361,13 +361,13 @@ Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered b **The Therapist.** "And how does that make you feel about your product?" No. This is a builder interview, not a feelings exploration. Emotions matter (JTBD switching forces), but ask about user emotions, not builder emotions. -**Premature Architecture.** Jumping to "What database should we use?" in Phase 1. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. +**Premature Architecture.** Jumping to "What database should we use?" during Excavation. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. **The Echo Chamber.** Reflecting back everything the builder says without challenging anything. The Mom Test exists because people are too polite. Be constructive, not agreeable. "That's a big scope. Are you sure you need ALL of that for v1?" **Solution-First Questioning.** "What features should it have?" is the wrong question. "What job does it do for the user?" is the right one. Features are an output of the interview, not an input. -**Asking for Permission to Proceed.** Don't ask "Should we move to the next phase?" Just move when the signals are strong. If the builder has more to say, they'll say it. +**Asking for Permission to Proceed.** Don't ask "Should we move to the next section?" Just move when the signals are strong. If the builder has more to say, they'll say it. **Over-Indexing on Frameworks.** Don't say "Let's do a JTBD analysis" or "Let me apply Wardley Mapping here." The frameworks are lenses for the interviewer, not vocabulary for the builder. Just ask good questions. @@ -413,12 +413,12 @@ The bootstrap interview creates the foundation. Other skills deepen specific are ## Framework Attribution -| Framework | Primary Contribution | Phase(s) | +| Framework | Primary Contribution | Section(s) | |-----------|---------------------|----------| -| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | 2, 3 | -| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | 1, 2 | -| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | 1, 2 | -| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All phases | -| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | 2, 3 | -| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | 3 | -| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | 1, 3 | +| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | Sharpening, Grounding | +| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | Excavation, Sharpening | +| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | Excavation, Sharpening | +| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All sections | +| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | Sharpening, Grounding | +| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | Grounding | +| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | Excavation, Grounding | diff --git a/dist/cursor/skills/breakdown/SKILL.md b/dist/cursor/skills/breakdown/SKILL.md index 94b1f3a4d..90b40fc52 100644 --- a/dist/cursor/skills/breakdown/SKILL.md +++ b/dist/cursor/skills/breakdown/SKILL.md @@ -89,7 +89,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/dist/cursor/skills/foundations/SKILL.md b/dist/cursor/skills/foundations/SKILL.md index 1e7d3cbcc..4c0d3bdbd 100644 --- a/dist/cursor/skills/foundations/SKILL.md +++ b/dist/cursor/skills/foundations/SKILL.md @@ -114,6 +114,22 @@ Engineering foundations for consistent, high-quality code. | Constants | `UPPER_SNAKE` | `UPPER_SNAKE` | | Tests | `test___` | `describe/it` blocks | +### Artifact Names Never Cite Their Work Unit + +Name an artifact for what it is, never for the work unit that produced it. The directory or Change that contains it already records that provenance, so repeating it in the filename inverts the reference and rots the moment the work closes: a work unit points at its artifacts, artifacts never point back. + +| Instead of | Write | +|------------|-------| +| `u8-claude-smoke.mjs` | `smoke-claude-code-startup.mjs` | +| `report-spec-053-taxonomy-signoff.md` | `taxonomy-signoff.md` | +| `TASK-074-sidecar-audit-report.md` | `sidecar-audit.md` | + +Provenance belongs in a front-matter field such as `source:`, where it can be read and updated, not in a name that has to be renamed to stay true. + +Two look-alikes are correct and stay. A **version** is identity, not reference: `claude-code-2.1.218-plugin-startup-smoke.json`. A **timestamp** records when, not which work unit: `20260620-214448-skills-audit.md`. And a numbered record living in the directory that owns it *is* that entity, so `.agents/specs/SPEC-042-slug.md` and `docs/decisions/ADR-007-slug.md` are its own name rather than a citation. + +`loaf check --hook artifact-names` enforces this at commit time over tracked artifacts, grandfathering anything already `final` or `archived`. + ## Test Patterns Scenario-based fixture naming: diff --git a/dist/cursor/skills/git-workflow/references/commits.md b/dist/cursor/skills/git-workflow/references/commits.md index 5ed2ba9e1..d6a48ab9b 100644 --- a/dist/cursor/skills/git-workflow/references/commits.md +++ b/dist/cursor/skills/git-workflow/references/commits.md @@ -185,7 +185,7 @@ Internal terms that have no meaning outside the team's working context: - Spec IDs and task IDs (`SPEC-024`, `TASK-042`) - Session, sprint, or branch references - Internal terminology from skills/docs that isn't part of the user's mental model — e.g. `Q1`/`Q2`/`Q3` question numbers from a Triage Gate, internal gate-logic notation like `(Q1 OR Q2) AND Q3`, hook IDs that aren't user-facing -- "How the work got done" framing — interview steps, breakdown phases, review gates +- "How the work got done" framing — interview steps, breakdown steps, review gates ### Keep @@ -252,7 +252,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE] Four hooks automatically enforce the conventions documented in this file: -| Hook | Phase | Behavior | +| Hook | Timing | Behavior | |------|-------|----------| | `github-account` | Pre-tool (Bash) | Force-switch: switches the active `gh` account to the configured one before `gh` commands run (passes with a warning), exempting `gh auth` administration, and blocks only when the switch fails. It writes the shared global account pointer on every mismatched `gh` call -- read-only ones included -- so concurrent sessions on different identities collide on that pointer more often. | | `workflow-pre-pr` | Pre-tool (Bash) | Advisory: reminds about CHANGELOG [Unreleased] entries and PR format. Non-blocking. | @@ -269,26 +269,14 @@ BREAKING CHANGE: Description of breaking change. ### Pre-Release Versions -When developing toward a major version, use pre-release suffixes to mark development milestones: - -``` -2.0.0-dev.0 → dev.1 → dev.2 → ... → 2.0.0 - ↑ ↑ ↑ ↑ - start dev milestone milestone stable release -``` - | Suffix | Meaning | When to use | |--------|---------|-------------| -| `-dev.N` | Development milestone | Active development toward a target version | | `-alpha.N` | Alpha pre-release | Feature-complete but untested broadly | | `-beta.N` | Beta pre-release | Testing with wider audience | | `-rc.N` | Release candidate | Final validation before stable | **Convention:** -- Set the target version with `-dev.0` when starting a major effort (e.g. `2.0.0-dev.0`) -- Bump the dev counter (`-dev.N` → `-dev.N+1`) when a meaningful batch of landed work is ready to publish — a completed spec, a related feature group, or a release train -- Don't bump for every commit — that's what git history is for -- Strip the suffix (`-dev.N` → `2.0.0`) when all planned work is complete +- Use standard SemVer pre-release identifiers (`alpha`, `beta`, or `rc`) when publishing pre-release versions. - `loaf release` handles all bump types: `prerelease`, `release`, `major`, `minor`, `patch` -**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects with multi-milestone development cycles. +**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects publishing staged pre-releases before stable releases. diff --git a/dist/cursor/skills/handoff/SKILL.md b/dist/cursor/skills/handoff/SKILL.md index c72f2382c..671e52e04 100644 --- a/dist/cursor/skills/handoff/SKILL.md +++ b/dist/cursor/skills/handoff/SKILL.md @@ -120,3 +120,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/cursor/skills/housekeeping/SKILL.md b/dist/cursor/skills/housekeeping/SKILL.md index 4b2b39d44..0f5cdde66 100644 --- a/dist/cursor/skills/housekeeping/SKILL.md +++ b/dist/cursor/skills/housekeeping/SKILL.md @@ -138,3 +138,7 @@ After housekeeping, suggest `/reflect` if the session produced key decisions or | Report Template | [templates/report.md](templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/cursor/skills/implement/SKILL.md b/dist/cursor/skills/implement/SKILL.md index f21d97c44..ab06ea660 100644 --- a/dist/cursor/skills/implement/SKILL.md +++ b/dist/cursor/skills/implement/SKILL.md @@ -91,9 +91,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -345,7 +345,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/dist/cursor/skills/implement/references/batch-orchestration.md b/dist/cursor/skills/implement/references/batch-orchestration.md index 7b69603f5..69fe524c5 100644 --- a/dist/cursor/skills/implement/references/batch-orchestration.md +++ b/dist/cursor/skills/implement/references/batch-orchestration.md @@ -2,63 +2,63 @@ ## Contents - Orchestration Options -- Batch Resolution and Wave Planning +- Batch Resolution and Dependency-Ready Scheduling - Option Handling - Batch Execution Model - Blocked-State Recovery -Detailed reference for running specs, task ranges, or task lists with dependency waves. +Detailed reference for running specs, task ranges, or task lists with dependency-ready scheduling. ## Orchestration Options | Option | Behavior | |--------|----------| -| `--dry-run` | Show dependency/wave execution plan, do not run agents | -| `--parallel` | Run tasks in the same wave concurrently (max 3 at once) | -| `--continue` | Resume a blocked orchestration from the recorded task/wave | +| `--dry-run` | Show dependency-ready execution plan, do not run agents | +| `--parallel` | Run tasks in the same dependency-ready group concurrently (max 3 at once) | +| `--continue` | Resume a blocked orchestration from the recorded task/group | | `--skip TASK-XXX` | Mark one blocked task as skipped and continue | | `--abort` | Mark orchestration as aborted and stop remaining work | -## Batch Resolution and Wave Planning +## Batch Resolution and Dependency-Ready Scheduling For `SPEC-XXX`, `TASK-XXX..YYY`, and `TASK-XXX,YYY,ZZZ`: 1. Resolve selected tasks and validate each task file exists. 2. Extract `depends_on` from each task and build a dependency graph. -3. Group tasks into dependency waves: - - Wave 1: tasks with no unresolved dependencies - - Wave N: tasks whose dependencies are completed in earlier waves -4. If `--parallel` is set, allow parallel execution only within a wave and only for non-conflicting tasks. -5. Present execution plan (tasks, waves, mode, total count) and ask for confirmation unless `--dry-run`. -6. Track progress in the journal and in task statuses: log wave boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. +3. Group tasks into dependency-ready rounds: + - First round: tasks with no unresolved dependencies + - Each subsequent round: tasks whose dependencies are completed in earlier rounds +4. If `--parallel` is set, allow parallel execution only within a dependency-ready round and only for non-conflicting tasks. +5. Present execution plan (tasks, dependency-ready rounds, mode, total count) and ask for confirmation unless `--dry-run`. +6. Track progress in the journal and in task statuses: log round boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. ## Option Handling (`--continue`, `--skip`, `--abort`) 1. Recover batch progress from the journal: `loaf journal recent --since-last-wrap` (or `loaf journal context`) plus `loaf task list --json` to see which tasks are still open. -2. If `--continue`: resume from the last logged wave and task. -3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same wave. +2. If `--continue`: resume from the last logged dependency-ready round and task. +3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same dependency-ready round. 4. If `--abort`: log `block(orchestration): aborted`, print a summary, and stop. 5. If no in-flight batch is evident from the journal, report that and ask for fresh selection input. ## Batch Execution Model -When input resolves to multiple tasks, run a wave-based loop: +When input resolves to multiple tasks, run a dependency-ready round loop: 1. Set orchestration mode (`sequential` by default, `parallel` only with `--parallel`). -2. For each wave: - - Log the wave start with `loaf journal log` +2. For each dependency-ready round: + - Log the round start with `loaf journal log` - Run each task (sequentially, or concurrently within safety limits) - For each task: set `in_progress` -> spawn agent -> run task verification -> mark `done`/`failed` via `loaf task update` 3. If any task fails verification, stop immediately and log `block(orchestration): failed `. -4. Consider a wave complete only when all its tasks are `done` or skipped. -5. Continue until all waves complete, then log a closing entry summarizing the batch. +4. Consider a round complete only when all its tasks are `done` or skipped. +5. Continue until all rounds complete, then log a closing entry summarizing the batch. ## Blocked-State Recovery When blocked, always print: - Failed task ID and title -- Wave number and current progress +- Dependency-ready round and current progress - Failure reason + key error output - Recovery commands: @@ -71,5 +71,5 @@ When blocked, always print: Use these semantics: - `--continue`: after fixes are applied, retry from the blocked task -- `--skip`: skip only the specified task and continue remaining tasks in the current wave +- `--skip`: skip only the specified task and continue remaining tasks in the current dependency-ready round - `--abort`: finalize the orchestration as aborted with no further execution diff --git a/dist/cursor/skills/implement/references/branch-and-completion.md b/dist/cursor/skills/implement/references/branch-and-completion.md index 0f715e4c5..250c8cdca 100644 --- a/dist/cursor/skills/implement/references/branch-and-completion.md +++ b/dist/cursor/skills/implement/references/branch-and-completion.md @@ -195,7 +195,7 @@ never implement through open `blockedBy`. **Print the current date and timestamp when:** - Waiting for user input or decision -- Completing a phase of work +- Completing a coherent unit of work - Encountering a blocker - Wrapping up the conversation diff --git a/dist/cursor/skills/loaf-reference/SKILL.md b/dist/cursor/skills/loaf-reference/SKILL.md index 770deae54..526ddcbeb 100644 --- a/dist/cursor/skills/loaf-reference/SKILL.md +++ b/dist/cursor/skills/loaf-reference/SKILL.md @@ -46,7 +46,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic. diff --git a/dist/cursor/skills/loaf-reference/references/command-routing.md b/dist/cursor/skills/loaf-reference/references/command-routing.md index 14a8ded99..de4f16c02 100644 --- a/dist/cursor/skills/loaf-reference/references/command-routing.md +++ b/dist/cursor/skills/loaf-reference/references/command-routing.md @@ -6,8 +6,9 @@ Which command a task needs. For exact flags, run `loaf --help`. | Intent | Route | |--------|-------| -| Shape new work | `loaf change init `, then `loaf change check` | -| Start working on a task | the implement workflow (/implement); `loaf task`/`loaf spec` stay transitional until the conversion pass — see the TRANSITIONAL note in AGENTS.md | +| Shape new bounded work | `loaf change init `, then `loaf change check` | +| Start implementing new bounded work | the implement workflow (/implement) after shaping and validating its Change | +| Continue an existing task or spec record | `loaf task` and `loaf spec` remain supported for existing records | | Continue after a restart | `loaf journal context` | | Skills or content changed | `loaf build && loaf install --to ` | | See what is in progress | `loaf task list --active` | diff --git a/dist/cursor/skills/orchestration/SKILL.md b/dist/cursor/skills/orchestration/SKILL.md index 8dde33718..e3266ae17 100644 --- a/dist/cursor/skills/orchestration/SKILL.md +++ b/dist/cursor/skills/orchestration/SKILL.md @@ -18,7 +18,7 @@ version: 2.0.0-alpha.13 - Philosophy - Configuration - Artifact Locations -- Three-Phase Workflow +- Workflow by Lifecycle Comprehensive patterns for orchestration: coordinating multi-agent work, keeping the project journal current, running councils, delegating to specialized agents, and integrating with Linear. @@ -130,7 +130,7 @@ This skill uses paths from `.agents/loaf.json`: **Rule:** Agents write artifacts to disk, orchestrator reasons over artifacts, users retrieve from disk. -## Three-Phase Workflow +## Workflow by Lifecycle ### BEFORE (Planning) - Create/check external issue (Linear, GitHub) diff --git a/dist/cursor/skills/orchestration/references/context-management.md b/dist/cursor/skills/orchestration/references/context-management.md index 4a577309f..fd07ec254 100644 --- a/dist/cursor/skills/orchestration/references/context-management.md +++ b/dist/cursor/skills/orchestration/references/context-management.md @@ -19,7 +19,7 @@ Patterns for keeping long work resumable while using the project journal as exte Compaction is normal in long workflows. Design work that spans many exchanges so important state is already outside chat context. 1. **The journal is external memory.** Record decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. **Artifacts carry detail.** Changes, transitional tasks, reports, ADRs, and commits hold rich detail; journal entries point to them. +2. **Artifacts carry detail.** Changes, task-board records, reports, ADRs, and commits hold rich detail; journal entries point to them. 3. **Delegated work absorbs exploration.** Use delegated agents for broad investigation and return concise findings to the main context. 4. **`wrap` captures synthesis.** When meaningful work holds intentions or abandoned paths worth saving, write an optional `wrap` journal entry. @@ -36,7 +36,7 @@ Compaction is normal in long workflows. Design work that spans many exchanges so | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent branch entries after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records retained during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each returned layer includes `source_available`, `available_count`, `shown_count`, `truncated`, and `expand_command`; paginated layers also include a cursor. Treat `source_available: false` as an explicit unavailable source, never as “nothing is active.” If Change discovery is unavailable, `active-changes` and `active-lineage` are unavailable and the digest carries a diagnostic. @@ -60,7 +60,7 @@ Use `/clear` when starting a completely new task, after the previous task is com PreCompact: 1. Flush unrecorded decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. Reference Changes, transitional tasks, reports, commits, and files by stable ID or path. +2. Reference Changes, task-board records, reports, commits, and files by stable ID or path. 3. On an exact target mode with supported PreCompact delivery, let the hook nudge the flush; otherwise flush manually before compacting. PostCompact: diff --git a/dist/cursor/skills/orchestration/references/linear.md b/dist/cursor/skills/orchestration/references/linear.md index 22d55b3ce..26ba14472 100644 --- a/dist/cursor/skills/orchestration/references/linear.md +++ b/dist/cursor/skills/orchestration/references/linear.md @@ -103,7 +103,7 @@ In Linear-native mode (`integrations.linear.enabled: true`), each spec produces one parent **rollup issue** and N sub-issues under it. ``` -[SPEC-024] Agent framework alignment ← parent, label: `spec` +Agent framework alignment ← parent, label: `change` ├── Split reviewer profile into reviewer/auditor ← sub-issue, label: type/refactor ├── Harden MCP fallback path ← sub-issue, label: type/feature └── Migrate legacy task references ← sub-issue, label: type/refactor @@ -127,8 +127,8 @@ researcher). Consolidate historical profile variants and add tool-boundary tests so profiles can't drift without a test failing. ## Context -See `.agents/specs/SPEC-024-agent-framework-alignment.md` for full text, -council references, rabbit holes, and strategic tensions. +See the canonical change file in the repository for full text, council +references, rabbit holes, and strategic tensions. ## Progress Sub-issues track execution. @@ -213,7 +213,7 @@ None currently. |-------|---------| | `Working on API` | `- [ ] API implementation` | | `Done with schema` | `- [x] Schema updated` | -| `Phase 1: Discovery` | `Discovery - COMPLETE` | +| `Discovery: IN PROGRESS` | `Discovery: COMPLETE` | | `Journal entry: ...` | *(omit entirely)* | | `Council decision: ...` | *(omit entirely)* | | `Week 1 deliverables` | `Initial deliverables` | @@ -373,6 +373,6 @@ Use `scripts/suggest-team.py "task desc"` to get suggestions. ### DON'T - Use emoji in progress lists - Reference local files (sessions, councils, plans) -- Use phase/stage/week terminology +- Use numbered development-stage terminology - Include absolute file paths - Duplicate issue titles after IDs diff --git a/dist/cursor/skills/orchestration/references/local-tasks.md b/dist/cursor/skills/orchestration/references/local-tasks.md index 183d997f3..58d3d033c 100644 --- a/dist/cursor/skills/orchestration/references/local-tasks.md +++ b/dist/cursor/skills/orchestration/references/local-tasks.md @@ -167,7 +167,7 @@ project journal (`loaf journal recent`, `loaf journal search`). 1. Can a single specialized agent complete this? → If no, split by agent type 2. Does it touch multiple unrelated concerns? → If yes, split by concern -3. Will the agent need too much context? → If yes, split into phases +3. Will the agent need too much context? → If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? → If yes, merge back ### Agent Scope diff --git a/dist/cursor/skills/orchestration/references/parallel-agents.md b/dist/cursor/skills/orchestration/references/parallel-agents.md index 7bb41deb5..f83e189d2 100644 --- a/dist/cursor/skills/orchestration/references/parallel-agents.md +++ b/dist/cursor/skills/orchestration/references/parallel-agents.md @@ -119,7 +119,7 @@ When streams complete: |---------|---------------------| | `/breakdown` | Identify parallelizable tasks during decomposition | | `/implement` | Single task, usually sequential | -| `/implement` | Runs dependency-wave orchestration, including parallel-safe tasks | +| `/implement` | Runs dependency-aware orchestration, including parallel-safe tasks | ## Conflict Resolution diff --git a/dist/cursor/skills/refactor-deepen/SKILL.md b/dist/cursor/skills/refactor-deepen/SKILL.md index a8803d341..e1d120b94 100644 --- a/dist/cursor/skills/refactor-deepen/SKILL.md +++ b/dist/cursor/skills/refactor-deepen/SKILL.md @@ -83,12 +83,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -149,11 +149,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -210,7 +211,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -310,7 +311,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/dist/cursor/skills/refactor-deepen/references/interface-design.md b/dist/cursor/skills/refactor-deepen/references/interface-design.md index ca6b79df1..401ffced5 100644 --- a/dist/cursor/skills/refactor-deepen/references/interface-design.md +++ b/dist/cursor/skills/refactor-deepen/references/interface-design.md @@ -1,6 +1,6 @@ # Interface Design — Parallel Sub-Agent Pattern -The INTERFACE-DESIGN phase of `/refactor-deepen` proposes the public surface +The Interface Design activity of `/refactor-deepen` proposes the public surface of a deepened module by sampling three independent design attempts and presenting all three to the user. Variety must come from sampling, not from manufactured opposition. @@ -31,10 +31,8 @@ optimizes for minimalism, Agent 2 for flexibility, Agent 3 for the common-caller path. That choice is reasonable when the agents are domain-agnostic and the orchestrator wants guaranteed surface variety. -Loaf rejects that choice. The decision is captured in -[SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md), -specifically in the Rabbit Holes and No-Gos sections (lines 96 and 107). The -short version: priming manufactures diversity rather than letting it emerge, +Loaf rejects that choice. The active rule is to use identical briefs: priming +manufactures diversity rather than letting it emerge, and manufactured diversity is dishonest signal. If the three designs do converge, the response is more agents or rerun — not priming. See [Convergence Fallback](#convergence-fallback) below. @@ -71,7 +69,7 @@ Three reasons, in order of importance: 2. **No dominant lens upfront.** Picking which constraint each agent optimizes for is itself a design decision. Doing it pre-grilling biases - the entire phase toward whatever lens the orchestrator happened to + the entire activity toward whatever lens the orchestrator happened to pick. Loaf's grilling protocol is supposed to surface tradeoffs from the codebase and the user, not from the orchestrator's pre-commitments. @@ -91,7 +89,7 @@ Justification: researcher contract: "Return findings as structured reports: summary, options (ranked with trade-offs), evidence sources, and a recommendation." See [content/agents/researcher.md](../../../agents/researcher.md). -- Read-only access matches the phase's purpose. The INTERFACE-DESIGN phase +- Read-only access matches the activity's purpose. Interface Design proposes designs; it does not implement them. Granting write access invites scope creep into "let me just sketch the implementation" and pollutes the parallel sampling. @@ -102,14 +100,14 @@ Justification: ### When `implementer` Could Be an Alternative -If the design phase needs to write probe code — a quick spike to verify +If the design activity needs to write probe code — a quick spike to verify that a proposed interface compiles against the existing call sites, for example — the `implementer` profile becomes viable. See [content/agents/implementer.md](../../../agents/implementer.md). The default remains `researcher` because: -- Probe code at this phase is rarely necessary; the deepening review +- Probe code during this activity is rarely necessary; the deepening review catches most fatal interface mistakes before code is written. - Three implementers writing probe code in parallel risks three divergent partial implementations of the same module — a merge problem the user @@ -162,7 +160,7 @@ Inside the grilling loop, after dependency classification, only when: If the interface is obvious from the dependency category and the call sites — for example, a thin adapter over a true-external dependency — -skip the parallel phase. A single proposed interface is enough. +skip parallel exploration. A single proposed interface is enough. ## Convergence Fallback @@ -172,7 +170,7 @@ implementation strategy, same tradeoffs. Two cases: 1. **Convergence is real.** The problem has a single best answer. Accept the convergence as a genuine finding and proceed to the PLAN with that single design. Note in the PLAN's "rejected alternatives" section that - the parallel phase produced no meaningful variation. + parallel exploration produced no meaningful variation. 2. **Convergence feels accidental.** The designs are suspiciously similar, the user senses a missed branch, or the briefing was so @@ -226,7 +224,7 @@ escalates on its own. ## Cost Note -A single invocation of the parallel phase is approximately **3 × +A single invocation of parallel exploration is approximately **3 × deep-exploration cost** in tokens — three sub-agents each running a full design pass against the same context. With more-agents escalation, the cost scales linearly (4 agents = ~4 ×, 5 agents = ~5 ×). @@ -235,10 +233,10 @@ This pattern is **opt-in inside the grilling loop**. It is not auto-triggered on every `/refactor-deepen` invocation. The 3-agent default is the cost ceiling for the default settings — the skill does not scale agent count silently. If a candidate's interface is obvious, skip the -phase entirely and propose a single design. +activity entirely and propose a single design. The cost is an explicit tradeoff the user accepts when they enter the -INTERFACE-DESIGN phase for a non-obvious interface. The skill should +Interface Design activity for a non-obvious interface. The skill should surface the cost briefly before spawning: > Spawning 3 design agents in parallel (~3 × token cost). Proceed? @@ -265,7 +263,7 @@ After the three sub-agents return: | Don't | Do Instead | |-------|------------| | Prime agents with opposing constraints by default | Use identical briefs; let sampling produce variety | -| Auto-trigger the parallel phase on every invocation | Invoke only when interface is non-obvious | +| Auto-trigger parallel exploration on every invocation | Invoke only when interface is non-obvious | | Use `implementer` profile for design sub-agents | Use `researcher`; switch to `implementer` only on explicit user request | | Add a "lens" to the brief silently | Surface the tradeoff to the user before priming | | Pre-rank the three designs in the output | Present in arbitrary order, let the user pick | @@ -283,6 +281,3 @@ After the three sub-agents return: agent profile for design sub-agents - [content/agents/implementer.md](../../../agents/implementer.md) — Alternative profile when probe code is needed -- [SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md) - — The shape decision (lines 64, 96, 107, 117) that established the - identical-brief default diff --git a/dist/cursor/skills/refactor-deepen/templates/plan.md b/dist/cursor/skills/refactor-deepen/templates/plan.md index 54a591e61..f564229a3 100644 --- a/dist/cursor/skills/refactor-deepen/templates/plan.md +++ b/dist/cursor/skills/refactor-deepen/templates/plan.md @@ -27,7 +27,7 @@ write a new file rather than updating an existing one. |-------|----------|-------| | `title` | Yes | One-line description of the deepening, not the candidate name | | `created` | Yes | ISO 8601 UTC, e.g. `2026-05-02T01:30:00Z` (must match the filename timestamp) | -| `status` | Yes | `drafting` on first write — lifecycle states are deferred to a follow-up spec | +| `status` | Yes | `drafting` on first write; this template does not define additional lifecycle states | | `spec` | Yes | `SPEC-NNN` if the plan is scoped under a spec; `null` otherwise (do not omit the key) | | `related` | No | List of related artifact IDs (`ADR-*`, `SPEC-*`, idea filenames, other plan filenames) | @@ -36,8 +36,7 @@ identity, mirroring councils and ideas. ## Required Sections -The five sections below are the *minimal shape* defined in SPEC-034. Order is -load-bearing: each section assumes the previous one is settled. Do not reorder. +The five sections below are the *minimal shape* for a PLAN. Order is load-bearing: each section assumes the previous one is settled. Do not reorder. 1. **Candidate** — what's being considered for deepening. Name the **module** verbatim (use the canonical glossary term — run `loaf kb glossary check` @@ -111,14 +110,12 @@ proportional to actual usage, matching how `.agents/specs/` behaves. ## Linear-Native Mode: Fail Fast -PLAN files are **local-only storage**. Per SPEC-034 line 81, write commands -must fail fast in Linear-native mode rather than silently degrade. The -consuming skill (`/refactor-deepen`) is responsible for: +PLAN files are **local-only storage**. Write commands must fail fast in Linear-native mode rather than silently degrade. The consuming skill (`/refactor-deepen`) is responsible for: 1. Reading `.agents/loaf.json` and checking `integrations.linear.enabled`. 2. If true: aborting before `mkdir -p .agents/plans` and before any write, with the verbatim error - `"Linear-native plan storage pending artifact-taxonomy spec — local mode only for now."` + `"Linear-native plan storage unavailable — continuing with a read-only report."` 3. If false: proceeding with the write as documented above. This template intentionally does **not** wrap the write in a diff --git a/dist/cursor/skills/research/SKILL.md b/dist/cursor/skills/research/SKILL.md index 028800ce8..346c6ca94 100644 --- a/dist/cursor/skills/research/SKILL.md +++ b/dist/cursor/skills/research/SKILL.md @@ -144,3 +144,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/cursor/skills/shape/SKILL.md b/dist/cursor/skills/shape/SKILL.md index 5066edca2..0552d784a 100644 --- a/dist/cursor/skills/shape/SKILL.md +++ b/dist/cursor/skills/shape/SKILL.md @@ -164,3 +164,7 @@ Offer to push the branch and open a draft PR, using [the PR template](templates/ | Decomposition | [references/decomposition.md](references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/cursor/skills/shape/references/cli-boundary.md b/dist/cursor/skills/shape/references/cli-boundary.md index efb3cc1b5..7f5816b03 100644 --- a/dist/cursor/skills/shape/references/cli-boundary.md +++ b/dist/cursor/skills/shape/references/cli-boundary.md @@ -13,7 +13,7 @@ Folder resolution: an explicit `[folder]` argument always wins; otherwise the cu Output splits into two tiers: - **Violations** — always fail (exit code 2), regardless of flags: status-like frontmatter keys (`readiness`, `status`, `state`) or values matching the canonical change-state vocabulary; frontmatter not opening the file at byte one; malformed `YYYYMMDD-slug` folder naming; identity mismatch between `change:`/`created:` and the folder name; missing Product Contract sections (Problem, Hypothesis, Scope, Observable Workflow, Rabbit Holes and No-Gos). -- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A shaping-stage Change with open gaps is valid; the report just says what's still missing. +- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A Change with open gaps is incomplete and non-executable; the report just says what's still missing. `--require-executable` turns structural executability into a gate (exit code 1 if not structurally executable); it does not prove implementation completion. This is implement's preflight and CI's non-draft-PR check, not something shape itself passes during shaping. diff --git a/dist/cursor/skills/shape/references/decomposition.md b/dist/cursor/skills/shape/references/decomposition.md index edf38530b..5ffefbe74 100644 --- a/dist/cursor/skills/shape/references/decomposition.md +++ b/dist/cursor/skills/shape/references/decomposition.md @@ -4,7 +4,7 @@ Shaping step absorbed from the retired breakdown skill: dependency awareness, gr ## What Survives -- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into phases. Are you splitting just to have more units? If yes, merge back. +- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into smaller coherent units. Are you splitting just to have more units? If yes, merge back. - **Right-sizing rules** — one agent type per unit (completable by a single implementer), one concern per unit (one layer, service, or component), context-appropriate (fits in model context with room for exploration), not over-fragmented (don't split what naturally belongs together). - **Per-unit verification discipline** — every unit includes its own observable done condition. Never a separate "verify" unit; keep tests with the code they test. - **Own the decisions** — decide granularity and unit boundaries autonomously. Ask the user only when two orderings are genuinely equally valid with different trade-offs; otherwise decide and move on. diff --git a/dist/opencode/.loaf-target-manifest.json b/dist/opencode/.loaf-target-manifest.json index c96e790a9..5610789c6 100644 --- a/dist/opencode/.loaf-target-manifest.json +++ b/dist/opencode/.loaf-target-manifest.json @@ -114,7 +114,7 @@ "kind": "plugin", "source_path": "plugins/hooks.ts", "destination": "plugins/hooks.ts", - "sha256": "b345ff7ec631d30f009c96d1d3161ba731fa57352a153e71bdf95583640c25e6", + "sha256": "3aaf803762a52b541ef7ddac008ff87bba20ac5a7ed3940d8018abe610f84873", "mode": 420 } ] diff --git a/dist/opencode/commands/architecture.md b/dist/opencode/commands/architecture.md index d21928de7..6de542b7f 100644 --- a/dist/opencode/commands/architecture.md +++ b/dist/opencode/commands/architecture.md @@ -43,7 +43,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/dist/opencode/commands/bootstrap.md b/dist/opencode/commands/bootstrap.md index 7414daf7f..216b06d3e 100644 --- a/dist/opencode/commands/bootstrap.md +++ b/dist/opencode/commands/bootstrap.md @@ -217,7 +217,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -226,14 +226,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](../skills/bootstrap/references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](../skills/bootstrap/references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -243,9 +243,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/dist/opencode/commands/breakdown.md b/dist/opencode/commands/breakdown.md index 0dd5e8c4f..051e2c75b 100644 --- a/dist/opencode/commands/breakdown.md +++ b/dist/opencode/commands/breakdown.md @@ -89,7 +89,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/dist/opencode/commands/handoff.md b/dist/opencode/commands/handoff.md index b5f2acd93..c07e1d9f3 100644 --- a/dist/opencode/commands/handoff.md +++ b/dist/opencode/commands/handoff.md @@ -120,3 +120,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/commands/housekeeping.md b/dist/opencode/commands/housekeeping.md index 5e7e919b6..d0384050b 100644 --- a/dist/opencode/commands/housekeeping.md +++ b/dist/opencode/commands/housekeeping.md @@ -138,3 +138,7 @@ After housekeeping, suggest `/reflect` if the session produced key decisions or | Report Template | [templates/report.md](../skills/housekeeping/templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/commands/implement.md b/dist/opencode/commands/implement.md index bdca5a744..2656f09c2 100644 --- a/dist/opencode/commands/implement.md +++ b/dist/opencode/commands/implement.md @@ -91,9 +91,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -345,7 +345,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](../skills/implement/references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](../skills/implement/references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](../skills/implement/references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/dist/opencode/commands/refactor-deepen.md b/dist/opencode/commands/refactor-deepen.md index 591936f7b..1bd048c4c 100644 --- a/dist/opencode/commands/refactor-deepen.md +++ b/dist/opencode/commands/refactor-deepen.md @@ -82,12 +82,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](../skills/refactor-deepen/templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -148,11 +148,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -209,7 +210,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -309,7 +310,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](../skills/refactor-deepen/references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](../skills/refactor-deepen/references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](../skills/refactor-deepen/references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](../skills/refactor-deepen/references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](../skills/refactor-deepen/templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](../skills/refactor-deepen/templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/dist/opencode/commands/research.md b/dist/opencode/commands/research.md index 3e1098177..dea52ebcf 100644 --- a/dist/opencode/commands/research.md +++ b/dist/opencode/commands/research.md @@ -144,3 +144,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/commands/shape.md b/dist/opencode/commands/shape.md index 0e76229fb..2cf4bceab 100644 --- a/dist/opencode/commands/shape.md +++ b/dist/opencode/commands/shape.md @@ -164,3 +164,7 @@ Offer to push the branch and open a draft PR, using [the PR template](../skills/ | Decomposition | [references/decomposition.md](../skills/shape/references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](../skills/shape/references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](../skills/shape/references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/plugins/hooks.ts b/dist/opencode/plugins/hooks.ts index 1d4004e6a..e1850697e 100644 --- a/dist/opencode/plugins/hooks.ts +++ b/dist/opencode/plugins/hooks.ts @@ -258,6 +258,13 @@ const preToolHooks: Record = { "failClosed": true, "if": "Bash(git push:*)" }, + { + "id": "artifact-names", + "command": "loaf check --hook artifact-names", + "timeout": 30000, + "failClosed": true, + "if": "Bash(git commit:*)" + }, { "id": "github-account", "command": "loaf check --hook github-account", diff --git a/dist/opencode/skills/architecture/SKILL.md b/dist/opencode/skills/architecture/SKILL.md index 5ae8882d5..8eb91d42a 100644 --- a/dist/opencode/skills/architecture/SKILL.md +++ b/dist/opencode/skills/architecture/SKILL.md @@ -44,7 +44,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/dist/opencode/skills/bootstrap/SKILL.md b/dist/opencode/skills/bootstrap/SKILL.md index 01b6349b8..c389e1987 100644 --- a/dist/opencode/skills/bootstrap/SKILL.md +++ b/dist/opencode/skills/bootstrap/SKILL.md @@ -218,7 +218,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -227,14 +227,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -244,9 +244,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/dist/opencode/skills/bootstrap/references/interview-guide.md b/dist/opencode/skills/bootstrap/references/interview-guide.md index ad67e1947..3313798f0 100644 --- a/dist/opencode/skills/bootstrap/references/interview-guide.md +++ b/dist/opencode/skills/bootstrap/references/interview-guide.md @@ -5,10 +5,10 @@ A structured interview framework for helping builders go from a vague idea to a ## Contents - How This Guide Works - Framework Foundations -- Phase 1: Excavation (The Spark) -- Phase 2: Sharpening (The Shape) -- Phase 3: Grounding (The Architecture) -- Phase 4: Synthesis (The Documents) +- Excavation (The Spark) +- Sharpening (The Shape) +- Grounding (The Architecture) +- Synthesis (The Documents) - Adapting Interview Depth - Anti-Patterns - Transitioning to Document Drafting @@ -17,16 +17,16 @@ A structured interview framework for helping builders go from a vague idea to a This is a **builder interview**, not a user research interview. The interviewer (the agent) is helping the builder crystallize their own thinking -- not extracting requirements from a stakeholder. The builder has context, intuition, and taste that need to be surfaced, challenged, and structured. -The interview flows through four phases, each producing progressively sharper artifacts: +The interview flows through four sections, each producing progressively sharper artifacts: -| Phase | Focus | Primary Output | Frameworks | +| Section | Focus | Primary Output | Frameworks | |-------|-------|----------------|------------| -| 1. Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | -| 2. Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | -| 3. Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | -| 4. Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | +| Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | +| Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | +| Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | +| Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | -Phases are not rigid walls. A strong answer in Phase 1 might skip half of Phase 2. A weak answer in Phase 2 might loop back to Phase 1. Follow the energy. +Sections are not rigid walls. A strong answer in Excavation might skip half of Sharpening. A weak answer in Sharpening might loop back to Excavation. Follow the energy. --- @@ -80,7 +80,7 @@ What each framework contributes and what to skip. **What to skip:** Customer interview logistics, meeting scheduling advice. The Mom Test is about question quality, not interview operations. -**Connection to documents:** Informs the quality of every answer in every phase. The Mom Test isn't a phase -- it's a lens applied to ALL questioning. It keeps the interview honest. +**Connection to documents:** Informs the quality of every answer in every section. The Mom Test isn't a section -- it's a lens applied to ALL questioning. It keeps the interview honest. ### Design Sprint - Understand Phase (Google Ventures) @@ -120,7 +120,7 @@ What each framework contributes and what to skip. --- -## Phase 1: Excavation (The Spark) +## Excavation (The Spark) **Goal:** Understand what exists, why it matters, and whether the problem is real. @@ -157,9 +157,9 @@ The builder's own experience with the problem is the richest source of insight. - "Have you seen anyone spend money or significant time on this problem?" *(Mom Test: evidence of pain)* - "Is this problem getting worse or better over time? Why?" *(Wardley: movement awareness)* -### Phase 1 Signals +### Excavation Signals -**Strong signal (move to Phase 2):** Builder can describe a specific person with a specific problem and knows what they do about it today. +**Strong signal (move to Sharpening):** Builder can describe a specific person with a specific problem and knows what they do about it today. **Weak signal (dig deeper):** Builder describes a category ("developers need better tools") without specifics. Ask for a story: "Tell me about a specific moment when this problem was most painful." @@ -167,13 +167,13 @@ The builder's own experience with the problem is the richest source of insight. --- -## Phase 2: Sharpening (The Shape) +## Sharpening (The Shape) **Goal:** Define who this is for, what it does, and -- critically -- what it does NOT do. Set complexity and boundaries. -**Mood:** Constructive pressure. Phase 1 was expansive; Phase 2 is reductive. The builder will want to include everything. Your job is to help them cut. +**Mood:** Constructive pressure. Excavation was expansive; Sharpening is reductive. The builder will want to include everything. Your job is to help them cut. -**Duration:** This is typically the longest phase. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. +**Duration:** This is typically the longest section. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. ### Must-Ask Questions @@ -210,17 +210,17 @@ Surface the riskiest assumptions. "Will users actually switch from their current - "How might we make [the hardest part] effortless?" *(Design Sprint: HMW)* - "What would definitely make this fail?" *(First Principles: inversion)* -### Phase 2 Signals +### Sharpening Signals -**Strong signal (move to Phase 3):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. +**Strong signal (move to Grounding):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. **Weak signal (iterate):** Builder keeps expanding scope. "It should also..." is a signal to tighten. Ask: "If you could only do ONE thing, what would it be?" -**Red flag (loop back to Phase 1):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" +**Red flag (loop back to Excavation):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" --- -## Phase 3: Grounding (The Architecture) +## Grounding (The Architecture) **Goal:** Establish technical direction, identify what to build vs. buy, and surface hidden complexity. @@ -257,19 +257,19 @@ These become the rabbit holes in the spec. The builder often knows where the dra - "If you had to ship something in one week, what would you cut?" *(Shape Up: scope pressure test)* - "Are there regulatory, legal, or compliance considerations?" *(Often forgotten at 0-to-1)* -### Phase 3 Signals +### Grounding Signals -**Strong signal (move to Phase 4):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. +**Strong signal (move to Synthesis):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. **Weak signal (iterate):** Builder wants to build everything from scratch. Challenge: "What's the thing ONLY YOU can build? Build that. Use existing solutions for the rest." -**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Phase 3 and note that ARCHITECTURE.md will be populated later when technical decisions are made. +**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Grounding and note that ARCHITECTURE.md will be populated later when technical decisions are made. --- -## Phase 4: Synthesis (The Documents) +## Synthesis (The Documents) -**Goal:** Transform interview insights into draft documents. This is NOT a phase of the interview -- it's the transition from interviewing to drafting. +**Goal:** Transform interview insights into draft documents. This is NOT an interview section -- it's the transition from interviewing to drafting. **Mood:** Collaborative, iterative. The agent drafts, the builder reacts and refines. @@ -319,11 +319,11 @@ Allow the builder to approve all remaining sections at once if they're satisfied ## Adapting Interview Depth -The interview adapts to three contexts, per SPEC-013's mode detection: +The interview adapts to three contexts based on the detected project mode: ### Greenfield + Empty (Full Interview) -Run all four phases in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all phases. This is where the interview guide earns its keep. +Run all four sections in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all sections. This is where the interview guide earns its keep. **Key adaptation:** Be patient. The builder may circle back, contradict themselves, or get stuck. That's normal. Let them think out loud. Silence after a question is productive, not awkward. @@ -332,9 +332,9 @@ Run all four phases in full. The builder has minimal clarity and needs the most Read and analyze the brief first. Then run a compressed interview that: - Confirms understanding ("Here's what I extracted -- is this right?") - Challenges assumptions ("Your brief says X, but have you considered Y?") -- Fills gaps (which phases have missing information?) +- Fills gaps (which sections have missing information?) -Expect 8-12 questions total, concentrated in whichever phases the brief is weakest. +Expect 8-12 questions total, concentrated in whichever sections the brief is weakest. **Key adaptation:** Don't re-ask what the brief already answers well. Quote the brief back and ask "Is this still accurate?" to confirm, then move to gaps. @@ -345,7 +345,7 @@ The project exists. Code exists. Docs may exist. The interview focuses on: - What the builder wants to CHANGE (current pain, technical debt, strategic shifts) - What conventions and preferences exist but aren't documented -Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered by the existing codebase. +Expect 6-10 questions total, mostly in Excavation and Sharpening. Grounding is largely answered by the existing codebase. **Key adaptation:** Show the builder what you learned from their code. "I see a Python/FastAPI project with PostgreSQL and Docker. The test suite uses pytest. Is that the intended stack going forward?" Let the codebase speak first, then fill gaps. @@ -361,13 +361,13 @@ Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered b **The Therapist.** "And how does that make you feel about your product?" No. This is a builder interview, not a feelings exploration. Emotions matter (JTBD switching forces), but ask about user emotions, not builder emotions. -**Premature Architecture.** Jumping to "What database should we use?" in Phase 1. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. +**Premature Architecture.** Jumping to "What database should we use?" during Excavation. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. **The Echo Chamber.** Reflecting back everything the builder says without challenging anything. The Mom Test exists because people are too polite. Be constructive, not agreeable. "That's a big scope. Are you sure you need ALL of that for v1?" **Solution-First Questioning.** "What features should it have?" is the wrong question. "What job does it do for the user?" is the right one. Features are an output of the interview, not an input. -**Asking for Permission to Proceed.** Don't ask "Should we move to the next phase?" Just move when the signals are strong. If the builder has more to say, they'll say it. +**Asking for Permission to Proceed.** Don't ask "Should we move to the next section?" Just move when the signals are strong. If the builder has more to say, they'll say it. **Over-Indexing on Frameworks.** Don't say "Let's do a JTBD analysis" or "Let me apply Wardley Mapping here." The frameworks are lenses for the interviewer, not vocabulary for the builder. Just ask good questions. @@ -413,12 +413,12 @@ The bootstrap interview creates the foundation. Other skills deepen specific are ## Framework Attribution -| Framework | Primary Contribution | Phase(s) | +| Framework | Primary Contribution | Section(s) | |-----------|---------------------|----------| -| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | 2, 3 | -| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | 1, 2 | -| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | 1, 2 | -| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All phases | -| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | 2, 3 | -| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | 3 | -| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | 1, 3 | +| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | Sharpening, Grounding | +| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | Excavation, Sharpening | +| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | Excavation, Sharpening | +| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All sections | +| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | Sharpening, Grounding | +| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | Grounding | +| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | Excavation, Grounding | diff --git a/dist/opencode/skills/breakdown/SKILL.md b/dist/opencode/skills/breakdown/SKILL.md index 871de921c..c70bcb373 100644 --- a/dist/opencode/skills/breakdown/SKILL.md +++ b/dist/opencode/skills/breakdown/SKILL.md @@ -90,7 +90,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/dist/opencode/skills/foundations/SKILL.md b/dist/opencode/skills/foundations/SKILL.md index 1e7d3cbcc..4c0d3bdbd 100644 --- a/dist/opencode/skills/foundations/SKILL.md +++ b/dist/opencode/skills/foundations/SKILL.md @@ -114,6 +114,22 @@ Engineering foundations for consistent, high-quality code. | Constants | `UPPER_SNAKE` | `UPPER_SNAKE` | | Tests | `test___` | `describe/it` blocks | +### Artifact Names Never Cite Their Work Unit + +Name an artifact for what it is, never for the work unit that produced it. The directory or Change that contains it already records that provenance, so repeating it in the filename inverts the reference and rots the moment the work closes: a work unit points at its artifacts, artifacts never point back. + +| Instead of | Write | +|------------|-------| +| `u8-claude-smoke.mjs` | `smoke-claude-code-startup.mjs` | +| `report-spec-053-taxonomy-signoff.md` | `taxonomy-signoff.md` | +| `TASK-074-sidecar-audit-report.md` | `sidecar-audit.md` | + +Provenance belongs in a front-matter field such as `source:`, where it can be read and updated, not in a name that has to be renamed to stay true. + +Two look-alikes are correct and stay. A **version** is identity, not reference: `claude-code-2.1.218-plugin-startup-smoke.json`. A **timestamp** records when, not which work unit: `20260620-214448-skills-audit.md`. And a numbered record living in the directory that owns it *is* that entity, so `.agents/specs/SPEC-042-slug.md` and `docs/decisions/ADR-007-slug.md` are its own name rather than a citation. + +`loaf check --hook artifact-names` enforces this at commit time over tracked artifacts, grandfathering anything already `final` or `archived`. + ## Test Patterns Scenario-based fixture naming: diff --git a/dist/opencode/skills/git-workflow/references/commits.md b/dist/opencode/skills/git-workflow/references/commits.md index 5ed2ba9e1..d6a48ab9b 100644 --- a/dist/opencode/skills/git-workflow/references/commits.md +++ b/dist/opencode/skills/git-workflow/references/commits.md @@ -185,7 +185,7 @@ Internal terms that have no meaning outside the team's working context: - Spec IDs and task IDs (`SPEC-024`, `TASK-042`) - Session, sprint, or branch references - Internal terminology from skills/docs that isn't part of the user's mental model — e.g. `Q1`/`Q2`/`Q3` question numbers from a Triage Gate, internal gate-logic notation like `(Q1 OR Q2) AND Q3`, hook IDs that aren't user-facing -- "How the work got done" framing — interview steps, breakdown phases, review gates +- "How the work got done" framing — interview steps, breakdown steps, review gates ### Keep @@ -252,7 +252,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE] Four hooks automatically enforce the conventions documented in this file: -| Hook | Phase | Behavior | +| Hook | Timing | Behavior | |------|-------|----------| | `github-account` | Pre-tool (Bash) | Force-switch: switches the active `gh` account to the configured one before `gh` commands run (passes with a warning), exempting `gh auth` administration, and blocks only when the switch fails. It writes the shared global account pointer on every mismatched `gh` call -- read-only ones included -- so concurrent sessions on different identities collide on that pointer more often. | | `workflow-pre-pr` | Pre-tool (Bash) | Advisory: reminds about CHANGELOG [Unreleased] entries and PR format. Non-blocking. | @@ -269,26 +269,14 @@ BREAKING CHANGE: Description of breaking change. ### Pre-Release Versions -When developing toward a major version, use pre-release suffixes to mark development milestones: - -``` -2.0.0-dev.0 → dev.1 → dev.2 → ... → 2.0.0 - ↑ ↑ ↑ ↑ - start dev milestone milestone stable release -``` - | Suffix | Meaning | When to use | |--------|---------|-------------| -| `-dev.N` | Development milestone | Active development toward a target version | | `-alpha.N` | Alpha pre-release | Feature-complete but untested broadly | | `-beta.N` | Beta pre-release | Testing with wider audience | | `-rc.N` | Release candidate | Final validation before stable | **Convention:** -- Set the target version with `-dev.0` when starting a major effort (e.g. `2.0.0-dev.0`) -- Bump the dev counter (`-dev.N` → `-dev.N+1`) when a meaningful batch of landed work is ready to publish — a completed spec, a related feature group, or a release train -- Don't bump for every commit — that's what git history is for -- Strip the suffix (`-dev.N` → `2.0.0`) when all planned work is complete +- Use standard SemVer pre-release identifiers (`alpha`, `beta`, or `rc`) when publishing pre-release versions. - `loaf release` handles all bump types: `prerelease`, `release`, `major`, `minor`, `patch` -**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects with multi-milestone development cycles. +**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects publishing staged pre-releases before stable releases. diff --git a/dist/opencode/skills/handoff/SKILL.md b/dist/opencode/skills/handoff/SKILL.md index e574120b7..eb6355701 100644 --- a/dist/opencode/skills/handoff/SKILL.md +++ b/dist/opencode/skills/handoff/SKILL.md @@ -121,3 +121,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/skills/housekeeping/SKILL.md b/dist/opencode/skills/housekeeping/SKILL.md index 6db3b2397..cd2e4cccf 100644 --- a/dist/opencode/skills/housekeeping/SKILL.md +++ b/dist/opencode/skills/housekeeping/SKILL.md @@ -139,3 +139,7 @@ After housekeeping, suggest `/reflect` if the session produced key decisions or | Report Template | [templates/report.md](templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/skills/implement/SKILL.md b/dist/opencode/skills/implement/SKILL.md index b47cd7f19..0e9073fca 100644 --- a/dist/opencode/skills/implement/SKILL.md +++ b/dist/opencode/skills/implement/SKILL.md @@ -92,9 +92,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -346,7 +346,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/dist/opencode/skills/implement/references/batch-orchestration.md b/dist/opencode/skills/implement/references/batch-orchestration.md index 7b69603f5..69fe524c5 100644 --- a/dist/opencode/skills/implement/references/batch-orchestration.md +++ b/dist/opencode/skills/implement/references/batch-orchestration.md @@ -2,63 +2,63 @@ ## Contents - Orchestration Options -- Batch Resolution and Wave Planning +- Batch Resolution and Dependency-Ready Scheduling - Option Handling - Batch Execution Model - Blocked-State Recovery -Detailed reference for running specs, task ranges, or task lists with dependency waves. +Detailed reference for running specs, task ranges, or task lists with dependency-ready scheduling. ## Orchestration Options | Option | Behavior | |--------|----------| -| `--dry-run` | Show dependency/wave execution plan, do not run agents | -| `--parallel` | Run tasks in the same wave concurrently (max 3 at once) | -| `--continue` | Resume a blocked orchestration from the recorded task/wave | +| `--dry-run` | Show dependency-ready execution plan, do not run agents | +| `--parallel` | Run tasks in the same dependency-ready group concurrently (max 3 at once) | +| `--continue` | Resume a blocked orchestration from the recorded task/group | | `--skip TASK-XXX` | Mark one blocked task as skipped and continue | | `--abort` | Mark orchestration as aborted and stop remaining work | -## Batch Resolution and Wave Planning +## Batch Resolution and Dependency-Ready Scheduling For `SPEC-XXX`, `TASK-XXX..YYY`, and `TASK-XXX,YYY,ZZZ`: 1. Resolve selected tasks and validate each task file exists. 2. Extract `depends_on` from each task and build a dependency graph. -3. Group tasks into dependency waves: - - Wave 1: tasks with no unresolved dependencies - - Wave N: tasks whose dependencies are completed in earlier waves -4. If `--parallel` is set, allow parallel execution only within a wave and only for non-conflicting tasks. -5. Present execution plan (tasks, waves, mode, total count) and ask for confirmation unless `--dry-run`. -6. Track progress in the journal and in task statuses: log wave boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. +3. Group tasks into dependency-ready rounds: + - First round: tasks with no unresolved dependencies + - Each subsequent round: tasks whose dependencies are completed in earlier rounds +4. If `--parallel` is set, allow parallel execution only within a dependency-ready round and only for non-conflicting tasks. +5. Present execution plan (tasks, dependency-ready rounds, mode, total count) and ask for confirmation unless `--dry-run`. +6. Track progress in the journal and in task statuses: log round boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. ## Option Handling (`--continue`, `--skip`, `--abort`) 1. Recover batch progress from the journal: `loaf journal recent --since-last-wrap` (or `loaf journal context`) plus `loaf task list --json` to see which tasks are still open. -2. If `--continue`: resume from the last logged wave and task. -3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same wave. +2. If `--continue`: resume from the last logged dependency-ready round and task. +3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same dependency-ready round. 4. If `--abort`: log `block(orchestration): aborted`, print a summary, and stop. 5. If no in-flight batch is evident from the journal, report that and ask for fresh selection input. ## Batch Execution Model -When input resolves to multiple tasks, run a wave-based loop: +When input resolves to multiple tasks, run a dependency-ready round loop: 1. Set orchestration mode (`sequential` by default, `parallel` only with `--parallel`). -2. For each wave: - - Log the wave start with `loaf journal log` +2. For each dependency-ready round: + - Log the round start with `loaf journal log` - Run each task (sequentially, or concurrently within safety limits) - For each task: set `in_progress` -> spawn agent -> run task verification -> mark `done`/`failed` via `loaf task update` 3. If any task fails verification, stop immediately and log `block(orchestration): failed `. -4. Consider a wave complete only when all its tasks are `done` or skipped. -5. Continue until all waves complete, then log a closing entry summarizing the batch. +4. Consider a round complete only when all its tasks are `done` or skipped. +5. Continue until all rounds complete, then log a closing entry summarizing the batch. ## Blocked-State Recovery When blocked, always print: - Failed task ID and title -- Wave number and current progress +- Dependency-ready round and current progress - Failure reason + key error output - Recovery commands: @@ -71,5 +71,5 @@ When blocked, always print: Use these semantics: - `--continue`: after fixes are applied, retry from the blocked task -- `--skip`: skip only the specified task and continue remaining tasks in the current wave +- `--skip`: skip only the specified task and continue remaining tasks in the current dependency-ready round - `--abort`: finalize the orchestration as aborted with no further execution diff --git a/dist/opencode/skills/implement/references/branch-and-completion.md b/dist/opencode/skills/implement/references/branch-and-completion.md index 0f715e4c5..250c8cdca 100644 --- a/dist/opencode/skills/implement/references/branch-and-completion.md +++ b/dist/opencode/skills/implement/references/branch-and-completion.md @@ -195,7 +195,7 @@ never implement through open `blockedBy`. **Print the current date and timestamp when:** - Waiting for user input or decision -- Completing a phase of work +- Completing a coherent unit of work - Encountering a blocker - Wrapping up the conversation diff --git a/dist/opencode/skills/loaf-reference/SKILL.md b/dist/opencode/skills/loaf-reference/SKILL.md index 770deae54..526ddcbeb 100644 --- a/dist/opencode/skills/loaf-reference/SKILL.md +++ b/dist/opencode/skills/loaf-reference/SKILL.md @@ -46,7 +46,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic. diff --git a/dist/opencode/skills/loaf-reference/references/command-routing.md b/dist/opencode/skills/loaf-reference/references/command-routing.md index 14a8ded99..de4f16c02 100644 --- a/dist/opencode/skills/loaf-reference/references/command-routing.md +++ b/dist/opencode/skills/loaf-reference/references/command-routing.md @@ -6,8 +6,9 @@ Which command a task needs. For exact flags, run `loaf --help`. | Intent | Route | |--------|-------| -| Shape new work | `loaf change init `, then `loaf change check` | -| Start working on a task | the implement workflow (/implement); `loaf task`/`loaf spec` stay transitional until the conversion pass — see the TRANSITIONAL note in AGENTS.md | +| Shape new bounded work | `loaf change init `, then `loaf change check` | +| Start implementing new bounded work | the implement workflow (/implement) after shaping and validating its Change | +| Continue an existing task or spec record | `loaf task` and `loaf spec` remain supported for existing records | | Continue after a restart | `loaf journal context` | | Skills or content changed | `loaf build && loaf install --to ` | | See what is in progress | `loaf task list --active` | diff --git a/dist/opencode/skills/orchestration/SKILL.md b/dist/opencode/skills/orchestration/SKILL.md index 998ed354e..942c0a6ae 100644 --- a/dist/opencode/skills/orchestration/SKILL.md +++ b/dist/opencode/skills/orchestration/SKILL.md @@ -18,7 +18,7 @@ version: 2.0.0-alpha.13 - Philosophy - Configuration - Artifact Locations -- Three-Phase Workflow +- Workflow by Lifecycle Comprehensive patterns for orchestration: coordinating multi-agent work, keeping the project journal current, running councils, delegating to specialized agents, and integrating with Linear. @@ -130,7 +130,7 @@ This skill uses paths from `.agents/loaf.json`: **Rule:** Agents write artifacts to disk, orchestrator reasons over artifacts, users retrieve from disk. -## Three-Phase Workflow +## Workflow by Lifecycle ### BEFORE (Planning) - Create/check external issue (Linear, GitHub) diff --git a/dist/opencode/skills/orchestration/references/context-management.md b/dist/opencode/skills/orchestration/references/context-management.md index 4a577309f..fd07ec254 100644 --- a/dist/opencode/skills/orchestration/references/context-management.md +++ b/dist/opencode/skills/orchestration/references/context-management.md @@ -19,7 +19,7 @@ Patterns for keeping long work resumable while using the project journal as exte Compaction is normal in long workflows. Design work that spans many exchanges so important state is already outside chat context. 1. **The journal is external memory.** Record decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. **Artifacts carry detail.** Changes, transitional tasks, reports, ADRs, and commits hold rich detail; journal entries point to them. +2. **Artifacts carry detail.** Changes, task-board records, reports, ADRs, and commits hold rich detail; journal entries point to them. 3. **Delegated work absorbs exploration.** Use delegated agents for broad investigation and return concise findings to the main context. 4. **`wrap` captures synthesis.** When meaningful work holds intentions or abandoned paths worth saving, write an optional `wrap` journal entry. @@ -36,7 +36,7 @@ Compaction is normal in long workflows. Design work that spans many exchanges so | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent branch entries after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records retained during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each returned layer includes `source_available`, `available_count`, `shown_count`, `truncated`, and `expand_command`; paginated layers also include a cursor. Treat `source_available: false` as an explicit unavailable source, never as “nothing is active.” If Change discovery is unavailable, `active-changes` and `active-lineage` are unavailable and the digest carries a diagnostic. @@ -60,7 +60,7 @@ Use `/clear` when starting a completely new task, after the previous task is com PreCompact: 1. Flush unrecorded decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. Reference Changes, transitional tasks, reports, commits, and files by stable ID or path. +2. Reference Changes, task-board records, reports, commits, and files by stable ID or path. 3. On an exact target mode with supported PreCompact delivery, let the hook nudge the flush; otherwise flush manually before compacting. PostCompact: diff --git a/dist/opencode/skills/orchestration/references/linear.md b/dist/opencode/skills/orchestration/references/linear.md index 22d55b3ce..26ba14472 100644 --- a/dist/opencode/skills/orchestration/references/linear.md +++ b/dist/opencode/skills/orchestration/references/linear.md @@ -103,7 +103,7 @@ In Linear-native mode (`integrations.linear.enabled: true`), each spec produces one parent **rollup issue** and N sub-issues under it. ``` -[SPEC-024] Agent framework alignment ← parent, label: `spec` +Agent framework alignment ← parent, label: `change` ├── Split reviewer profile into reviewer/auditor ← sub-issue, label: type/refactor ├── Harden MCP fallback path ← sub-issue, label: type/feature └── Migrate legacy task references ← sub-issue, label: type/refactor @@ -127,8 +127,8 @@ researcher). Consolidate historical profile variants and add tool-boundary tests so profiles can't drift without a test failing. ## Context -See `.agents/specs/SPEC-024-agent-framework-alignment.md` for full text, -council references, rabbit holes, and strategic tensions. +See the canonical change file in the repository for full text, council +references, rabbit holes, and strategic tensions. ## Progress Sub-issues track execution. @@ -213,7 +213,7 @@ None currently. |-------|---------| | `Working on API` | `- [ ] API implementation` | | `Done with schema` | `- [x] Schema updated` | -| `Phase 1: Discovery` | `Discovery - COMPLETE` | +| `Discovery: IN PROGRESS` | `Discovery: COMPLETE` | | `Journal entry: ...` | *(omit entirely)* | | `Council decision: ...` | *(omit entirely)* | | `Week 1 deliverables` | `Initial deliverables` | @@ -373,6 +373,6 @@ Use `scripts/suggest-team.py "task desc"` to get suggestions. ### DON'T - Use emoji in progress lists - Reference local files (sessions, councils, plans) -- Use phase/stage/week terminology +- Use numbered development-stage terminology - Include absolute file paths - Duplicate issue titles after IDs diff --git a/dist/opencode/skills/orchestration/references/local-tasks.md b/dist/opencode/skills/orchestration/references/local-tasks.md index b62d4aa2c..ad8a24254 100644 --- a/dist/opencode/skills/orchestration/references/local-tasks.md +++ b/dist/opencode/skills/orchestration/references/local-tasks.md @@ -167,7 +167,7 @@ project journal (`loaf journal recent`, `loaf journal search`). 1. Can a single specialized agent complete this? → If no, split by agent type 2. Does it touch multiple unrelated concerns? → If yes, split by concern -3. Will the agent need too much context? → If yes, split into phases +3. Will the agent need too much context? → If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? → If yes, merge back ### Agent Scope diff --git a/dist/opencode/skills/orchestration/references/parallel-agents.md b/dist/opencode/skills/orchestration/references/parallel-agents.md index dbf8a12e6..1fde9cf25 100644 --- a/dist/opencode/skills/orchestration/references/parallel-agents.md +++ b/dist/opencode/skills/orchestration/references/parallel-agents.md @@ -119,7 +119,7 @@ When streams complete: |---------|---------------------| | `/breakdown` | Identify parallelizable tasks during decomposition | | `/implement` | Single task, usually sequential | -| `/implement` | Runs dependency-wave orchestration, including parallel-safe tasks | +| `/implement` | Runs dependency-aware orchestration, including parallel-safe tasks | ## Conflict Resolution diff --git a/dist/opencode/skills/refactor-deepen/SKILL.md b/dist/opencode/skills/refactor-deepen/SKILL.md index a8803d341..e1d120b94 100644 --- a/dist/opencode/skills/refactor-deepen/SKILL.md +++ b/dist/opencode/skills/refactor-deepen/SKILL.md @@ -83,12 +83,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -149,11 +149,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -210,7 +211,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -310,7 +311,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/dist/opencode/skills/refactor-deepen/references/interface-design.md b/dist/opencode/skills/refactor-deepen/references/interface-design.md index ca6b79df1..401ffced5 100644 --- a/dist/opencode/skills/refactor-deepen/references/interface-design.md +++ b/dist/opencode/skills/refactor-deepen/references/interface-design.md @@ -1,6 +1,6 @@ # Interface Design — Parallel Sub-Agent Pattern -The INTERFACE-DESIGN phase of `/refactor-deepen` proposes the public surface +The Interface Design activity of `/refactor-deepen` proposes the public surface of a deepened module by sampling three independent design attempts and presenting all three to the user. Variety must come from sampling, not from manufactured opposition. @@ -31,10 +31,8 @@ optimizes for minimalism, Agent 2 for flexibility, Agent 3 for the common-caller path. That choice is reasonable when the agents are domain-agnostic and the orchestrator wants guaranteed surface variety. -Loaf rejects that choice. The decision is captured in -[SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md), -specifically in the Rabbit Holes and No-Gos sections (lines 96 and 107). The -short version: priming manufactures diversity rather than letting it emerge, +Loaf rejects that choice. The active rule is to use identical briefs: priming +manufactures diversity rather than letting it emerge, and manufactured diversity is dishonest signal. If the three designs do converge, the response is more agents or rerun — not priming. See [Convergence Fallback](#convergence-fallback) below. @@ -71,7 +69,7 @@ Three reasons, in order of importance: 2. **No dominant lens upfront.** Picking which constraint each agent optimizes for is itself a design decision. Doing it pre-grilling biases - the entire phase toward whatever lens the orchestrator happened to + the entire activity toward whatever lens the orchestrator happened to pick. Loaf's grilling protocol is supposed to surface tradeoffs from the codebase and the user, not from the orchestrator's pre-commitments. @@ -91,7 +89,7 @@ Justification: researcher contract: "Return findings as structured reports: summary, options (ranked with trade-offs), evidence sources, and a recommendation." See [content/agents/researcher.md](../../../agents/researcher.md). -- Read-only access matches the phase's purpose. The INTERFACE-DESIGN phase +- Read-only access matches the activity's purpose. Interface Design proposes designs; it does not implement them. Granting write access invites scope creep into "let me just sketch the implementation" and pollutes the parallel sampling. @@ -102,14 +100,14 @@ Justification: ### When `implementer` Could Be an Alternative -If the design phase needs to write probe code — a quick spike to verify +If the design activity needs to write probe code — a quick spike to verify that a proposed interface compiles against the existing call sites, for example — the `implementer` profile becomes viable. See [content/agents/implementer.md](../../../agents/implementer.md). The default remains `researcher` because: -- Probe code at this phase is rarely necessary; the deepening review +- Probe code during this activity is rarely necessary; the deepening review catches most fatal interface mistakes before code is written. - Three implementers writing probe code in parallel risks three divergent partial implementations of the same module — a merge problem the user @@ -162,7 +160,7 @@ Inside the grilling loop, after dependency classification, only when: If the interface is obvious from the dependency category and the call sites — for example, a thin adapter over a true-external dependency — -skip the parallel phase. A single proposed interface is enough. +skip parallel exploration. A single proposed interface is enough. ## Convergence Fallback @@ -172,7 +170,7 @@ implementation strategy, same tradeoffs. Two cases: 1. **Convergence is real.** The problem has a single best answer. Accept the convergence as a genuine finding and proceed to the PLAN with that single design. Note in the PLAN's "rejected alternatives" section that - the parallel phase produced no meaningful variation. + parallel exploration produced no meaningful variation. 2. **Convergence feels accidental.** The designs are suspiciously similar, the user senses a missed branch, or the briefing was so @@ -226,7 +224,7 @@ escalates on its own. ## Cost Note -A single invocation of the parallel phase is approximately **3 × +A single invocation of parallel exploration is approximately **3 × deep-exploration cost** in tokens — three sub-agents each running a full design pass against the same context. With more-agents escalation, the cost scales linearly (4 agents = ~4 ×, 5 agents = ~5 ×). @@ -235,10 +233,10 @@ This pattern is **opt-in inside the grilling loop**. It is not auto-triggered on every `/refactor-deepen` invocation. The 3-agent default is the cost ceiling for the default settings — the skill does not scale agent count silently. If a candidate's interface is obvious, skip the -phase entirely and propose a single design. +activity entirely and propose a single design. The cost is an explicit tradeoff the user accepts when they enter the -INTERFACE-DESIGN phase for a non-obvious interface. The skill should +Interface Design activity for a non-obvious interface. The skill should surface the cost briefly before spawning: > Spawning 3 design agents in parallel (~3 × token cost). Proceed? @@ -265,7 +263,7 @@ After the three sub-agents return: | Don't | Do Instead | |-------|------------| | Prime agents with opposing constraints by default | Use identical briefs; let sampling produce variety | -| Auto-trigger the parallel phase on every invocation | Invoke only when interface is non-obvious | +| Auto-trigger parallel exploration on every invocation | Invoke only when interface is non-obvious | | Use `implementer` profile for design sub-agents | Use `researcher`; switch to `implementer` only on explicit user request | | Add a "lens" to the brief silently | Surface the tradeoff to the user before priming | | Pre-rank the three designs in the output | Present in arbitrary order, let the user pick | @@ -283,6 +281,3 @@ After the three sub-agents return: agent profile for design sub-agents - [content/agents/implementer.md](../../../agents/implementer.md) — Alternative profile when probe code is needed -- [SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md) - — The shape decision (lines 64, 96, 107, 117) that established the - identical-brief default diff --git a/dist/opencode/skills/refactor-deepen/templates/plan.md b/dist/opencode/skills/refactor-deepen/templates/plan.md index 54a591e61..f564229a3 100644 --- a/dist/opencode/skills/refactor-deepen/templates/plan.md +++ b/dist/opencode/skills/refactor-deepen/templates/plan.md @@ -27,7 +27,7 @@ write a new file rather than updating an existing one. |-------|----------|-------| | `title` | Yes | One-line description of the deepening, not the candidate name | | `created` | Yes | ISO 8601 UTC, e.g. `2026-05-02T01:30:00Z` (must match the filename timestamp) | -| `status` | Yes | `drafting` on first write — lifecycle states are deferred to a follow-up spec | +| `status` | Yes | `drafting` on first write; this template does not define additional lifecycle states | | `spec` | Yes | `SPEC-NNN` if the plan is scoped under a spec; `null` otherwise (do not omit the key) | | `related` | No | List of related artifact IDs (`ADR-*`, `SPEC-*`, idea filenames, other plan filenames) | @@ -36,8 +36,7 @@ identity, mirroring councils and ideas. ## Required Sections -The five sections below are the *minimal shape* defined in SPEC-034. Order is -load-bearing: each section assumes the previous one is settled. Do not reorder. +The five sections below are the *minimal shape* for a PLAN. Order is load-bearing: each section assumes the previous one is settled. Do not reorder. 1. **Candidate** — what's being considered for deepening. Name the **module** verbatim (use the canonical glossary term — run `loaf kb glossary check` @@ -111,14 +110,12 @@ proportional to actual usage, matching how `.agents/specs/` behaves. ## Linear-Native Mode: Fail Fast -PLAN files are **local-only storage**. Per SPEC-034 line 81, write commands -must fail fast in Linear-native mode rather than silently degrade. The -consuming skill (`/refactor-deepen`) is responsible for: +PLAN files are **local-only storage**. Write commands must fail fast in Linear-native mode rather than silently degrade. The consuming skill (`/refactor-deepen`) is responsible for: 1. Reading `.agents/loaf.json` and checking `integrations.linear.enabled`. 2. If true: aborting before `mkdir -p .agents/plans` and before any write, with the verbatim error - `"Linear-native plan storage pending artifact-taxonomy spec — local mode only for now."` + `"Linear-native plan storage unavailable — continuing with a read-only report."` 3. If false: proceeding with the write as documented above. This template intentionally does **not** wrap the write in a diff --git a/dist/opencode/skills/research/SKILL.md b/dist/opencode/skills/research/SKILL.md index a9613e72e..be4c8c928 100644 --- a/dist/opencode/skills/research/SKILL.md +++ b/dist/opencode/skills/research/SKILL.md @@ -145,3 +145,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/skills/shape/SKILL.md b/dist/opencode/skills/shape/SKILL.md index db12231e6..2903d80b2 100644 --- a/dist/opencode/skills/shape/SKILL.md +++ b/dist/opencode/skills/shape/SKILL.md @@ -165,3 +165,7 @@ Offer to push the branch and open a draft PR, using [the PR template](templates/ | Decomposition | [references/decomposition.md](references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/opencode/skills/shape/references/cli-boundary.md b/dist/opencode/skills/shape/references/cli-boundary.md index efb3cc1b5..7f5816b03 100644 --- a/dist/opencode/skills/shape/references/cli-boundary.md +++ b/dist/opencode/skills/shape/references/cli-boundary.md @@ -13,7 +13,7 @@ Folder resolution: an explicit `[folder]` argument always wins; otherwise the cu Output splits into two tiers: - **Violations** — always fail (exit code 2), regardless of flags: status-like frontmatter keys (`readiness`, `status`, `state`) or values matching the canonical change-state vocabulary; frontmatter not opening the file at byte one; malformed `YYYYMMDD-slug` folder naming; identity mismatch between `change:`/`created:` and the folder name; missing Product Contract sections (Problem, Hypothesis, Scope, Observable Workflow, Rabbit Holes and No-Gos). -- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A shaping-stage Change with open gaps is valid; the report just says what's still missing. +- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A Change with open gaps is incomplete and non-executable; the report just says what's still missing. `--require-executable` turns structural executability into a gate (exit code 1 if not structurally executable); it does not prove implementation completion. This is implement's preflight and CI's non-draft-PR check, not something shape itself passes during shaping. diff --git a/dist/opencode/skills/shape/references/decomposition.md b/dist/opencode/skills/shape/references/decomposition.md index edf38530b..5ffefbe74 100644 --- a/dist/opencode/skills/shape/references/decomposition.md +++ b/dist/opencode/skills/shape/references/decomposition.md @@ -4,7 +4,7 @@ Shaping step absorbed from the retired breakdown skill: dependency awareness, gr ## What Survives -- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into phases. Are you splitting just to have more units? If yes, merge back. +- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into smaller coherent units. Are you splitting just to have more units? If yes, merge back. - **Right-sizing rules** — one agent type per unit (completable by a single implementer), one concern per unit (one layer, service, or component), context-appropriate (fits in model context with room for exploration), not over-fragmented (don't split what naturally belongs together). - **Per-unit verification discipline** — every unit includes its own observable done condition. Never a separate "verify" unit; keep tests with the code they test. - **Own the decisions** — decide granularity and unit boundaries autonomously. Ask the user only when two orderings are genuinely equally valid with different trade-offs; otherwise decide and move on. diff --git a/dist/skills/architecture/SKILL.md b/dist/skills/architecture/SKILL.md index 962412e61..4e5b6f877 100644 --- a/dist/skills/architecture/SKILL.md +++ b/dist/skills/architecture/SKILL.md @@ -42,7 +42,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/dist/skills/bootstrap/SKILL.md b/dist/skills/bootstrap/SKILL.md index 1a497c096..6157004ee 100644 --- a/dist/skills/bootstrap/SKILL.md +++ b/dist/skills/bootstrap/SKILL.md @@ -217,7 +217,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -226,14 +226,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -243,9 +243,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/dist/skills/bootstrap/references/interview-guide.md b/dist/skills/bootstrap/references/interview-guide.md index ad67e1947..3313798f0 100644 --- a/dist/skills/bootstrap/references/interview-guide.md +++ b/dist/skills/bootstrap/references/interview-guide.md @@ -5,10 +5,10 @@ A structured interview framework for helping builders go from a vague idea to a ## Contents - How This Guide Works - Framework Foundations -- Phase 1: Excavation (The Spark) -- Phase 2: Sharpening (The Shape) -- Phase 3: Grounding (The Architecture) -- Phase 4: Synthesis (The Documents) +- Excavation (The Spark) +- Sharpening (The Shape) +- Grounding (The Architecture) +- Synthesis (The Documents) - Adapting Interview Depth - Anti-Patterns - Transitioning to Document Drafting @@ -17,16 +17,16 @@ A structured interview framework for helping builders go from a vague idea to a This is a **builder interview**, not a user research interview. The interviewer (the agent) is helping the builder crystallize their own thinking -- not extracting requirements from a stakeholder. The builder has context, intuition, and taste that need to be surfaced, challenged, and structured. -The interview flows through four phases, each producing progressively sharper artifacts: +The interview flows through four sections, each producing progressively sharper artifacts: -| Phase | Focus | Primary Output | Frameworks | +| Section | Focus | Primary Output | Frameworks | |-------|-------|----------------|------------| -| 1. Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | -| 2. Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | -| 3. Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | -| 4. Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | +| Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | +| Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | +| Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | +| Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | -Phases are not rigid walls. A strong answer in Phase 1 might skip half of Phase 2. A weak answer in Phase 2 might loop back to Phase 1. Follow the energy. +Sections are not rigid walls. A strong answer in Excavation might skip half of Sharpening. A weak answer in Sharpening might loop back to Excavation. Follow the energy. --- @@ -80,7 +80,7 @@ What each framework contributes and what to skip. **What to skip:** Customer interview logistics, meeting scheduling advice. The Mom Test is about question quality, not interview operations. -**Connection to documents:** Informs the quality of every answer in every phase. The Mom Test isn't a phase -- it's a lens applied to ALL questioning. It keeps the interview honest. +**Connection to documents:** Informs the quality of every answer in every section. The Mom Test isn't a section -- it's a lens applied to ALL questioning. It keeps the interview honest. ### Design Sprint - Understand Phase (Google Ventures) @@ -120,7 +120,7 @@ What each framework contributes and what to skip. --- -## Phase 1: Excavation (The Spark) +## Excavation (The Spark) **Goal:** Understand what exists, why it matters, and whether the problem is real. @@ -157,9 +157,9 @@ The builder's own experience with the problem is the richest source of insight. - "Have you seen anyone spend money or significant time on this problem?" *(Mom Test: evidence of pain)* - "Is this problem getting worse or better over time? Why?" *(Wardley: movement awareness)* -### Phase 1 Signals +### Excavation Signals -**Strong signal (move to Phase 2):** Builder can describe a specific person with a specific problem and knows what they do about it today. +**Strong signal (move to Sharpening):** Builder can describe a specific person with a specific problem and knows what they do about it today. **Weak signal (dig deeper):** Builder describes a category ("developers need better tools") without specifics. Ask for a story: "Tell me about a specific moment when this problem was most painful." @@ -167,13 +167,13 @@ The builder's own experience with the problem is the richest source of insight. --- -## Phase 2: Sharpening (The Shape) +## Sharpening (The Shape) **Goal:** Define who this is for, what it does, and -- critically -- what it does NOT do. Set complexity and boundaries. -**Mood:** Constructive pressure. Phase 1 was expansive; Phase 2 is reductive. The builder will want to include everything. Your job is to help them cut. +**Mood:** Constructive pressure. Excavation was expansive; Sharpening is reductive. The builder will want to include everything. Your job is to help them cut. -**Duration:** This is typically the longest phase. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. +**Duration:** This is typically the longest section. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. ### Must-Ask Questions @@ -210,17 +210,17 @@ Surface the riskiest assumptions. "Will users actually switch from their current - "How might we make [the hardest part] effortless?" *(Design Sprint: HMW)* - "What would definitely make this fail?" *(First Principles: inversion)* -### Phase 2 Signals +### Sharpening Signals -**Strong signal (move to Phase 3):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. +**Strong signal (move to Grounding):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. **Weak signal (iterate):** Builder keeps expanding scope. "It should also..." is a signal to tighten. Ask: "If you could only do ONE thing, what would it be?" -**Red flag (loop back to Phase 1):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" +**Red flag (loop back to Excavation):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" --- -## Phase 3: Grounding (The Architecture) +## Grounding (The Architecture) **Goal:** Establish technical direction, identify what to build vs. buy, and surface hidden complexity. @@ -257,19 +257,19 @@ These become the rabbit holes in the spec. The builder often knows where the dra - "If you had to ship something in one week, what would you cut?" *(Shape Up: scope pressure test)* - "Are there regulatory, legal, or compliance considerations?" *(Often forgotten at 0-to-1)* -### Phase 3 Signals +### Grounding Signals -**Strong signal (move to Phase 4):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. +**Strong signal (move to Synthesis):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. **Weak signal (iterate):** Builder wants to build everything from scratch. Challenge: "What's the thing ONLY YOU can build? Build that. Use existing solutions for the rest." -**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Phase 3 and note that ARCHITECTURE.md will be populated later when technical decisions are made. +**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Grounding and note that ARCHITECTURE.md will be populated later when technical decisions are made. --- -## Phase 4: Synthesis (The Documents) +## Synthesis (The Documents) -**Goal:** Transform interview insights into draft documents. This is NOT a phase of the interview -- it's the transition from interviewing to drafting. +**Goal:** Transform interview insights into draft documents. This is NOT an interview section -- it's the transition from interviewing to drafting. **Mood:** Collaborative, iterative. The agent drafts, the builder reacts and refines. @@ -319,11 +319,11 @@ Allow the builder to approve all remaining sections at once if they're satisfied ## Adapting Interview Depth -The interview adapts to three contexts, per SPEC-013's mode detection: +The interview adapts to three contexts based on the detected project mode: ### Greenfield + Empty (Full Interview) -Run all four phases in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all phases. This is where the interview guide earns its keep. +Run all four sections in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all sections. This is where the interview guide earns its keep. **Key adaptation:** Be patient. The builder may circle back, contradict themselves, or get stuck. That's normal. Let them think out loud. Silence after a question is productive, not awkward. @@ -332,9 +332,9 @@ Run all four phases in full. The builder has minimal clarity and needs the most Read and analyze the brief first. Then run a compressed interview that: - Confirms understanding ("Here's what I extracted -- is this right?") - Challenges assumptions ("Your brief says X, but have you considered Y?") -- Fills gaps (which phases have missing information?) +- Fills gaps (which sections have missing information?) -Expect 8-12 questions total, concentrated in whichever phases the brief is weakest. +Expect 8-12 questions total, concentrated in whichever sections the brief is weakest. **Key adaptation:** Don't re-ask what the brief already answers well. Quote the brief back and ask "Is this still accurate?" to confirm, then move to gaps. @@ -345,7 +345,7 @@ The project exists. Code exists. Docs may exist. The interview focuses on: - What the builder wants to CHANGE (current pain, technical debt, strategic shifts) - What conventions and preferences exist but aren't documented -Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered by the existing codebase. +Expect 6-10 questions total, mostly in Excavation and Sharpening. Grounding is largely answered by the existing codebase. **Key adaptation:** Show the builder what you learned from their code. "I see a Python/FastAPI project with PostgreSQL and Docker. The test suite uses pytest. Is that the intended stack going forward?" Let the codebase speak first, then fill gaps. @@ -361,13 +361,13 @@ Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered b **The Therapist.** "And how does that make you feel about your product?" No. This is a builder interview, not a feelings exploration. Emotions matter (JTBD switching forces), but ask about user emotions, not builder emotions. -**Premature Architecture.** Jumping to "What database should we use?" in Phase 1. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. +**Premature Architecture.** Jumping to "What database should we use?" during Excavation. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. **The Echo Chamber.** Reflecting back everything the builder says without challenging anything. The Mom Test exists because people are too polite. Be constructive, not agreeable. "That's a big scope. Are you sure you need ALL of that for v1?" **Solution-First Questioning.** "What features should it have?" is the wrong question. "What job does it do for the user?" is the right one. Features are an output of the interview, not an input. -**Asking for Permission to Proceed.** Don't ask "Should we move to the next phase?" Just move when the signals are strong. If the builder has more to say, they'll say it. +**Asking for Permission to Proceed.** Don't ask "Should we move to the next section?" Just move when the signals are strong. If the builder has more to say, they'll say it. **Over-Indexing on Frameworks.** Don't say "Let's do a JTBD analysis" or "Let me apply Wardley Mapping here." The frameworks are lenses for the interviewer, not vocabulary for the builder. Just ask good questions. @@ -413,12 +413,12 @@ The bootstrap interview creates the foundation. Other skills deepen specific are ## Framework Attribution -| Framework | Primary Contribution | Phase(s) | +| Framework | Primary Contribution | Section(s) | |-----------|---------------------|----------| -| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | 2, 3 | -| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | 1, 2 | -| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | 1, 2 | -| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All phases | -| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | 2, 3 | -| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | 3 | -| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | 1, 3 | +| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | Sharpening, Grounding | +| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | Excavation, Sharpening | +| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | Excavation, Sharpening | +| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All sections | +| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | Sharpening, Grounding | +| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | Grounding | +| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | Excavation, Grounding | diff --git a/dist/skills/breakdown/SKILL.md b/dist/skills/breakdown/SKILL.md index de7bfbd85..a299eb180 100644 --- a/dist/skills/breakdown/SKILL.md +++ b/dist/skills/breakdown/SKILL.md @@ -88,7 +88,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/dist/skills/foundations/SKILL.md b/dist/skills/foundations/SKILL.md index 1bc09d9ef..f6732be53 100644 --- a/dist/skills/foundations/SKILL.md +++ b/dist/skills/foundations/SKILL.md @@ -113,6 +113,22 @@ Engineering foundations for consistent, high-quality code. | Constants | `UPPER_SNAKE` | `UPPER_SNAKE` | | Tests | `test___` | `describe/it` blocks | +### Artifact Names Never Cite Their Work Unit + +Name an artifact for what it is, never for the work unit that produced it. The directory or Change that contains it already records that provenance, so repeating it in the filename inverts the reference and rots the moment the work closes: a work unit points at its artifacts, artifacts never point back. + +| Instead of | Write | +|------------|-------| +| `u8-claude-smoke.mjs` | `smoke-claude-code-startup.mjs` | +| `report-spec-053-taxonomy-signoff.md` | `taxonomy-signoff.md` | +| `TASK-074-sidecar-audit-report.md` | `sidecar-audit.md` | + +Provenance belongs in a front-matter field such as `source:`, where it can be read and updated, not in a name that has to be renamed to stay true. + +Two look-alikes are correct and stay. A **version** is identity, not reference: `claude-code-2.1.218-plugin-startup-smoke.json`. A **timestamp** records when, not which work unit: `20260620-214448-skills-audit.md`. And a numbered record living in the directory that owns it *is* that entity, so `.agents/specs/SPEC-042-slug.md` and `docs/decisions/ADR-007-slug.md` are its own name rather than a citation. + +`loaf check --hook artifact-names` enforces this at commit time over tracked artifacts, grandfathering anything already `final` or `archived`. + ## Test Patterns Scenario-based fixture naming: diff --git a/dist/skills/git-workflow/references/commits.md b/dist/skills/git-workflow/references/commits.md index 5ed2ba9e1..d6a48ab9b 100644 --- a/dist/skills/git-workflow/references/commits.md +++ b/dist/skills/git-workflow/references/commits.md @@ -185,7 +185,7 @@ Internal terms that have no meaning outside the team's working context: - Spec IDs and task IDs (`SPEC-024`, `TASK-042`) - Session, sprint, or branch references - Internal terminology from skills/docs that isn't part of the user's mental model — e.g. `Q1`/`Q2`/`Q3` question numbers from a Triage Gate, internal gate-logic notation like `(Q1 OR Q2) AND Q3`, hook IDs that aren't user-facing -- "How the work got done" framing — interview steps, breakdown phases, review gates +- "How the work got done" framing — interview steps, breakdown steps, review gates ### Keep @@ -252,7 +252,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE] Four hooks automatically enforce the conventions documented in this file: -| Hook | Phase | Behavior | +| Hook | Timing | Behavior | |------|-------|----------| | `github-account` | Pre-tool (Bash) | Force-switch: switches the active `gh` account to the configured one before `gh` commands run (passes with a warning), exempting `gh auth` administration, and blocks only when the switch fails. It writes the shared global account pointer on every mismatched `gh` call -- read-only ones included -- so concurrent sessions on different identities collide on that pointer more often. | | `workflow-pre-pr` | Pre-tool (Bash) | Advisory: reminds about CHANGELOG [Unreleased] entries and PR format. Non-blocking. | @@ -269,26 +269,14 @@ BREAKING CHANGE: Description of breaking change. ### Pre-Release Versions -When developing toward a major version, use pre-release suffixes to mark development milestones: - -``` -2.0.0-dev.0 → dev.1 → dev.2 → ... → 2.0.0 - ↑ ↑ ↑ ↑ - start dev milestone milestone stable release -``` - | Suffix | Meaning | When to use | |--------|---------|-------------| -| `-dev.N` | Development milestone | Active development toward a target version | | `-alpha.N` | Alpha pre-release | Feature-complete but untested broadly | | `-beta.N` | Beta pre-release | Testing with wider audience | | `-rc.N` | Release candidate | Final validation before stable | **Convention:** -- Set the target version with `-dev.0` when starting a major effort (e.g. `2.0.0-dev.0`) -- Bump the dev counter (`-dev.N` → `-dev.N+1`) when a meaningful batch of landed work is ready to publish — a completed spec, a related feature group, or a release train -- Don't bump for every commit — that's what git history is for -- Strip the suffix (`-dev.N` → `2.0.0`) when all planned work is complete +- Use standard SemVer pre-release identifiers (`alpha`, `beta`, or `rc`) when publishing pre-release versions. - `loaf release` handles all bump types: `prerelease`, `release`, `major`, `minor`, `patch` -**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects with multi-milestone development cycles. +**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects publishing staged pre-releases before stable releases. diff --git a/dist/skills/handoff/SKILL.md b/dist/skills/handoff/SKILL.md index f0991fe68..b8610afb9 100644 --- a/dist/skills/handoff/SKILL.md +++ b/dist/skills/handoff/SKILL.md @@ -119,3 +119,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/skills/housekeeping/SKILL.md b/dist/skills/housekeeping/SKILL.md index 5a9f45a1a..4830f2075 100644 --- a/dist/skills/housekeeping/SKILL.md +++ b/dist/skills/housekeeping/SKILL.md @@ -137,3 +137,7 @@ After housekeeping, suggest `/reflect` if the session produced key decisions or | Report Template | [templates/report.md](templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/skills/implement/SKILL.md b/dist/skills/implement/SKILL.md index c5b4c96e0..780e70ebe 100644 --- a/dist/skills/implement/SKILL.md +++ b/dist/skills/implement/SKILL.md @@ -90,9 +90,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -344,7 +344,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/dist/skills/implement/references/batch-orchestration.md b/dist/skills/implement/references/batch-orchestration.md index 7b69603f5..69fe524c5 100644 --- a/dist/skills/implement/references/batch-orchestration.md +++ b/dist/skills/implement/references/batch-orchestration.md @@ -2,63 +2,63 @@ ## Contents - Orchestration Options -- Batch Resolution and Wave Planning +- Batch Resolution and Dependency-Ready Scheduling - Option Handling - Batch Execution Model - Blocked-State Recovery -Detailed reference for running specs, task ranges, or task lists with dependency waves. +Detailed reference for running specs, task ranges, or task lists with dependency-ready scheduling. ## Orchestration Options | Option | Behavior | |--------|----------| -| `--dry-run` | Show dependency/wave execution plan, do not run agents | -| `--parallel` | Run tasks in the same wave concurrently (max 3 at once) | -| `--continue` | Resume a blocked orchestration from the recorded task/wave | +| `--dry-run` | Show dependency-ready execution plan, do not run agents | +| `--parallel` | Run tasks in the same dependency-ready group concurrently (max 3 at once) | +| `--continue` | Resume a blocked orchestration from the recorded task/group | | `--skip TASK-XXX` | Mark one blocked task as skipped and continue | | `--abort` | Mark orchestration as aborted and stop remaining work | -## Batch Resolution and Wave Planning +## Batch Resolution and Dependency-Ready Scheduling For `SPEC-XXX`, `TASK-XXX..YYY`, and `TASK-XXX,YYY,ZZZ`: 1. Resolve selected tasks and validate each task file exists. 2. Extract `depends_on` from each task and build a dependency graph. -3. Group tasks into dependency waves: - - Wave 1: tasks with no unresolved dependencies - - Wave N: tasks whose dependencies are completed in earlier waves -4. If `--parallel` is set, allow parallel execution only within a wave and only for non-conflicting tasks. -5. Present execution plan (tasks, waves, mode, total count) and ask for confirmation unless `--dry-run`. -6. Track progress in the journal and in task statuses: log wave boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. +3. Group tasks into dependency-ready rounds: + - First round: tasks with no unresolved dependencies + - Each subsequent round: tasks whose dependencies are completed in earlier rounds +4. If `--parallel` is set, allow parallel execution only within a dependency-ready round and only for non-conflicting tasks. +5. Present execution plan (tasks, dependency-ready rounds, mode, total count) and ask for confirmation unless `--dry-run`. +6. Track progress in the journal and in task statuses: log round boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. ## Option Handling (`--continue`, `--skip`, `--abort`) 1. Recover batch progress from the journal: `loaf journal recent --since-last-wrap` (or `loaf journal context`) plus `loaf task list --json` to see which tasks are still open. -2. If `--continue`: resume from the last logged wave and task. -3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same wave. +2. If `--continue`: resume from the last logged dependency-ready round and task. +3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same dependency-ready round. 4. If `--abort`: log `block(orchestration): aborted`, print a summary, and stop. 5. If no in-flight batch is evident from the journal, report that and ask for fresh selection input. ## Batch Execution Model -When input resolves to multiple tasks, run a wave-based loop: +When input resolves to multiple tasks, run a dependency-ready round loop: 1. Set orchestration mode (`sequential` by default, `parallel` only with `--parallel`). -2. For each wave: - - Log the wave start with `loaf journal log` +2. For each dependency-ready round: + - Log the round start with `loaf journal log` - Run each task (sequentially, or concurrently within safety limits) - For each task: set `in_progress` -> spawn agent -> run task verification -> mark `done`/`failed` via `loaf task update` 3. If any task fails verification, stop immediately and log `block(orchestration): failed `. -4. Consider a wave complete only when all its tasks are `done` or skipped. -5. Continue until all waves complete, then log a closing entry summarizing the batch. +4. Consider a round complete only when all its tasks are `done` or skipped. +5. Continue until all rounds complete, then log a closing entry summarizing the batch. ## Blocked-State Recovery When blocked, always print: - Failed task ID and title -- Wave number and current progress +- Dependency-ready round and current progress - Failure reason + key error output - Recovery commands: @@ -71,5 +71,5 @@ When blocked, always print: Use these semantics: - `--continue`: after fixes are applied, retry from the blocked task -- `--skip`: skip only the specified task and continue remaining tasks in the current wave +- `--skip`: skip only the specified task and continue remaining tasks in the current dependency-ready round - `--abort`: finalize the orchestration as aborted with no further execution diff --git a/dist/skills/implement/references/branch-and-completion.md b/dist/skills/implement/references/branch-and-completion.md index 0f715e4c5..250c8cdca 100644 --- a/dist/skills/implement/references/branch-and-completion.md +++ b/dist/skills/implement/references/branch-and-completion.md @@ -195,7 +195,7 @@ never implement through open `blockedBy`. **Print the current date and timestamp when:** - Waiting for user input or decision -- Completing a phase of work +- Completing a coherent unit of work - Encountering a blocker - Wrapping up the conversation diff --git a/dist/skills/loaf-reference/SKILL.md b/dist/skills/loaf-reference/SKILL.md index 4ed664714..3a5baec27 100644 --- a/dist/skills/loaf-reference/SKILL.md +++ b/dist/skills/loaf-reference/SKILL.md @@ -45,7 +45,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic. diff --git a/dist/skills/loaf-reference/references/command-routing.md b/dist/skills/loaf-reference/references/command-routing.md index 60754c391..de4f16c02 100644 --- a/dist/skills/loaf-reference/references/command-routing.md +++ b/dist/skills/loaf-reference/references/command-routing.md @@ -6,8 +6,9 @@ Which command a task needs. For exact flags, run `loaf --help`. | Intent | Route | |--------|-------| -| Shape new work | `loaf change init `, then `loaf change check` | -| Start working on a task | the implement workflow (/implement); `loaf task`/`loaf spec` stay transitional until the conversion pass — see the TRANSITIONAL note in CLAUDE.md | +| Shape new bounded work | `loaf change init `, then `loaf change check` | +| Start implementing new bounded work | the implement workflow (/implement) after shaping and validating its Change | +| Continue an existing task or spec record | `loaf task` and `loaf spec` remain supported for existing records | | Continue after a restart | `loaf journal context` | | Skills or content changed | `loaf build && loaf install --to ` | | See what is in progress | `loaf task list --active` | diff --git a/dist/skills/orchestration/SKILL.md b/dist/skills/orchestration/SKILL.md index 6a798cb50..811ca336c 100644 --- a/dist/skills/orchestration/SKILL.md +++ b/dist/skills/orchestration/SKILL.md @@ -17,7 +17,7 @@ description: >- - Philosophy - Configuration - Artifact Locations -- Three-Phase Workflow +- Workflow by Lifecycle Comprehensive patterns for orchestration: coordinating multi-agent work, keeping the project journal current, running councils, delegating to specialized agents, and integrating with Linear. @@ -129,7 +129,7 @@ This skill uses paths from `.agents/loaf.json`: **Rule:** Agents write artifacts to disk, orchestrator reasons over artifacts, users retrieve from disk. -## Three-Phase Workflow +## Workflow by Lifecycle ### BEFORE (Planning) - Create/check external issue (Linear, GitHub) diff --git a/dist/skills/orchestration/references/context-management.md b/dist/skills/orchestration/references/context-management.md index 4a577309f..fd07ec254 100644 --- a/dist/skills/orchestration/references/context-management.md +++ b/dist/skills/orchestration/references/context-management.md @@ -19,7 +19,7 @@ Patterns for keeping long work resumable while using the project journal as exte Compaction is normal in long workflows. Design work that spans many exchanges so important state is already outside chat context. 1. **The journal is external memory.** Record decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. **Artifacts carry detail.** Changes, transitional tasks, reports, ADRs, and commits hold rich detail; journal entries point to them. +2. **Artifacts carry detail.** Changes, task-board records, reports, ADRs, and commits hold rich detail; journal entries point to them. 3. **Delegated work absorbs exploration.** Use delegated agents for broad investigation and return concise findings to the main context. 4. **`wrap` captures synthesis.** When meaningful work holds intentions or abandoned paths worth saving, write an optional `wrap` journal entry. @@ -36,7 +36,7 @@ Compaction is normal in long workflows. Design work that spans many exchanges so | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent branch entries after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records retained during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each returned layer includes `source_available`, `available_count`, `shown_count`, `truncated`, and `expand_command`; paginated layers also include a cursor. Treat `source_available: false` as an explicit unavailable source, never as “nothing is active.” If Change discovery is unavailable, `active-changes` and `active-lineage` are unavailable and the digest carries a diagnostic. @@ -60,7 +60,7 @@ Use `/clear` when starting a completely new task, after the previous task is com PreCompact: 1. Flush unrecorded decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. Reference Changes, transitional tasks, reports, commits, and files by stable ID or path. +2. Reference Changes, task-board records, reports, commits, and files by stable ID or path. 3. On an exact target mode with supported PreCompact delivery, let the hook nudge the flush; otherwise flush manually before compacting. PostCompact: diff --git a/dist/skills/orchestration/references/linear.md b/dist/skills/orchestration/references/linear.md index 22d55b3ce..26ba14472 100644 --- a/dist/skills/orchestration/references/linear.md +++ b/dist/skills/orchestration/references/linear.md @@ -103,7 +103,7 @@ In Linear-native mode (`integrations.linear.enabled: true`), each spec produces one parent **rollup issue** and N sub-issues under it. ``` -[SPEC-024] Agent framework alignment ← parent, label: `spec` +Agent framework alignment ← parent, label: `change` ├── Split reviewer profile into reviewer/auditor ← sub-issue, label: type/refactor ├── Harden MCP fallback path ← sub-issue, label: type/feature └── Migrate legacy task references ← sub-issue, label: type/refactor @@ -127,8 +127,8 @@ researcher). Consolidate historical profile variants and add tool-boundary tests so profiles can't drift without a test failing. ## Context -See `.agents/specs/SPEC-024-agent-framework-alignment.md` for full text, -council references, rabbit holes, and strategic tensions. +See the canonical change file in the repository for full text, council +references, rabbit holes, and strategic tensions. ## Progress Sub-issues track execution. @@ -213,7 +213,7 @@ None currently. |-------|---------| | `Working on API` | `- [ ] API implementation` | | `Done with schema` | `- [x] Schema updated` | -| `Phase 1: Discovery` | `Discovery - COMPLETE` | +| `Discovery: IN PROGRESS` | `Discovery: COMPLETE` | | `Journal entry: ...` | *(omit entirely)* | | `Council decision: ...` | *(omit entirely)* | | `Week 1 deliverables` | `Initial deliverables` | @@ -373,6 +373,6 @@ Use `scripts/suggest-team.py "task desc"` to get suggestions. ### DON'T - Use emoji in progress lists - Reference local files (sessions, councils, plans) -- Use phase/stage/week terminology +- Use numbered development-stage terminology - Include absolute file paths - Duplicate issue titles after IDs diff --git a/dist/skills/orchestration/references/local-tasks.md b/dist/skills/orchestration/references/local-tasks.md index e39cf7a68..c8e975136 100644 --- a/dist/skills/orchestration/references/local-tasks.md +++ b/dist/skills/orchestration/references/local-tasks.md @@ -167,7 +167,7 @@ project journal (`loaf journal recent`, `loaf journal search`). 1. Can a single specialized agent complete this? → If no, split by agent type 2. Does it touch multiple unrelated concerns? → If yes, split by concern -3. Will the agent need too much context? → If yes, split into phases +3. Will the agent need too much context? → If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? → If yes, merge back ### Agent Scope diff --git a/dist/skills/orchestration/references/parallel-agents.md b/dist/skills/orchestration/references/parallel-agents.md index 63cb39340..5fbec2b93 100644 --- a/dist/skills/orchestration/references/parallel-agents.md +++ b/dist/skills/orchestration/references/parallel-agents.md @@ -119,7 +119,7 @@ When streams complete: |---------|---------------------| | `/breakdown` | Identify parallelizable tasks during decomposition | | `/implement` | Single task, usually sequential | -| `/implement` | Runs dependency-wave orchestration, including parallel-safe tasks | +| `/implement` | Runs dependency-aware orchestration, including parallel-safe tasks | ## Conflict Resolution diff --git a/dist/skills/refactor-deepen/SKILL.md b/dist/skills/refactor-deepen/SKILL.md index d59db29a4..5d41d685f 100644 --- a/dist/skills/refactor-deepen/SKILL.md +++ b/dist/skills/refactor-deepen/SKILL.md @@ -82,12 +82,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -148,11 +148,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -209,7 +210,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -309,7 +310,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/dist/skills/refactor-deepen/references/interface-design.md b/dist/skills/refactor-deepen/references/interface-design.md index ca6b79df1..401ffced5 100644 --- a/dist/skills/refactor-deepen/references/interface-design.md +++ b/dist/skills/refactor-deepen/references/interface-design.md @@ -1,6 +1,6 @@ # Interface Design — Parallel Sub-Agent Pattern -The INTERFACE-DESIGN phase of `/refactor-deepen` proposes the public surface +The Interface Design activity of `/refactor-deepen` proposes the public surface of a deepened module by sampling three independent design attempts and presenting all three to the user. Variety must come from sampling, not from manufactured opposition. @@ -31,10 +31,8 @@ optimizes for minimalism, Agent 2 for flexibility, Agent 3 for the common-caller path. That choice is reasonable when the agents are domain-agnostic and the orchestrator wants guaranteed surface variety. -Loaf rejects that choice. The decision is captured in -[SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md), -specifically in the Rabbit Holes and No-Gos sections (lines 96 and 107). The -short version: priming manufactures diversity rather than letting it emerge, +Loaf rejects that choice. The active rule is to use identical briefs: priming +manufactures diversity rather than letting it emerge, and manufactured diversity is dishonest signal. If the three designs do converge, the response is more agents or rerun — not priming. See [Convergence Fallback](#convergence-fallback) below. @@ -71,7 +69,7 @@ Three reasons, in order of importance: 2. **No dominant lens upfront.** Picking which constraint each agent optimizes for is itself a design decision. Doing it pre-grilling biases - the entire phase toward whatever lens the orchestrator happened to + the entire activity toward whatever lens the orchestrator happened to pick. Loaf's grilling protocol is supposed to surface tradeoffs from the codebase and the user, not from the orchestrator's pre-commitments. @@ -91,7 +89,7 @@ Justification: researcher contract: "Return findings as structured reports: summary, options (ranked with trade-offs), evidence sources, and a recommendation." See [content/agents/researcher.md](../../../agents/researcher.md). -- Read-only access matches the phase's purpose. The INTERFACE-DESIGN phase +- Read-only access matches the activity's purpose. Interface Design proposes designs; it does not implement them. Granting write access invites scope creep into "let me just sketch the implementation" and pollutes the parallel sampling. @@ -102,14 +100,14 @@ Justification: ### When `implementer` Could Be an Alternative -If the design phase needs to write probe code — a quick spike to verify +If the design activity needs to write probe code — a quick spike to verify that a proposed interface compiles against the existing call sites, for example — the `implementer` profile becomes viable. See [content/agents/implementer.md](../../../agents/implementer.md). The default remains `researcher` because: -- Probe code at this phase is rarely necessary; the deepening review +- Probe code during this activity is rarely necessary; the deepening review catches most fatal interface mistakes before code is written. - Three implementers writing probe code in parallel risks three divergent partial implementations of the same module — a merge problem the user @@ -162,7 +160,7 @@ Inside the grilling loop, after dependency classification, only when: If the interface is obvious from the dependency category and the call sites — for example, a thin adapter over a true-external dependency — -skip the parallel phase. A single proposed interface is enough. +skip parallel exploration. A single proposed interface is enough. ## Convergence Fallback @@ -172,7 +170,7 @@ implementation strategy, same tradeoffs. Two cases: 1. **Convergence is real.** The problem has a single best answer. Accept the convergence as a genuine finding and proceed to the PLAN with that single design. Note in the PLAN's "rejected alternatives" section that - the parallel phase produced no meaningful variation. + parallel exploration produced no meaningful variation. 2. **Convergence feels accidental.** The designs are suspiciously similar, the user senses a missed branch, or the briefing was so @@ -226,7 +224,7 @@ escalates on its own. ## Cost Note -A single invocation of the parallel phase is approximately **3 × +A single invocation of parallel exploration is approximately **3 × deep-exploration cost** in tokens — three sub-agents each running a full design pass against the same context. With more-agents escalation, the cost scales linearly (4 agents = ~4 ×, 5 agents = ~5 ×). @@ -235,10 +233,10 @@ This pattern is **opt-in inside the grilling loop**. It is not auto-triggered on every `/refactor-deepen` invocation. The 3-agent default is the cost ceiling for the default settings — the skill does not scale agent count silently. If a candidate's interface is obvious, skip the -phase entirely and propose a single design. +activity entirely and propose a single design. The cost is an explicit tradeoff the user accepts when they enter the -INTERFACE-DESIGN phase for a non-obvious interface. The skill should +Interface Design activity for a non-obvious interface. The skill should surface the cost briefly before spawning: > Spawning 3 design agents in parallel (~3 × token cost). Proceed? @@ -265,7 +263,7 @@ After the three sub-agents return: | Don't | Do Instead | |-------|------------| | Prime agents with opposing constraints by default | Use identical briefs; let sampling produce variety | -| Auto-trigger the parallel phase on every invocation | Invoke only when interface is non-obvious | +| Auto-trigger parallel exploration on every invocation | Invoke only when interface is non-obvious | | Use `implementer` profile for design sub-agents | Use `researcher`; switch to `implementer` only on explicit user request | | Add a "lens" to the brief silently | Surface the tradeoff to the user before priming | | Pre-rank the three designs in the output | Present in arbitrary order, let the user pick | @@ -283,6 +281,3 @@ After the three sub-agents return: agent profile for design sub-agents - [content/agents/implementer.md](../../../agents/implementer.md) — Alternative profile when probe code is needed -- [SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md) - — The shape decision (lines 64, 96, 107, 117) that established the - identical-brief default diff --git a/dist/skills/refactor-deepen/templates/plan.md b/dist/skills/refactor-deepen/templates/plan.md index 54a591e61..f564229a3 100644 --- a/dist/skills/refactor-deepen/templates/plan.md +++ b/dist/skills/refactor-deepen/templates/plan.md @@ -27,7 +27,7 @@ write a new file rather than updating an existing one. |-------|----------|-------| | `title` | Yes | One-line description of the deepening, not the candidate name | | `created` | Yes | ISO 8601 UTC, e.g. `2026-05-02T01:30:00Z` (must match the filename timestamp) | -| `status` | Yes | `drafting` on first write — lifecycle states are deferred to a follow-up spec | +| `status` | Yes | `drafting` on first write; this template does not define additional lifecycle states | | `spec` | Yes | `SPEC-NNN` if the plan is scoped under a spec; `null` otherwise (do not omit the key) | | `related` | No | List of related artifact IDs (`ADR-*`, `SPEC-*`, idea filenames, other plan filenames) | @@ -36,8 +36,7 @@ identity, mirroring councils and ideas. ## Required Sections -The five sections below are the *minimal shape* defined in SPEC-034. Order is -load-bearing: each section assumes the previous one is settled. Do not reorder. +The five sections below are the *minimal shape* for a PLAN. Order is load-bearing: each section assumes the previous one is settled. Do not reorder. 1. **Candidate** — what's being considered for deepening. Name the **module** verbatim (use the canonical glossary term — run `loaf kb glossary check` @@ -111,14 +110,12 @@ proportional to actual usage, matching how `.agents/specs/` behaves. ## Linear-Native Mode: Fail Fast -PLAN files are **local-only storage**. Per SPEC-034 line 81, write commands -must fail fast in Linear-native mode rather than silently degrade. The -consuming skill (`/refactor-deepen`) is responsible for: +PLAN files are **local-only storage**. Write commands must fail fast in Linear-native mode rather than silently degrade. The consuming skill (`/refactor-deepen`) is responsible for: 1. Reading `.agents/loaf.json` and checking `integrations.linear.enabled`. 2. If true: aborting before `mkdir -p .agents/plans` and before any write, with the verbatim error - `"Linear-native plan storage pending artifact-taxonomy spec — local mode only for now."` + `"Linear-native plan storage unavailable — continuing with a read-only report."` 3. If false: proceeding with the write as documented above. This template intentionally does **not** wrap the write in a diff --git a/dist/skills/research/SKILL.md b/dist/skills/research/SKILL.md index ddf15dad4..e4c00f028 100644 --- a/dist/skills/research/SKILL.md +++ b/dist/skills/research/SKILL.md @@ -143,3 +143,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/skills/shape/SKILL.md b/dist/skills/shape/SKILL.md index f41146877..be87a5e12 100644 --- a/dist/skills/shape/SKILL.md +++ b/dist/skills/shape/SKILL.md @@ -163,3 +163,7 @@ Offer to push the branch and open a draft PR, using [the PR template](templates/ | Decomposition | [references/decomposition.md](references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/dist/skills/shape/references/cli-boundary.md b/dist/skills/shape/references/cli-boundary.md index efb3cc1b5..7f5816b03 100644 --- a/dist/skills/shape/references/cli-boundary.md +++ b/dist/skills/shape/references/cli-boundary.md @@ -13,7 +13,7 @@ Folder resolution: an explicit `[folder]` argument always wins; otherwise the cu Output splits into two tiers: - **Violations** — always fail (exit code 2), regardless of flags: status-like frontmatter keys (`readiness`, `status`, `state`) or values matching the canonical change-state vocabulary; frontmatter not opening the file at byte one; malformed `YYYYMMDD-slug` folder naming; identity mismatch between `change:`/`created:` and the folder name; missing Product Contract sections (Problem, Hypothesis, Scope, Observable Workflow, Rabbit Holes and No-Gos). -- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A shaping-stage Change with open gaps is valid; the report just says what's still missing. +- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A Change with open gaps is incomplete and non-executable; the report just says what's still missing. `--require-executable` turns structural executability into a gate (exit code 1 if not structurally executable); it does not prove implementation completion. This is implement's preflight and CI's non-draft-PR check, not something shape itself passes during shaping. diff --git a/dist/skills/shape/references/decomposition.md b/dist/skills/shape/references/decomposition.md index edf38530b..5ffefbe74 100644 --- a/dist/skills/shape/references/decomposition.md +++ b/dist/skills/shape/references/decomposition.md @@ -4,7 +4,7 @@ Shaping step absorbed from the retired breakdown skill: dependency awareness, gr ## What Survives -- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into phases. Are you splitting just to have more units? If yes, merge back. +- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into smaller coherent units. Are you splitting just to have more units? If yes, merge back. - **Right-sizing rules** — one agent type per unit (completable by a single implementer), one concern per unit (one layer, service, or component), context-appropriate (fits in model context with room for exploration), not over-fragmented (don't split what naturally belongs together). - **Per-unit verification discipline** — every unit includes its own observable done condition. Never a separate "verify" unit; keep tests with the code they test. - **Own the decisions** — decide granularity and unit boundaries autonomously. Ask the user only when two orderings are genuinely equally valid with different trade-offs; otherwise decide and move on. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 9be63166c..1f2381017 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -37,20 +37,20 @@ Each target transformer reads content (skills/agents/hooks) and config, then pro The public runtime and CLI reference generation are native Go. Remaining non-Go files under `cli/` are JavaScript launcher/build/smoke/evaluation scripts, not TypeScript command implementations or tests. -### Stateful Runtime Migration (ADR-014) +### Native Stateful Runtime (ADR-014) -ADR-014 accepts Go as the runtime direction for Loaf's stateful core. Native Go is now the shipped public runtime; TypeScript command registrations, the shipped fallback bundle, and the local TypeScript test harness have been removed from the active CLI surface. +ADR-014 records the decision to use Go for Loaf's stateful core. Native Go is the shipped public runtime; TypeScript command registrations, the fallback bundle, and the TypeScript test harness are no longer part of the active CLI surface. -The transition shape is a Go front controller for the public `loaf` command: +The public command has one native runtime: ``` -loaf # Go front controller -└── native Go commands # stateful/runtime-heavy behavior and migrated public commands +loaf # Native Go command surface +└── command families # Stateful operations, build/install, checks, and project workflows ``` -The former TypeScript bridge prevented a big-bang rewrite. Public commands have moved to Go for the stateful runtime, storage layer, and lower-dependency distribution shape. Historical ADRs still describe the transition, but the active `cli/` tree no longer contains TypeScript source or test files. +Historical decision records describe how the runtime moved, but the active `cli/` tree contains only JavaScript launcher, build, verification, smoke, and evaluation scripts. It does not contain TypeScript command source or tests. -This changes the construction technique, not the product contract: skills still call `loaf`, hooks still enforce through `loaf`, and users still see one command surface. The implementation boundary behind that command is allowed to migrate command-by-command. +Skills call `loaf`, hooks enforce through `loaf`, and users see one command surface. ADR and SPEC identifiers cited in this document serve only as decision and work provenance. ### Operational State Identity @@ -85,7 +85,7 @@ Amp's plugin API is intentionally minimal. Plugin handlers are dispatched via `h There is no session-lifecycle dispatch. Amp's binary internally emits `emitEvent("session.start", ...)` for telemetry purposes, but this is not exposed to plugins. Features that require a SessionStart hook (the journal continuity digest, SOUL.md self-healing) or PreCompact flushes are not viable on Amp without upstream support. Loaf's Amp target is scoped to tool events only; the SessionStart digest that other targets ship is intentionally absent here. -This was discovered during SPEC-033 review (PR #40). An earlier wiring attempted to map `sessionEnd` to `agent.end` (turn-end) — semantically wrong and now reverted. +`agent.end` is turn-end, not session-end, so Loaf does not map session lifecycle behavior onto it. ### Prompt Overlay Consolidation (ADR-020, superseding ADR-010) @@ -110,25 +110,25 @@ Fresh installs pre-create an empty root canonical so the Claude symlink is never **Config health (`loaf config check`):** the native CLI validates `.agents/loaf.json` and installed Loaf-managed hook config separately. `--fix` creates missing safe project-config defaults and refreshes stale installed target artifacts through the same target installers as `loaf install`, so new hooks such as `github-account` can be propagated without hand-editing target config files. -**Drift detection (`loaf doctor`):** Six checks cover root canonical presence and file type, retirement of legacy `.agents/AGENTS.md`, the Claude symlink target, stale `.cursor/rules/loaf.mdc`, fenced-section version match, and duplicate fenced sections. Plain diagnosis is read-only. `loaf doctor --fix` offers each logical repair once behind a default-no y/N prompt, preserves legacy content and backups for accepted repairs, and rechecks each repair before tallying the final result; checks that converge through the same filesystem action share one repair identity so a decline cannot be bypassed later in the run. Declined and non-interactively skipped repairs remain failures; only a real terminal is interactive, and `loaf doctor --fix --force` explicitly accepts every offered repair without prompting. +**Drift detection (`loaf doctor`):** Checks cover root canonical presence and file type, retirement of legacy `.agents/AGENTS.md`, the Claude symlink target, stale `.cursor/rules/loaf.mdc`, fenced-section version match, and duplicate fenced sections. Plain diagnosis is read-only. `loaf doctor --fix` offers each logical repair once behind a default-no y/N prompt, preserves legacy content and backups for accepted repairs, and rechecks each repair before tallying the final result; checks that converge through the same filesystem action share one repair identity so a decline cannot be bypassed later in the run. Declined and non-interactively skipped repairs remain failures; only a real terminal is interactive, and `loaf doctor --fix --force` explicitly accepts every offered repair without prompting. -This extends the "CLI is the correct protocol layer" principle to filesystem convention enforcement: the CLI owns the on-disk overlay state, not the skills or the user. When ADR-010 shipped, five harnesses went from "each writes its own file" to "each resolves to the same file" without any skill edits. +This extends the "CLI is the correct protocol layer" principle to filesystem convention enforcement: the CLI owns the on-disk overlay state, not the skills or the user. ADR-010 records the consolidation from per-harness writes to one canonical file. -### Mode-Aware Skills (Linear-Native Mode, ADR-011) +### Work Records and Optional Linear Tasks (ADR-011) -Skills that orchestrate specs and tasks (`/breakdown`, `/implement`, `/housekeeping`, `/shape`, `/council`) branch on `integrations.linear.enabled` in `.agents/loaf.json`: +New bounded work is git-canonical under `docs/changes/YYYYMMDD-slug/change.md`. Existing specs in `.agents/specs/` and task records remain supported compatibility surfaces. For compatible task workflows, `integrations.linear.enabled` in `.agents/loaf.json` selects the execution backend: -- **Local-tasks mode** (default): specs stay in `.agents/specs/`; task, journal, idea, spark, brainstorm, and draft records live in the global SQLite database. -- **Linear-native mode**: specs stay in `.agents/specs/` (canonical, deliberation layer); tasks move to Linear as sub-issues under a `spec`-labeled parent rollup issue (execution layer). +- **Local-tasks mode** (default): tasks, journal entries, ideas, sparks, brainstorms, and drafts live in the global SQLite database. +- **Linear-native mode**: existing compatible specs remain git-canonical while tasks use Linear sub-issues under a parent rollup issue. The split reflects an architectural principle from ADR-010's consolidation pattern extended to the spec/task artifact model: -- **Deliberation artifacts belong with code.** Specs, ADRs, councils. Need git history, code-adjacent visibility, travel with the branch, survive the tracker being down or switched. +- **Deliberation artifacts belong with code.** Changes, existing specs, ADRs, and councils need git history, code-adjacent visibility, and independence from tracker availability. - **Execution artifacts belong in the tracker.** Tasks, blockers, comments, assignees. Need real-time state, dashboards, blocking graphs, notifications. -In Linear-native mode, the parent Linear issue is a **canonical-elsewhere rollup** — summary + link to the local spec file, not a re-host. It parallels the root `AGENTS.md` → Claude compatibility-symlink pattern from ADR-020: the canonical artifact exists in exactly one place; the other surface is a thin pointer. +In Linear-native mode, the parent Linear issue is a **canonical-elsewhere rollup**: a summary and link to the git-canonical artifact, not a re-host. The artifact exists in one place; the tracker is a thin execution surface. -Skills detect the mode and branch accordingly. No skill edits are required to switch modes — same skill content, different backend. This sets up SPEC-023's backend abstraction as a narrower refactor than originally scoped: the contract is already mode-aware; SPEC-023 just extracts the Linear MCP calls into a shared `tracker` CLI subcommand with pluggable implementations. +Skills detect the mode and branch accordingly; the same skill content selects a different task backend without changing the git-canonical artifact. ### Pre-Flight Dependency Gate @@ -136,9 +136,9 @@ Skills detect the mode and branch accordingly. No skill edits are required to sw This is different from advisory dependency ordering: the dependency graph becomes a runtime invariant, not a suggestion. The orchestrator cannot implement through open blockers even by accident. -The local-tasks equivalent (dependencies in `TASKS.json`) is still advisory. Pre-flight gating requires a system of record that can be queried reliably for all blockers' current state; Linear provides that, local files do not without a separate polling layer. This asymmetry is intentional: teams that care about strict dependency enforcement get Linear's gate for free; solo developers on local tasks trade enforcement for simplicity. +Local task dependencies are stored in SQLite and remain advisory. Pre-flight gating requires a backend that can reliably query every blocker's current state; Linear provides that guarantee for its task workflow, while local tasks trade strict enforcement for simplicity. -Parent-issue completion follows from the same contract: when the last sub-issue flips to `completed`, `/implement` auto-closes the parent. A parent with any open sub-issue (including `blocked`) stays open — the spec is not done until its execution tree is. +Parent-issue completion follows from the same contract: when the last sub-issue flips to `completed`, `/implement` auto-closes the parent. A parent with any open sub-issue, including `blocked`, stays open. ### Agent Model: Functional Profiles @@ -148,7 +148,7 @@ Loaf uses **functional profiles** defined by tool access boundaries, not role-ba The main conversation is the **orchestrator** — the coordinator that plans and delegates but does not directly implement, review, research, or curate durable artifacts. -**4 Functional Profiles:** +**Functional Profiles:** | Profile | Tool Access | Purpose | |---------|-------------|---------| @@ -159,7 +159,7 @@ The main conversation is the **orchestrator** — the coordinator that plans and Each profile is defined in `content/agents/{implementer,reviewer,researcher,librarian}.md` — a minimal behavioral contract and tool boundary, not domain knowledge. A spawned implementer becomes a backend engineer, DBA, or devops engineer depending entirely on the skills loaded at spawn time. -**1 System Agent:** +**System Agent:** | Agent | Purpose | |-------|---------| @@ -187,11 +187,11 @@ The judgment boundary follows from the storage boundary: humans and Skills inter ### Authorship Model — Agents Create, Humans Curate -Agents are the primary authors of knowledge files, ADRs, tasks, and specs. Humans review, approve, and curate — they are not the writing surface. The CLI follows from this: it is for management and health checks (`check`, `validate`, `status`, `review`), not for authoring. +Agents are the primary authors of Changes, knowledge files, ADRs, and compatible task records. Humans review, approve, and curate — they are not the writing surface. The CLI follows from this: it is for deterministic operations and health checks, while skills guide authorship and judgment. The principle inverts the traditional "humans write docs, agents consume them" model. Agents are already doing the work and are closest to what's being learned; pulling knowledge creation into the work itself ("maintenance as side effect of work") is cheaper than treating documentation as a separate sprint. Humans are better at judgment — *is this worth recording?* — than at the writing. -The growth loop is concrete: agent discovers an insight during brainstorming, development, or debugging → proposes a knowledge file, ADR, task, or spec → human reviews and accepts, edits, or rejects → committed. Quality control depends on human review; agents may write redundant or low-quality material that the curator catches. Hooks (PostToolUse, PreCompact) prompt agents at the moments where insights are freshest, so the proposal isn't deferred until the context is gone. +The growth loop is concrete: an agent discovers an insight during exploration, implementation, or debugging, proposes the appropriate durable record, and a human accepts, edits, or rejects it. Hooks prompt agents when insights are fresh so useful learning is not deferred until context is gone. This principle shapes skill design and CLI surface; it is mutable and evolves via `/reflect`. @@ -217,41 +217,38 @@ Recategorization emerged from PR #46: three ADRs whose conventions/principles st This pattern generalizes beyond ADRs. When any Loaf artifact is later judged to have been classified wrong but its content is still valid, recategorize: deprecate the original, point to the new canonical home, leave the body intact for archeology. -## Execution Model +## Change-First Execution Model -The execution model is a three-artifact pipeline. No separate "plan" artifact — the journal serves as both execution trace and resumption protocol. +New bounded work uses a Change as its primary contract. The project journal remains the execution trace and resumption protocol; tasks are optional durable records rather than mandatory decomposition. ``` -/shape → SPEC file → /breakdown → SQLite tasks → /implement → project journal → Done +/idea or /brainstorm → /shape → Change → /implement → review → /ship + ↓ + project journal ``` -### Task System +### Work Records ``` -.agents/specs/SPEC-XXX.md # Bounded work definitions (scope, test conditions, priority order) -SQLite tasks # Individual work items (criteria, file hints, verification) -SQLite journal_entries # Project-scoped event record across every conversation +docs/changes/YYYYMMDD-slug/change.md # Primary bounded-work contract +SQLite tasks # Existing or optional compatible work items +.agents/specs/SPEC-XXX.md # Existing compatible bounded-work records +SQLite journal_entries # Project-scoped event record across conversations ``` -**Specs** define *what* to build — problem, solution direction, boundaries, test conditions. Multi-part specs use priority ordering with go/no-go gates between tracks (ship in order, drop from end). Sized by complexity (small/medium/large), not time. +**Changes** define the problem, hypothesis, scope, implementation units, verification contract, and definition of done. `loaf change check` validates their structure and derives executability. -**Tasks** define *what to do* — one concern per task, file hints, verification command, observable done condition. Created by `/breakdown`, worked by `/implement`. +**Tasks and specs** remain supported compatibility records. They may describe individual concerns, dependencies, and existing bounded work, but new shaping does not require a spec or a task decomposition layer. **The journal** captures *what happened* — `journal_entries` rows are project-scoped events (`project_id NOT NULL`), each tagged with an opaque `harness_session_id` that correlates one conversation's entries. Decisions, discoveries, commits, and progress land as structured entries; `loaf journal recent`/`show`/`search` and the `loaf journal context` digest provide handoff-ready context for compaction recovery and cross-conversation resumption. There is no session entity — see [Session Model: Journal-First](#session-model-journal-first). -`.agents/tasks/`, `.agents/ideas/`, `.agents/sparks/`, -`.agents/brainstorms/`, `.agents/drafts/`, and `.agents/TASKS.json` are -rollback material after SPEC-045, not compatibility mirrors. A stale branch that -reintroduces them should keep the deletion side and rerun -`loaf check --hook ephemeral-provenance`. Legacy `.agents/sessions/` markdown is -also gone: the journal is SQLite-native and never rendered to a hand-authored -source file. +`.agents/tasks/`, `.agents/ideas/`, `.agents/sparks/`, `.agents/brainstorms/`, `.agents/drafts/`, and `.agents/TASKS.json` are rollback material after the SQLite cutover recorded by `SPEC-045`, not compatibility mirrors. A stale branch that reintroduces them should keep the deletion side and rerun `loaf check --hook ephemeral-provenance`. Legacy `.agents/sessions/` Markdown is also gone: the journal is SQLite-native and never rendered to a hand-authored source file. ### Session Model: Journal-First -The project journal is the **only** session-related structure (SPEC-056). There is no session entity — no `sessions` table, no statuses, no lifecycle, no rotation. `journal_entries` are project-scoped events (`project_id NOT NULL`) in the global SQLite database, each carrying an opaque `harness_session_id` column that correlates the entries written by one conversation. Nobody opens, closes, or transitions a session; nothing is ever "unwrapped." +The project journal is the **only** session-related structure. There is no session entity — no `sessions` table, no statuses, no lifecycle, no rotation. `journal_entries` are project-scoped events (`project_id NOT NULL`) in the global SQLite database, each carrying an opaque `harness_session_id` column that correlates the entries written by one conversation. Nobody opens, closes, or transitions a session; nothing is ever "unwrapped." -This supersedes the SPEC-048 `start → log → end --wrap` session lifecycle and its six-state entity: production data showed the lifecycle never maintained itself (stuck `active`/`paused` records, empty snapshots, ~24% lifecycle-noise entries), and its rotation semantics actively fought concurrency. **Concurrent conversations on the same project — across branches, worktrees, even harnesses — are safe by construction:** two conversations logging at once simply interleave rows with different `harness_session_id` tags, which is correct rather than corrupt. +The journal model supersedes the former mutable session lifecycle. **Concurrent conversations on the same project — across branches, worktrees, even harnesses — are safe by construction:** simultaneous writers interleave rows with different `harness_session_id` tags instead of rotating or reconciling shared session state. **Logging:** `loaf journal log "type(scope): description"` appends a durable entry; the current branch and harness id are attached automatically. Skills self-log their invocation as their first action; the `session` entry type is gone. @@ -291,15 +288,7 @@ A new conversation is never a new "session" — it is just a new `harness_sessio ### Forward-Only In-Flight Pivots -When a PR is reviewed, approved-with-findings, and the findings reveal that a feature shouldn't ship as designed, the project favors **forward removal commits over history rewriting**. - -Three reasons: - -1. The squash merge nets the diff regardless — main only sees the final change. -2. Force-push invalidates review thread context (Codex citations, reviewer line refs) and is generally blocked on shared branches. -3. The PR's commit history becomes honest archeology — "we shipped, then reviewed, then pivoted" is more useful than a tidy linear story that hides the deliberation. - -SPEC-033 (PR #40, v2.0.0-dev.32) is the canonical example: 13 feature commits + 2 forward-removal commits + 1 cleanup. The squash on main is clean; the PR thread shows the pivot. Future PRs that need to pivot mid-flight should follow the same pattern. +When review reveals that code on an open branch should not ship as designed, the project favors **forward removal commits over history rewriting**. The final squash preserves a clean mainline diff, while the pull request retains review context and an honest record of the pivot. Avoid force-pushing away citations or shared review history. ## Hook Architecture @@ -315,7 +304,7 @@ Hooks are defined in `config/hooks.yaml` and distributed to target-specific form ### Hook Type Behavioral Constraints -Hard-won constraints validated during SPEC-030 implementation: +The target hook APIs impose these behavioral constraints: - **`type: prompt`** — Binary gate. Any non-empty LLM response is treated as rejection (`ok: false`). Cannot express "this looks fine, proceed" — the response itself blocks. Unusable for advisory hooks or hooks requiring LLM judgment. Use only for validation that returns empty on success. - **`type: agent`** — Read-only tool access (Read, Grep, Glob, WebFetch, WebSearch). No Edit, Write, or Bash. Max 50 turns. Useful for observation, not mutation. @@ -380,7 +369,7 @@ Any test that spawns a CLI subprocess must use OS-tmp isolation for its fixtures workingDir := realpath(t, t.TempDir()) ``` -CWD-relative fixtures are forbidden for subprocess tests. The old Vitest suite exposed why: workers shared filesystem state and cwd, so `join(process.cwd(), ".test-...")` fixtures could race against other subprocess tests. One such leak in `cli/commands/check.test.ts` silently failed `cli/commands/report.test.ts` for 17+ commits before v2.0.0-dev.28 bisected it. +CWD-relative fixtures are forbidden for subprocess tests because workers may share filesystem state and cwd. A fixture such as `join(process.cwd(), ".test-...")` can race with another subprocess test even when each file passes independently. `realpath` is required on macOS because the system tmpdir (`/var/folders/...`) is reached through a `/private/var/folders/...` symlink; without realpath, subprocess cwd comparisons can fail. @@ -396,18 +385,14 @@ Patterns that apply across multiple subsystems and emerged from specific post-re The native CLI version must report the package version consistently through the launcher, native runtime, generated targets, and install markers. Go runtime paths read package metadata directly; the obsolete TypeScript version helper was removed after the install and version surfaces moved to native Go. -Before PR #35 (v2.0.0-dev.30), three separate runtime `package.json` walkers in those same files diverged and all fell back to `"0.0.0"` from the bundled binary — a false-positive factory for every version-comparison check in the CLI. The lesson generalizes: any value that must be identical across runtime modes should be injected at build time, not resolved at runtime. +Any value that must be identical across runtime modes should be injected at build time, not independently resolved by multiple runtime paths. Divergent version discovery creates false positives in every downstream comparison. ### Generated Runtime Plugin Artifacts Parsed From Emitted Output Files the build emits for downstream runtimes to execute — OpenCode `hooks.ts`, Amp `loaf.js`, and any future per-target runtime plugin — must have tests against the **actual emitted file**, not just the generator's input string. -Template-literal escape bugs are invisible at the source-string level: the former TypeScript build helper emitted invalid regex (`/*/g`) into `dist/opencode/plugins/hooks.ts` for multiple versions because the broken code path was unreachable at runtime. The syntactic breakage was dormant until OpenCode's plugin loader tightened its validation and rejected the file on load. Native build tests in `internal/cli/build_test.go` now read the emitted OpenCode and Amp plugin files and assert the runtime hook bodies and command payloads that downstream runtimes load. +Source-template assertions cannot prove that escaping remains valid after generation. Native build tests in `internal/cli/build_test.go` therefore read the emitted OpenCode and Amp plugin files and assert the runtime hook bodies and command payloads that downstream runtimes load. ### Visible-Degraded Fallback with Stderr WARN -When strict invariant enforcement would break existing callers but silent fallback corrupts data, emit a stderr WARN naming the missing signal and the silencing flag. The action proceeds (preserving compatibility) but the WARN makes the misroute visible in real time and provides a regression-testable surface for the eventual cutover. - -SPEC-032 used this pattern for the branch-fallback session router that resolved a target session for `loaf session log`, `archive`, and `end --wrap`. **SPEC-056 superseded that mechanism:** journal-first removed the session entity the router resolved against, so there is nothing to misroute — `loaf journal log` attaches the current branch and `harness_session_id` automatically, and concurrent conversations interleave rows by construction. The WARN it emitted was the regression gate for exactly this cutover; the cutover has now landed. The pattern is retained here as a general design tool, not as a description of live session routing. - -The pattern generalizes: any compatibility carve-out that violates a stated invariant should be observable in real time, not invisible. The cost (one extra stderr line for legacy callers) is paid once per invocation; the benefit (every misroute surfaces immediately) is paid forward to whoever next opens an issue saying "my entry didn't land where I expected." +When strict invariant enforcement would break existing callers but silent fallback risks incorrect behavior, emit a stderr warning that names the missing signal and any silencing flag. The action may proceed for compatibility, but the degraded path must remain visible and regression-testable. The journal no longer uses a branch-fallback session router; entries attach project, branch, and harness context without resolving a mutable session entity. diff --git a/docs/STRATEGY.md b/docs/STRATEGY.md index 4042af51e..af4f37267 100644 --- a/docs/STRATEGY.md +++ b/docs/STRATEGY.md @@ -1,125 +1,65 @@ # Strategy -Loaf is an opinionated agentic framework for AI coding assistants. It ships skills, profiles, hooks, and a CLI to six harnesses. This document records what the project has proven through implementation and what the evidence says to build next. +Loaf is an opinionated agentic framework for AI coding assistants. It ships portable skills, bounded agent profiles, target-native adapters, enforcement hooks, and a native CLI. This document states current strategy; detailed history and evidence remain in [Changes](changes/), [decision records](decisions/), [reports](reports/), and git history. ## Who This Serves -**Solo developer.** Uses Loaf with Claude Code (or another AI tool) for personal and professional projects. Wants structured workflow that reduces context-switching overhead, enforces quality without manual effort, and preserves work across sessions. Technical, comfortable with CLI, values autonomy. Measures Loaf by how much friction it removes compared to vanilla AI-assisted development. Will abandon the framework if it gets in the way more than it helps. +**Solo developers** need an agent workflow that reduces context-switching overhead, preserves work across conversations, and enforces quality without becoming more cumbersome than direct tool use. -**Team lead.** Installs Loaf across multiple developers and tools. Wants consistent agent behavior regardless of which developer or AI tool is used. Values quality gates, audit trails, and predictable outcomes. Needs the framework to work without requiring every team member to understand its internals. Measures Loaf by whether it reduces variance in agent output quality across the team. Will not adopt if the onboarding cost exceeds the consistency benefit. +**Teams** need consistent agent behavior across developers and harnesses, with auditable decisions, trustworthy quality checks, and installation behavior that does not require everyone to understand Loaf internals. -## What Has Been Proven +## Proven Principles -24 specs shipped, 6 in progress. The evidence clusters into four themes. +**Skills are the portable knowledge layer.** Shared authoring should remain the default, while target-specific adapters translate that knowledge into the strongest trustworthy native surface each harness exposes. -**Skills are the highest-leverage investment.** They work across all six targets. Better skill descriptions and organization improve every target simultaneously. Profiles and hooks are Claude Code infrastructure that other targets cannot use. +**The CLI is the protocol layer.** Skills describe judgment and workflow, the CLI performs deterministic state and filesystem operations, and hooks enforce or inject narrowly scoped behavior. Runtime behavior should not depend on prose reimplementing CLI logic. -This was proven by SPEC-014 (skill activation redesign) and SPEC-020 (target convergence) -- the same 31 skills now deploy to Claude Code, Cursor, OpenCode, Codex, Gemini, and Amp from a single source tree. The implication for both personas: invest in skill quality first, harness-specific features second. +**Continuity belongs to the project journal, not a session lifecycle.** Journal entries are project-scoped events correlated by an opaque harness identity. Context is derived at read time, and a wrap is an optional synthesis checkpoint rather than a transition. -ADR-010 (prompt-overlay consolidation, shipped v2.0.0-dev.28) extended target convergence to the project overlay file itself: five of six targets now write to `.agents/AGENTS.md` directly; the sixth target's native path is a symlink to it. A single managed fenced section replaces six. For the team lead persona, this means onboarding additional harnesses adds no duplicated content-maintenance overhead; for the solo developer, the file they edit and the file every harness reads are the same file. +**Managed installation requires ownership evidence.** Loaf should change installed content only when it can identify what it owns and verify the expected digest. Capability claims must be tied to exact client versions and installed runtime evidence rather than inferred from build output. ADR-020 preserves that single-overlay result while making root `AGENTS.md` the canonical real file. This improves standards-native discoverability and removes the unnecessary root indirection; `.agents/` remains reserved for Loaf state and configuration, while `.claude/CLAUDE.md` remains a compatibility symlink. **Continuity must survive everything -- the session entity didn't need to.** Context compaction, `/clear`, tool restarts, and cross-conversation handoffs all create new harness session IDs pointing at the same stream of work. Any architecture that assumes 1 session = 1 conversation fails in practice. -SPEC-027 (session stability), SPEC-023 (session continuity on `/clear`), and SPEC-030 (Librarian agent) addressed this incrementally under the session-entity model: splits were detected and consolidated on start, and a `## Current State` section carried handoff context across compaction. That machinery stabilized the surface but stayed the most failure-prone one -- it touched every other feature, which is what ultimately motivated SPEC-056's move to a journal-first model where continuity is a derived, ephemeral digest rather than persisted session state. Journal-first (SPEC-056, commit 9189080c) resolved the theme by deleting the entity rather than preserving it: the project journal is the durable record, `harness_session_id` is an opaque correlation tag, and continuity is computed at read time. Production data made the case -- 40 of 276 sessions were stuck `active` or `paused`, 22% held zero journal entries, and ~24% of all entries were lifecycle noise. Migration 0010 purged 1,122 noise entries and dropped all 286 session rows. +**Automation must fail within its evidence boundary.** Automatic completion remains disabled unless a target supplies trustworthy success evidence and a durable event identity. When a harness cannot distinguish the relevant traffic or lifecycle event reliably, an explicit fallback is preferable to a false guarantee. -SPEC-029 (journal enrichment) extended session completeness by adding post-hoc JSONL review. Its first real test exposed a routing tension between logging by branch and enriching by `claude_session_id` — when multiple conversations contributed to one session, the two mechanisms could disagree. SPEC-032 narrowed that gap with a three-tier router, but the tension was structural: it existed only because a mutable session entity had to be resolved before an entry could land. SPEC-056 dissolved it by removing the entity entirely — entries are project-scoped rows tagged with an opaque `harness_session_id`, so concurrent conversations interleave by construction and there is nothing to misroute. - -**Hook primitives have hard behavioral constraints.** These are platform limits discovered through SPEC-026 and SPEC-030, not design choices. They constrain every future hook design: - -- **Prompt hooks** are binary gates -- any non-empty LLM response is treated as rejection. Cannot express "this looks fine, proceed." Unusable for advisory guidance; use only for validation that returns empty on success. -- **Agent hooks** have read-only tool access (Read, Grep, Glob, WebFetch). Useful for observation, not mutation. -- **Command hooks** are the correct primitive for side effects and context injection. Exit 0 with stdout for injection, exit 1 for warning, exit 2 to block. -- **Stop hooks** can create circular re-triggers when they write to files the hook chain monitors. State writes must be idempotent or guarded. -- **PreCompact prompt hooks** do not work outside REPL sessions. Use command hooks for PreCompact context injection. -- **`plugin.json`** silently drops non-matcher lifecycle events. `hooks.json` is the canonical registration path for session events. -- **Plugin caching** serves stale hook handlers during local development. Marketplace remove/re-add is the only reliable cache-bust. This is the single largest development-cycle friction point. - -**The CLI is the correct protocol layer.** Skills should describe what to do. The CLI should execute it deterministically. Hooks should enforce invariants. This three-layer separation emerged through SPEC-008 (CLI), SPEC-009 (knowledge management), SPEC-012 (cleanup), and SPEC-019 (release). +**The CLI is the correct protocol layer.** Skills should describe what to do. The CLI should execute it deterministically. Hooks should enforce invariants. This three-layer separation emerged from repeated attempts to let skills act on the world directly. Every time a skill tried to call an external tool directly -- Linear MCP, raw git commands, file operations -- reliability dropped. The CLI absorbs that complexity and presents a stable interface to skills. For the team lead persona, this is critical: the CLI is the enforcement layer that makes agent behavior deterministic regardless of which LLM or harness is running. **Diagnosis and repair must share the same state taxonomy.** Sharing repair helpers is not enough; the detection branches in a diagnostic tool must consult the same classification logic as the repair path, or they will drift apart. -`loaf doctor` v1 (shipped v2.0.0-dev.28, PR #33) silently skipped legacy-layout states (real `./AGENTS.md` or `.claude/CLAUDE.md` without a canonical `.agents/AGENTS.md`) even though `migrateRealFileToSymlink` -- the very helper that repairs those states -- was already written and invocable from the fix path. The diagnostic and repair code paths had diverged: the repair path knew about legacy layouts; the detection path did not. External review caught this in PR #35 (v2.0.0-dev.30); the fix rebuilt detection to surface legacy states as fixable `fail`, and the fix paths to lazily create canonical before delegating to the shared helper. For both personas, this means `loaf doctor --fix` can be trusted to heal every state the diagnostic surfaces as fixable -- because the same state definitions drive both halves of the state machine. +An early `loaf doctor` silently skipped legacy-layout states -- a real `./AGENTS.md` or `.claude/CLAUDE.md` with no canonical overlay -- even though the helper that repairs those states was already written and invocable from the fix path. The two halves had diverged: the repair path knew about legacy layouts, the detection path did not. External review caught it, and the fix rebuilt detection to surface legacy states as fixable `fail` and taught the fix paths to create canonical lazily before delegating to the shared helper. For both personas this means `loaf doctor --fix` can be trusted to heal every state the diagnostic surfaces as fixable, because the same state definitions drive both halves of the state machine. ADR-020 applies that lesson to the reverse migration: doctor now classifies root-file canonicality, retired `.agents/AGENTS.md` presence, and Claude compatibility-link drift independently. Plain diagnosis stays read-only; `--fix` asks before each repair, preserves legacy content and backups for accepted repairs, and requires `--force` to accept all repairs non-interactively. -**Personality is decorative, mechanics are durable.** SPEC-033 explored decoupling agent personality (Warden/Fellowship lore) from agent mechanics via a swappable souls catalog. Implementation was complete, reviewed twice (Loaf reviewer + two Codex passes), and pivoted in-flight before merge — the user, after months of personal Loaf use, acknowledged the lore had never landed; Codex flagged SOUL.md as a brittle prompt-injection surface (advisory enforcement only). The shipped artifact (`v2.0.0-dev.32`) keeps the profile neutralization and skill prose audit; the catalog/CLI/install/SessionStart-restoration layers were removed. +**Personality is decorative, mechanics are durable.** An attempt to decouple agent personality (Warden/Fellowship lore) from agent mechanics through a swappable souls catalog was fully implemented, reviewed twice, and then pivoted in flight before merge: after months of real use the lore had never landed, and review flagged a prose-driven soul file as a brittle prompt-injection surface enforceable only by advice. What shipped keeps the profile neutralization and the skill prose audit; the catalog, CLI, install, and startup-restoration layers were removed. -The implication for both personas: Loaf's value is the *framework* (mechanical hooks, structured pipeline, profile boundaries, knowledge layer), not a personality layer. Adding identity through prompt content is incompatible with hardening agents — it costs complexity, adds attack surface, and delivers value only when the user already buys into the metaphor. The lore concept is preserved in SPEC-033 archive as a record of what was tried, with a possible future home in a Pi-based harness where it could be load-bearing rather than decorative. +The implication for both personas: Loaf's value is the *framework* -- mechanical hooks, structured pipeline, profile boundaries, knowledge layer -- not a personality layer. Adding identity through prompt content is incompatible with hardening agents: it costs complexity, adds attack surface, and delivers value only when the user already buys into the metaphor. The lore concept survives in the archived record as an account of what was tried, with a possible future home in a Pi-based harness where it could be load-bearing rather than decorative. + +**Release is separate from shipping.** A Change may land through one or more coherent pull requests; publishing a project version is a distinct operation over already-landed work. CI verifies reproducible outputs and must not silently repair the source branch. ## Current Priorities -Ordered by evidence strength -- what has been proven most urgent by shipping. - -1. **Journal continuity** (proven: SPEC-056; groundwork: SPEC-027, 028, 030, 032, which operated under the retired session-entity model). The foundation everything else builds on. Compaction and `/clear` continuity are handled by the derived start digest. Artifact housekeeping and archival run via `loaf housekeeping`. The Librarian agent tends the project journal and durable `.agents/` artifacts. SPEC-056 retired the session entity in favor of the project journal. - - Remaining gap: the PreCompact flush depends on the model actually writing journal entries before compaction completes -- a race Loaf cannot fully control. Journal-discipline hooks mitigate it but do not eliminate it. - - **v2.0.0-dev.31 (SPEC-032) closed the routing inconsistency, then SPEC-056 removed the mechanism outright.** SPEC-032 resolved session mutations through a 3-tier chain (`--session-id` flag → hook stdin → branch-fallback) whose branch-fallback tier emitted a stderr WARN naming the missing signal — that WARN was the regression gate for the eventual cutover. Journal-first landed the cutover: there is no session entity to key or resolve, so `loaf journal log` attaches the current branch and `harness_session_id` automatically and the router no longer exists. - - **What SPEC-056 resolved:** the router existed to reconcile skill self-logging (which routed by branch because skills couldn't reliably pass a per-process session id) with enrichment (which routed by `claude_session_id`). Journal-first made the reconciliation moot — skills now self-log with `loaf journal log`, entries are keyed by project and tagged with `harness_session_id`, and enrich is gone. Branch is a query filter over rows, not an identity to resolve. - -2. **Hook correctness** (proven: SPEC-026, 030). Hooks must use the right primitive for the job. The behavioral constraint documentation is now in ARCHITECTURE.md and tested. - - Remaining gap: new hooks are still occasionally authored with the wrong type because the failure mode is silent. - - A prompt hook that should be advisory becomes an accidental gate, and nothing in the build warns about it. - - v2.0.0-dev.28 surfaced a parallel mismatch: `workflow-pre-pr`'s escape hatch for a consumed `[Unreleased]` section only covered tagged HEAD, but `/loaf:release` uses `--no-tag` (tags land on main post-merge). The hook blocked a legitimate release-commit PR. Worked around with a `[Unreleased]` placeholder line, but the root problem is that hook contracts drift from skill assumptions without any cross-layer validation. - -3. **Release flow hardening** (new, exposed by v2.0.0-dev.28 release; expanded by v2.0.0-dev.31). The release skill's step order does not match hook contracts in practice. `validate-push` blocks any push without a version bump + CHANGELOG update; `workflow-pre-pr` blocks any PR whose `[Unreleased]` is empty. `/loaf:release` as currently written pushes before bumping (blocked) OR bumps before pushing and consumes `[Unreleased]` (blocked at PR creation). Path forward: rewrite the release skill's step order to bump → push → PR, and extend `workflow-pre-pr` and `validate-push` to accept a `chore: release v` HEAD commit as an escape hatch the way tagged HEAD is accepted today (shipped in SPEC-031, replacing the rejected `release:` shape that never passed `@commitlint/config-conventional`). - - v2.0.0-dev.31 release surfaced three additional friction points concretely. First, `loaf release` CLI silently overrode curated `[Unreleased]` entries with auto-generated commit-subject jargon — the release skill's docs describe a "preserve curated entries" path the CLI doesn't implement. Required a follow-up commit (`382e474d`) to rewrite the changelog from the user's perspective. Second, `validate-push` rejects the `release: vX.Y.Z` commit shape on any project pinned to `@commitlint/config-conventional` — Loaf-using projects that adopt commitlint cannot use the release flow without rewording the commit by hand. Third, bundled artifacts (lockfiles, `plugins/loaf/bin/loaf`, build outputs) recurringly leak into commits whose primary scope is unrelated; in this release Codex review caught this twice across two different PRs (lockfile in PR #36, `plugins/loaf/bin/loaf` in `13ce968d`), each requiring a follow-up to split. - - v2.0.0-dev.32 (PR #40) hit two of the same friction points again: `loaf release` auto-generated commit-subject CHANGELOG jargon (required `3abf59f5` follow-up to rewrite from user perspective), and emptied `[Unreleased]` after the bump (required `5a567dc7` and `91159be5` ceremony commits to satisfy `workflow-pre-pr`). Recurrence reinforces SPEC-031 as a real release-experience tax — every release pays it. - - **v2.0.0-dev.33 (SPEC-031, PR #41) shipped** the canonical 5-step release flow: `loaf release --pre-merge` → `gh pr create` → review → `gh pr merge --squash` → `loaf release --post-merge`. The chore-shape commit cutover, hook escape hatches, monorepo discovery, release-only PR classifier, curated-entries preservation, and stub re-insertion all landed atomically in one PR that dogfooded the very flow it implemented. Tag/push/GH-release/branch-cleanup are now a single `--post-merge` invocation. - - **Meta-learning: pre-push Codex review is a release-flow gate.** The Codex review of the implementation (run between local green and `git push`) caught two P0s — a divergent base resolver in `post-merge.ts` and a missing real-commit subject test — plus one "non-blocking" stub-form finding that turned out to be a real production bug in `workflow-pre-pr`'s empty-section detector (would have allowed feature PRs without changelog entries to silently pass). Outsider review on a complete-but-unpushed branch is a higher-leverage moment than post-PR comments because rework is free; SPEC-031 itself benefited from a pre-breakdown Codex review of the spec text, confirming the pattern across both ends of the workflow. - - **New polish layer surfaced during the ship.** Three follow-ups that aren't release-flow defects but adjacent build/lockfile hygiene: `TASK-149` (`loaf release`'s build step runs content-only `loaf build`, not full `npm run build` — released a stale CLI bundle, caught by the new CI verifier), `TASK-148` (`extractUnreleasedEntries` flattens `### Added`/`### Changed` subsection headers — "verbatim" was implemented as list-items-only), `TASK-136` (pre-commit guard against bundled-artifact leakage — recurring pattern from dev.31 + dev.32 documented but not yet fixed). These are the next iteration's release-experience tax. - - **CI flipped from fixer to verifier (ADR-012).** `Build Distributions` workflow used to auto-commit and push build outputs back to `main`; branch protection rejected it (`GH013`) every run. New design: verify-only with diff-on-failure debugging, also runs on `pull_request`. Caught two real determinism bugs (lockfile/install drift on `yaml@2.8.2` vs `2.8.3`, and the TASK-149 content-only build step) that auto-push would have papered over. Build determinism contract is now explicit: bundled deps are part of the contract, lockfile is authoritative, `npm ci` before any commit-able rebuild. - -4. **Agent routing enforcement** (next: SPEC-022). Profiles exist and build to all targets, but nothing makes the harness use them. A developer spawning a generic agent gets no tool boundaries, no naming convention, no behavioral contract. - - The spec proposes hook-assisted routing: a PreToolUse hook on Agent that enriches profile-based spawns and warns on generic ones. Nudge-based, never blocking. - - For the team lead persona, this is the difference between "we have agent profiles" and "agents actually behave consistently." - -5. **Backend abstraction** (next: SPEC-023). Skills reference Linear MCP tools directly (~80 references across 12+ files). The CLI should be the protocol layer with pluggable backends -- same `loaf task` commands, different storage (local files, Linear, eventually GitHub Issues). - - This also completes the Python/Bash to TypeScript migration (38 scripts remaining), eliminating Python and Bash as runtime dependencies. - - For the solo developer, this means Loaf works without Linear. For the team lead, the tool choice is a config toggle, not a skill rewrite. - - **Significant progress from v2.0.0-dev.29 (Linear-native mode, ADR-011):** skills no longer hard-code Linear MCP tool names in every branch — they branch explicitly on `integrations.linear.enabled` in `.agents/loaf.json`. Same skills, two modes (local-tasks and Linear-native). The full abstraction is still ahead, but the skills' mode-awareness is now the contract to extend. SPEC-023's scope narrows: mostly "extract the Linear calls into a `tracker` CLI subcommand" rather than "rewrite N skills to remove MCP coupling." - -6. **Harness-native surface leverage** (next: SPEC-024). Each harness has unique runtime capabilities (Cursor native agents, Gemini subagents and hooks, OpenCode runtime plugins). Loaf currently deploys skills as the lowest common denominator. - - Gemini is still modeled as "skills only" despite now supporting a richer native surface. - - SPEC-024 proposes a surface-first target model: shared source, per-target native delivery. The payoff is that each target feels native rather than aliased through another tool's layout. - - Per-harness gap analysis surfaced during SPEC-033 implementation: - - **Gemini** is the largest gap — modeled as "skills only" but the harness now supports subagents and hooks. SPEC-024 should prioritize Gemini hook + agent registration. - - **Codex** has agent registration that Loaf doesn't use (we rely on `codex:rescue` agents in our own workflows already). Adding first-class Codex agent support is high-leverage. - - **Cursor** native `subagent_type` routing composes with SPEC-022. - - **Amp's** plugin API is upstream-limited: it dispatches exactly four events (`tool.call`/`tool.result`/`agent.start`/`agent.end`) — no session-lifecycle dispatch despite the binary internally emitting `session.start`. Loaf's Amp target is correctly scoped to tool events; session-lifecycle features (SOUL.md self-healing, etc.) are not viable on Amp without upstream changes. SPEC-024 should reflect this constraint rather than try to work around it. +- **Journal reliability across installed targets.** Converge content-addressed installation, target adapter ownership, capability diagnosis, and isolated installed-runtime dogfood without mutating users' production state. +- **Change-first workflow consistency.** New bounded work uses `docs/changes/YYYYMMDD-slug/change.md`, validated with `loaf change check`. Existing spec and task records remain supported compatibility surfaces until deliberately converted. +- **Evidence-driven target support.** Keep capability classifications conservative, version-pinned, and reproducible. Promote native behavior only after the installed target proves model-visible delivery; otherwise retain narrower runtime gating or an explicit fallback. +- **Durable knowledge with low ceremony.** Preserve decisions, discoveries, and operational lessons where later work can retrieve them, while removing lifecycle machinery and planning vocabulary that do not carry product meaning. ## Strategic Tensions -These are not problems to solve -- they are tradeoffs to manage. Each has surfaced repeatedly during implementation. - -**Portability vs. native leverage.** Writing for the lowest common denominator (skills only) leaves harness-specific features unused. But harness-native code (hooks, agents, runtime plugins) is not portable. SPEC-024 proposes a surface-first model: shared authoring with per-target native delivery. The cost is clear -- every native surface adds to the test matrix and maintenance burden. The benefit is that each harness feels native rather than lowest-common-denominator. The tension will not resolve; it requires ongoing judgment about where to invest per-target effort and where skills alone are sufficient. - -**Automation vs. explainability.** Hooks that "just work" are invisible, but invisible behavior is hard to debug when it breaks. Plugin caching is the canonical example: the framework cached a stale hook handler, the hook silently misbehaved, and the failure was indistinguishable from a logic error. The `validate-push` hook going from blocking to advisory (SPEC-015 to dev.12) is another -- it blocked valid pushes silently until the behavior was observed and corrected. Every automation decision must weigh the cost of silent failure against the cost of manual intervention. The solo developer can tolerate more automation (they can debug it). The team lead cannot (their developers will file bugs). - -**Convention vs. flexibility.** The framework is opinionated about workflow (spec, tasks, code, learn), but projects vary enormously. Too rigid and users fight the framework; too flexible and the opinions do not hold. The current balance -- strict pipeline, flexible domain skills -- has held through 24 shipped specs. But all of that usage has been on Loaf itself, a project that was designed around the pipeline. The first real test is when someone installs Loaf on a project with an existing workflow and existing conventions that conflict with Loaf's opinions. - -**Skill depth vs. skill breadth.** 32 skills across 8 languages, 6 workflow phases, and 5 engineering domains. Each skill competes for context window space. Claude's 250-character description truncation means routing quality depends on the first sentence of every skill description. Adding more skills improves coverage but degrades routing accuracy. The SPEC-014 description rewrite improved routing, but the fundamental constraint -- finite context, growing skill count -- remains. - -**Test-fixture isolation vs. development speed.** `cli/commands/report.test.ts > "scaffolds a report"` was silently broken for 17+ commits because `cli/commands/check.test.ts` used a cwd-relative fixture (`join(process.cwd(), ".test-check-command")`) that raced against report's subprocesses under vitest's default file parallelism. Per-file runs passed; full-suite runs failed non-deterministically. The current response (v2.0.0-dev.28) migrates `check.test.ts` to `mkdtempSync` and sets `fileParallelism: false` as a defensive default. The tension: parallel test execution is fast, but subprocess-spawning tests must use OS-tmp isolation to prevent cross-file pollution, and nothing in the test authoring path forces this. Options to consider: a lint rule that flags `join(process.cwd(), ...)` in test files; a shared test helper that creates isolated tmpdirs; or a per-file-only default in vitest with opt-in parallelism for pure tests. - -**Refactoring artifact taxonomy and ambiguity-funnel discipline (SPEC-034).** Specs are feature-shaped and assume convergent intent; refactoring and bug-fix work want lighter artifacts that reflect their probing nature. SPEC-034 ships PLAN as a minimal ad-hoc shape and surfaces three downstream questions captured as ideas: +**Portability versus native leverage.** A shared skill should express the common contract, but each native adapter expands the compatibility and test surface. Native behavior earns its place only when it is observable and maintainable. -- `20260501-225251-spec-plan-tasks-artifact-taxonomy` — the broader SPEC-as-PRD / PLAN-as-strategy / TASKS-as-agent-native taxonomy. Deferred until the first PLAN ships in the wild and the shape can be evaluated against real use. -- `20260501-225335-shape-spawned-ideas-harness` — `/shape` has no discipline for capturing adjacent concepts that surface during interviews. The mechanism (`/idea`, `related:`, `/triage`, `/reflect`) exists; the workflow tying them together does not. -- `20260501-231922-plan-lifecycle-cli-doctor-housekeeping` — plans need lifecycle infrastructure (list, archive, doctor recognition, housekeeping awareness) parallel to specs. Originally Track C of SPEC-034; extracted because lifecycle is a distinct product surface from refactoring-skill scope. -- `20260501-231923-shape-glossary-evolution-deferred` — `/shape` evolution to participate in glossary mutation. Removed from SPEC-034 because `/shape` is an upstream ambiguity funnel; writing to a stability-focused glossary from an ambiguity-resolving step risks polluting canonical vocabulary. Revisit after `/architecture` and `/refactor-deepen` validate the convention. +**Automation versus explainability.** Invisible automation is convenient until it fails. Ownership manifests, diagnostics, isolated smoke tests, and explicit degradation make failures inspectable without requiring hand-edited global configuration. -The tension is real: every workflow skill that wants to surface or stabilize vocabulary must decide *how much commitment to encode*, and the answer depends on where in the convergent-divergent funnel the skill lives. The current resolution (downstream skills mutate; upstream skills observe) is provisional and will be revisited. +**Convention versus compatibility.** Change-first is the current model for new work, while existing SQLite tasks, `SPEC-*` records, and their CLI commands remain real supported data. Compatibility should preserve access without keeping retired workflow assumptions in current guidance. -## What We Do Not Know Yet +**Durability versus noise.** The journal must retain information that changes future decisions, not duplicate lifecycle state or syntheses that can be derived from source, git, and pull requests. -- Whether the pipeline works for teams. All usage so far is solo development on Loaf itself. The team lead persona is designed from first principles, not validated by observation. -- Whether agent routing enforcement (SPEC-022) changes behavior meaningfully or just adds ceremony. The profiles are well-defined, but Claude may ignore routing nudges the way it ignores other soft instructions. -- Whether harness-native leverage (SPEC-024) is worth the maintenance cost. Six targets is already a wide surface. Adding native hooks, agents, and settings per target multiplies the test matrix. -- Whether backend abstraction (SPEC-023) is the right scope -- should it be narrower (just remove Linear references) or wider (full plugin system with arbitrary backends)? -- Whether plugin caching is a solvable development friction or an inherent platform constraint that Loaf must design around permanently. -- Whether journal continuity quality — the derived start digest plus voluntary `wrap` entries — matches hand-written session summaries in practice. The enrichment path SPEC-056 removed showed scope-filtering and conciseness issues; the open question is whether the layered digest degrades gracefully when a conversation dies without a wrap. +## Open Questions -These are questions that can only be answered by shipping the next round of specs and observing what breaks. +- Which target-native signals can provide durable event identity and trustworthy success evidence without coupling Loaf to unstable client internals? +- How should scheduled client-version discovery produce reviewable candidate evidence without automatically changing capability classifications? +- Where does target-native behavior materially improve the user experience enough to justify its maintenance and installed-test burden? +- How well does Change-first workflow adoption hold outside Loaf itself, particularly for teams with existing trackers and conventions? diff --git a/docs/VISION.md b/docs/VISION.md index 0546096b4..8f55ecb8e 100644 --- a/docs/VISION.md +++ b/docs/VISION.md @@ -6,11 +6,11 @@ An opinionated agentic framework that makes AI coding assistants structured, por ### Portable Knowledge -Write skills once, deploy to six harnesses. Skills are the universal knowledge layer that works everywhere. Profiles and hooks adapt per target. Better skill descriptions improve all targets simultaneously. +Write skills once, deploy to supported harnesses. Skills are the universal knowledge layer that works everywhere. Profiles and hooks adapt per target. Better skill descriptions improve all targets simultaneously. ### Structured Execution -Every change flows through a deliberate pipeline: Idea, Spec, Tasks, Code, Learnings. No scope creep, no lost context, no "what were we doing?" Each phase has clear inputs, outputs, and quality gates. +Ideas may be explored before `/shape` turns the chosen direction into a bounded Change. The Change carries the product and verification contract through implementation, review, and shipping; release remains a separate project-level operation. ### Bounded Autonomy @@ -18,14 +18,14 @@ Functional profiles define what agents can mechanically touch (tool access). Ski ### Continuity -Work survives context loss, compaction, tool restarts, and cross-conversation handoffs. The project journal is external memory. The pipeline's three-artifact model (spec, tasks, journal) means no single failure point can lose the thread. +Work survives context loss, compaction, tool restarts, and cross-conversation handoffs. The project journal is external memory, while Change artifacts and compatible task records keep intent and execution inspectable outside any one conversation. ## What Success Looks Like A developer installs Loaf and immediately gets: - **Consistent agent behavior across tools** -- same skills, same conventions, different runtimes -- **A pipeline that prevents scope creep** -- specs bound the work before code is written +- **Bounded work that prevents scope creep** -- Changes define the intended outcome, boundaries, and proof before implementation - **Project journal history that enables handoff** -- pick up where you left off, or hand off to a colleague - **Hooks that enforce quality without friction** -- secrets scanning, commit conventions, push guards - **Domain expertise that loads automatically** -- the right engineering standards for the current task @@ -36,4 +36,4 @@ A developer installs Loaf and immediately gets: **Not Claude-only.** Multi-target by design. Claude Code is the primary development target, but skills are authored once and built for all supported harnesses. -**Not opinionated about what you build.** Opinionated about *how* you build it. The pipeline, conventions, and quality gates are fixed; the domain knowledge is yours. +**Not opinionated about what you build.** Opinionated about *how* you build it. The Change contract, conventions, and quality checks are explicit; the domain knowledge is yours. diff --git a/docs/changes/20260710-journal-reliability-foundation/change.md b/docs/changes/20260710-journal-reliability-foundation/change.md index 3936b5e57..6707755dd 100644 --- a/docs/changes/20260710-journal-reliability-foundation/change.md +++ b/docs/changes/20260710-journal-reliability-foundation/change.md @@ -334,9 +334,9 @@ Append-only lineage decisions supersede earlier entries through exact scope and | Target | Current evidence | Completion success/result signal | Planned mechanism | Fallback | |--------|------------------|----------------------------------|-------------------|----------| -| Claude Code | Exact CLI 2.1.207 startup is model-visible in the retained plugin-dir smoke; resume, clear, and compact remain candidate fixture modes | Unknown until real PostToolUse payload fixtures prove exit/result semantics | Native SessionStart delivery; startup is the only exact-version model-visible proof and compact continuity is `SessionStart:compact`, not `PostCompact` | Managed instruction to run `loaf journal context`; explicit CLI; no automatic completion when unproven | +| Claude Code | Exact CLI 2.1.218 startup is model-visible in the retained plugin-dir smoke; resume, clear, and compact remain candidate fixture modes | Unknown until real PostToolUse payload fixtures prove exit/result semantics | Native SessionStart delivery; startup is the only exact-version model-visible proof and compact continuity is `SessionStart:compact`, not `PostCompact` | Managed instruction to run `loaf journal context`; explicit CLI; no automatic completion when unproven | | Cursor | Native hook projection exists and is closest to Claude semantics; real installed smoke still required | Unknown until target payload/runtime smoke | Target payload adapter plus native context delivery where model-visible; completion capture only with proven signal | Managed instruction plus explicit CLI; no automatic completion when unproven | -| Codex | Installed `codex-cli 0.144.1` reports stable hooks, accepts SessionStart/UserPromptSubmit/Stop, and parses user-layer execpolicy rules whose exact `allow` prefixes run outside the workspace sandbox without prompting; the isolated `CODEX_HOME` startup smoke on `darwin-arm64` observes exact native `SessionStart` `additionalContext` and the model returns its random marker exactly; global home, resume, clear, compact, and Windows runtime remain candidate | Unknown; SessionStart capability does not imply PostToolUse result fidelity | Install the current-schema SessionStart adapter with a trusted absolute executable rendered at install, retain hardened journal guidance, and classify compaction and completion separately | Managed skill/instruction to run `loaf journal context` plus explicit CLI; global-home, Windows, and unproven lifecycle modes remain gated; body/file-consuming and path-taking leaves remain gated; no automatic completion when unproven; fail visibly when the managed policy is absent, conflicted, or bypassed | +| Codex | Exact `codex-cli 0.145.0` startup is model-visible in the retained isolated-`CODEX_HOME` smoke on `darwin-arm64`; the earlier 0.144.1 source and policy proof remains the basis for candidate resume, clear, compact, and execpolicy classifications, which are not promoted for 0.145.0 | Unknown; SessionStart capability does not imply PostToolUse result fidelity | Install the current-schema SessionStart adapter with a trusted absolute executable rendered at install, retain hardened journal guidance, and classify compaction and completion separately | Managed skill/instruction to run `loaf journal context` plus explicit CLI; global-home, Windows, and unproven lifecycle modes remain gated; body/file-consuming and path-taking leaves remain gated; no automatic completion when unproven; fail visibly when the managed policy is absent, conflicted, or bypassed | | OpenCode | CLI 1.17.18 isolated-XDG request smoke proves the exact marker is model-visible through `experimental.chat.system.transform` `output.system`; resume and compact remain candidates, and startup has no distinct native signal | Bash exit status is source-proven; operation success and durable identity remain unproven, so completion is disabled | Use per-request `experimental.chat.system.transform` `output.system` and `experimental.session.compacting` `output.context`; root lookup without `parentID` fails closed while child/background classification uses `parentID` | Managed instruction plus explicit CLI for bypasses; no automatic completion; bypass missing/disabled plugin, attached/remote server without candidate plugin, missing state, untested version | | Amp | `tool.call`/`tool.result` are available, but no root identity is proven; `agent.start` is only a foreground-turn candidate because root-only identity cannot be proven; startup/resume/compact have no distinct native signals | Generic done/error/cancelled is source-proven, but durable operation success, identity, and child suppression are unproven, so completion is disabled | No automatic context; keep the `agent.start` foreground-turn candidate only as classified evidence and disable policies where foreground children are indistinguishable; candidate plugin paths are `XDG_CONFIG_HOME/amp/plugins` or `HOME/.config/amp/plugins` | Honest managed instruction plus explicit `loaf journal context` and CLI fallback; bypass missing/disabled plugin, legacy-only `~/.amp` installation, missing state, or untested version; legacy-path retirement belongs to U9; no automatic completion | @@ -387,13 +387,14 @@ Every schema migration is backup-first, idempotent, and tested from the current - **U8 evidence:** The version-3 target-capability registry records exact platform-scoped identities, per-mode triggers, retained source evidence, and explicit candidate/unsupported boundaries across the build targets. Claude Code 2.1.207 startup, Codex CLI 0.144.1 startup on `darwin-arm64` in an isolated `CODEX_HOME`, and OpenCode CLI 1.17.18 request delivery in isolated XDG now have retained model-visible smoke proof with strict receipts and current artifact hashes. OpenCode request is supported through `experimental.chat.system.transform` `output.system`; startup has no distinct native signal, resume is a transform candidate after reopen, compact is a compaction candidate, and completion remains disabled because operation success and durable identity are unproven. Cursor IDE 3.11.19 and cursor-agent 2026.05.09-0afadcc remain separate exact-version candidate records handled by one fixed `cursor-session-start-v1` adapter; focused tests cover complete active-truth delivery, native background suppression, and generated-hook parity, but both remain candidate because the safe cursor-agent preflight found no `--no-session-persistence` boundary and the IDE was not independently smoked. Amp has no automatic context claim: `agent.start` is a foreground-turn candidate whose exact reason is that root-only identity cannot be proven, while startup/resume/compact and completion are unsupported with the managed explicit-context fallback; candidate plugin paths are `XDG_CONFIG_HOME/amp/plugins` or `HOME/.config/amp/plugins`, and legacy `~/.amp` retirement belongs to U9. Pi remains deferred and is not a build target. U8 may close with this honest Amp fallback; any newly discovered target mode remains unsupported until classified. - **U8 adapter and adversarial evidence:** OpenCode gates model-visible request/compaction delivery and the `detect-linear-magic` capture hook on a fail-closed root-session lookup; enforcement and unrelated post-tool hooks remain active. Amp preserves documented `tool.call`/`tool.result` enforcement behavior but omits only `detect-linear-magic` because its foreground events cannot distinguish root work from child work; automatic context also stays disabled. Shared workflow guidance now makes startup, compaction, and resumption claims conditional on the exact target-mode capability and directs candidate/unsupported modes to explicit `loaf journal context`. Strict receipt validators bind Claude and Codex native paths to the recorded platform and target root; matching binary bytes and hashes at platform-swapped or cross-target paths are rejected. Registry tests separately reject stale versions, malformed receipts, missing artifacts, hash drift, unsupported bypasses, and candidate evidence presented as support. - **U8 verification and review:** `LOAF_VALIDATE_TYPESCRIPT=1 npm run build` passed all targets and synchronized generated Go artifacts. Fresh retained smokes passed for Claude startup, Codex startup, and OpenCode request delivery; the OpenCode receipt additionally proves plugin load, root-session lookup, no supplied auth, and disposable-state cleanup. The strict capability suite, 19 Node smoke-parser tests, `npm run test`, `npm run typecheck`, executable Change check, render-drift, ephemeral-provenance, check-secrets, validate-commit, security-audit, and `git diff --check` passed. The parity regression test was falsified by the former unconditional Amp-hook expectation and now requires the unsupported capture hook to remain absent while preserving every enforcement hook. Initial final reviews found the omitted Amp missing/disabled-plugin bypass and substitution-damaged generated guidance; after correcting both and sweeping the U8-touched orchestration sources, final Sol/high and Claude Opus verification returned `APPROVE` with no blocking findings. Claude separately noted pre-existing plural-substitution defects in unrelated housekeeping, wrap, and foundations guidance; U9's documentation reconciliation retains that boundary. -- **U9 content-ownership primitive:** managed fences use version-independent body fingerprints with legacy migration, tamper refusal, atomic user-prose preservation, and strict fence parsing; the shared skill manifest v2 records deterministic per-tree digests with v1 migration, stale/missing convergence, foreign/tamper/race refusal, and rollback, covered by mode, symlink, strict-manifest, and fence-parser tests. Rebuilding changed the candidate native binary hash, so the strict capability suite failed closed on stale receipts; fresh isolated Claude startup, Codex startup, and OpenCode request smokes passed, refreshed retained hashes, and integrated tests passed afterward. +- **U9 content-ownership primitive:** managed fences use version-independent body fingerprints with legacy migration, tamper refusal, atomic user-prose preservation, and strict fence parsing; the shared skill manifest v2 records deterministic per-tree digests with v1 migration, stale/missing convergence, foreign/tamper/race refusal, and rollback, covered by mode, symlink, strict-manifest, and fence-parser tests. Rebuilding changed the candidate native binary hash, so the strict capability suite failed closed on stale receipts; fresh isolated Claude Code 2.1.218 startup, Codex 0.145.0 startup, and OpenCode 1.18.4 request smokes passed, refreshed retained hashes, and integrated tests passed afterward. - **U9 target-adapter manifest slice:** every native build target now emits one deterministic strict manifest whose adapter identities come from the validated version-3 capability evidence and whose managed-instruction digest is version-independent. Concrete hook/plugin artifacts bind content plus permission mode, while merged user hook projections retain their existing mode; malformed metadata, source or installed content/mode drift, unsafe paths, symlinks, duplicate keys, and trailing JSON fail closed. OpenCode, Cursor, Codex, and Amp installs persist strict ownership state, converge same-version changes, migrate recognized legacy surfaces, retire unchanged stale artifacts, preserve foreign content, reject unowned or modified destinations, revalidate each destination immediately before mutation, and roll back only actual mutations in reverse order with restoration failures surfaced alongside the primary error and current recovery state. Claude Code receives the build manifest but remains intentionally outside CLI install ownership because the CLI has no Claude installer. Focused manifest/install tests, the full internal CLI suite, `go vet ./...`, formatting, and diff checks passed; this slice does not complete V12 or U9. +- **U9 durable-guidance reconciliation:** living project guidance, generated skills, operational fixtures, release examples, and runtime comments now describe Change-first work and semantic execution boundaries without leaking implementation-unit names, numbered development stages, volatile inventory counts, or completed migration narration. Historical Change/SPEC/ADR evidence, Change unit syntax, schema migration identities, compatibility keys and commands, and legitimate domain terms remain intact. Content hygiene tests pin the rewritten authority surfaces and reject implementation-unit prefixes in operational runner/evidence filenames plus `loaf-uN` fixture labels in runtime code. Every target was rebuilt from the reconciled sources, and the isolated full suite, typecheck, capability-runner tests, `go vet`, executable Change check, repository hooks, and diff checks passed. - **Search-parity incident evidence:** a real global divergence belonging entirely to another project reproduced Claude Code's nonblocking SessionStart failure because schema validation incorrectly treated the derived FTS index as a whole-database gate. A two-project regression falsified the fix under the old gate, then proved current-project context, recent, and log remain available while global parity stays non-ready and search still returns the typed divergence refusal. The rebuilt Claude plugin's exact SessionStart command exits zero with no stderr against that unchanged database; no global repair or unrelated-project mutation was performed. - **Direct evidence passed during implementation:** independent two-process `journal defer` convergence passed at count 10; schema-upgrade rollback and stale-source refusal tests passed; state, CLI, and command-surface suites passed in the integrated workspace. Atomic staged storage copy SIGKILL and concurrent-publisher coverage passed at count 10 and under `-race` count 3. Final Sol review was clean. - **Project-move race evidence:** a deterministic independent-store claimant race passed at focused count 10 and under `-race` count 3; disabling transactional rejection falsified the guard. The protected path retained one owner/current mapping and both projects' journals remained preserved. - **Final verification gates:** `LOAF_VALIDATE_TYPESCRIPT=1 npm run build` passed all targets with Go artifact synchronization; `npm run test` and typecheck passed. Executable Change check passed with only the expected unmaterialized `release-after` warning. Render-drift, ephemeral-provenance, changed-text secret, validate-commit, and security checks passed. Isolated public smokes proved manual origin capture, atomic defer/search, current schema, backup plus verify recovery/provenance readiness, and contract-v2 synthesis/lineage/blocker/Change projection without touching the global database. -- **Remaining boundary:** U7 normalized envelopes, outcome-aware trusted seams, namespaced origins, lifecycle suppression, safe-hook preflight, and replay evidence are implemented. U8 now has strict installed model-visible proof for Claude startup, Codex startup, and OpenCode request delivery; OpenCode completion is disabled, Cursor remains candidate, and Amp remains an explicitly unsupported automatic-context fallback with a foreground-turn candidate trigger. The U9 content-ownership primitive and target-adapter manifest slice are implemented: deterministic strict build manifests cover Claude Code, OpenCode, Cursor, Codex, and Amp, while strict CLI install ownership covers OpenCode, Cursor, Codex, and Amp because Claude Code intentionally has no CLI installer. U9 still owns doctor diagnostics, broader documentation reconciliation, legacy `~/.amp` retirement, isolated builds/upgrades, and approved real installed cross-harness dogfood; V12 and the root Change remain open. +- **Remaining boundary:** U7 normalized envelopes, outcome-aware trusted seams, namespaced origins, lifecycle suppression, safe-hook preflight, and replay evidence are implemented. U8 now has strict installed model-visible proof for Claude startup, Codex startup, and OpenCode request delivery; OpenCode completion is disabled, Cursor remains candidate, and Amp remains an explicitly unsupported automatic-context fallback with a foreground-turn candidate trigger. The U9 content-ownership primitive, target-adapter manifest slice, and durable-guidance reconciliation are implemented: deterministic strict build manifests cover Claude Code, OpenCode, Cursor, Codex, and Amp, while strict CLI install ownership covers OpenCode, Cursor, Codex, and Amp because Claude Code intentionally has no CLI installer. U9 still owns doctor diagnostics, legacy `~/.amp` retirement, isolated builds/upgrades, and approved real installed cross-harness dogfood; V12, U9, and the root Change remain open. ## Verification Contract diff --git a/docs/changes/20260710-journal-reliability-foundation/research/claude-code-2.1.218-plugin-startup-smoke.json b/docs/changes/20260710-journal-reliability-foundation/research/claude-code-2.1.218-plugin-startup-smoke.json index 68b50bb92..6580562ad 100644 --- a/docs/changes/20260710-journal-reliability-foundation/research/claude-code-2.1.218-plugin-startup-smoke.json +++ b/docs/changes/20260710-journal-reliability-foundation/research/claude-code-2.1.218-plugin-startup-smoke.json @@ -1,6 +1,6 @@ { "evidence_version": 2, - "timestamp": "2026-07-24T22:31:44.205Z", + "timestamp": "2026-07-25T00:20:37.215Z", "target": "claude-code", "surface": "cli", "version": "2.1.218", @@ -41,7 +41,7 @@ "stderr_empty": true, "model_visible_marker_observed": true, "assistant_marker_match": true, - "marker": "LOAF_CLAUDE_STARTUP_SMOKE_82C9A319C829", + "marker": "LOAF_CLAUDE_STARTUP_SMOKE_F8C330ED60BE", "hook_observation": { "event_name": "SessionStart:startup", "native_json": true, @@ -50,8 +50,8 @@ }, "candidate_artifacts": { "hooks_path": "plugins/loaf/hooks/hooks.json", - "hooks_sha256": "5c7343a34af37d6c6e930981f71e405b8023975de4146822058f98c15251b7c2", + "hooks_sha256": "564917493bfa795fee8a067e235e13eec5f992e098cb94540d2202cc6fe3cad4", "native_binary_path": "plugins/loaf/bin/native/darwin-arm64/loaf", - "native_binary_sha256": "06c9baba4ab5a570df6b8e1f7deba3fc346c24b832882e49563108efe7d11d36" + "native_binary_sha256": "ec0548a18a0afaf63f866d37a9a636449106d6db3277f2da65c84639aa4ba9c8" } } diff --git a/docs/changes/20260710-journal-reliability-foundation/research/codex-0.145.0-isolated-startup-smoke.json b/docs/changes/20260710-journal-reliability-foundation/research/codex-0.145.0-isolated-startup-smoke.json index 0835817f5..f0dc1cf33 100644 --- a/docs/changes/20260710-journal-reliability-foundation/research/codex-0.145.0-isolated-startup-smoke.json +++ b/docs/changes/20260710-journal-reliability-foundation/research/codex-0.145.0-isolated-startup-smoke.json @@ -1,6 +1,6 @@ { "evidence_version": 2, - "timestamp": "2026-07-24T22:32:03.850Z", + "timestamp": "2026-07-25T00:20:42.914Z", "target": "codex", "surface": "cli", "version": "0.145.0", @@ -39,7 +39,7 @@ "stderr": "Reading additional input from stdin...", "model_visible_marker_observed": true, "assistant_marker_match": true, - "marker": "LOAF_CODEX_STARTUP_SMOKE_A5533AEA314C", + "marker": "LOAF_CODEX_STARTUP_SMOKE_57B7F146B7E3", "hook_observation": { "event_name": "SessionStart:startup", "native_json": true, @@ -50,6 +50,6 @@ "hooks_path": "dist/codex/.codex/hooks.json", "hooks_sha256": "0f9e3feb7204c3309a7db6a02224ad881f6801a8cdd126ec6222e6d9a804c33d", "native_binary_path": "bin/native/darwin-arm64/loaf", - "native_binary_sha256": "06c9baba4ab5a570df6b8e1f7deba3fc346c24b832882e49563108efe7d11d36" + "native_binary_sha256": "ec0548a18a0afaf63f866d37a9a636449106d6db3277f2da65c84639aa4ba9c8" } } diff --git a/docs/changes/20260710-journal-reliability-foundation/research/opencode-1.18.4-isolated-request-smoke.json b/docs/changes/20260710-journal-reliability-foundation/research/opencode-1.18.4-isolated-request-smoke.json index eb2ef2266..43d47fa70 100644 --- a/docs/changes/20260710-journal-reliability-foundation/research/opencode-1.18.4-isolated-request-smoke.json +++ b/docs/changes/20260710-journal-reliability-foundation/research/opencode-1.18.4-isolated-request-smoke.json @@ -1,6 +1,6 @@ { "evidence_version": 2, - "timestamp": "2026-07-24T22:32:15.899Z", + "timestamp": "2026-07-25T00:20:55.688Z", "target": "opencode", "surface": "cli", "version": "1.18.4", @@ -39,11 +39,11 @@ "root_session_lookup_proven": true, "no_auth_supplied": true, "cleanup_succeeded": true, - "marker": "LOAF_OPENCODE_REQUEST_SMOKE_BB01462EC885", + "marker": "LOAF_OPENCODE_REQUEST_SMOKE_334370E5F8D3", "candidate_artifacts": { "hooks_path": "dist/opencode/plugins/hooks.ts", - "hooks_sha256": "b345ff7ec631d30f009c96d1d3161ba731fa57352a153e71bdf95583640c25e6", + "hooks_sha256": "3aaf803762a52b541ef7ddac008ff87bba20ac5a7ed3940d8018abe610f84873", "native_binary_path": "bin/native/darwin-arm64/loaf", - "native_binary_sha256": "06c9baba4ab5a570df6b8e1f7deba3fc346c24b832882e49563108efe7d11d36" + "native_binary_sha256": "ec0548a18a0afaf63f866d37a9a636449106d6db3277f2da65c84639aa4ba9c8" } } diff --git a/docs/knowledge/build-system.md b/docs/knowledge/build-system.md index d55d41828..7d198b512 100644 --- a/docs/knowledge/build-system.md +++ b/docs/knowledge/build-system.md @@ -10,7 +10,7 @@ covers: consumers: - implementer - reviewer -last_reviewed: '2026-07-03' +last_reviewed: '2026-07-14' --- # Build System @@ -20,7 +20,7 @@ Loaf compiles skills, agents, and hooks from a single source tree into multiple ## Key Rules - **Single source, multiple outputs.** Content is authored in `content/`. The build system transforms it per-target. -- **Two-phase build.** Skills first compile to a shared intermediate (`dist/skills/`), then each target reads from the intermediate. +- **Shared intermediate.** Skills compile to `dist/skills/`, then each target reads that normalized content. - **Targets are additive.** Each target gets what it supports — Claude Code gets everything, while Codex gets skills plus its policy template and current-schema SessionStart context hook. - **Sidecars carry target-specific fields.** SKILL.md has standard fields only. `.claude-code.yaml`, `.opencode.yaml`, etc. carry extensions. Build merges them. - **Shared templates distribute at build time.** `content/templates/` files (`session.md`, `adr.md`) are copied to specified skills via `shared-templates` in `targets.yaml`. @@ -42,7 +42,7 @@ Loaf compiles skills, agents, and hooks from a single source tree into multiple ### Notes -- **Claude Code** bundles a self-contained `loaf` binary in `plugins/loaf/bin/loaf` for hook execution. Hooks are registered in `hooks/hooks.json` (inside the plugin directory), not in `plugin.json`. `plugin.json` silently drops non-matcher session events — a key SPEC-030 finding. +- **Claude Code** bundles a self-contained `loaf` binary in `plugins/loaf/bin/loaf` for hook execution. Hooks are registered in `hooks/hooks.json` because `plugin.json` silently drops non-matcher session events. - **OpenCode and Amp** generate runtime plugins (`hooks.ts` / `.amp/plugins/loaf.ts`) that implement enforcement hooks via subprocess calls to `loaf check`. - **Codex** generates a current-schema `.codex/hooks.json` SessionStart matcher group because Codex `0.144.1` rejects Loaf's legacy flat hook projection; the command and `commandWindows` placeholders are rendered to trusted absolute paths at install. POSIX installs retain the exact two-field command shape and omit the Windows variant; Windows installs render both fields to the same `cmd.exe /C` outer-wrapped command. Isolated `CODEX_HOME` startup on `darwin-arm64` is model-visible smoke-proven; global-home installation, resume, clear, compact, Windows runtime behavior, and completion remain separately unproven. The separately opted-in basic command policy renders one absolute-executable prefix per explicitly classified leaf, while body/file-consuming leaves and path-taking `change check` remain operator-gated. Other harness adapters are not implied. - **MCP servers** are not bundled. `loaf install` detects and recommends MCPs at install time; integration state stored in `.agents/loaf.json`. diff --git a/docs/knowledge/hook-system.md b/docs/knowledge/hook-system.md index 938dc4077..e63f6d338 100644 --- a/docs/knowledge/hook-system.md +++ b/docs/knowledge/hook-system.md @@ -11,7 +11,7 @@ covers: consumers: - implementer - reviewer -last_reviewed: '2026-07-03' +last_reviewed: '2026-07-14' --- # Hook System @@ -41,7 +41,7 @@ Enforcement hooks without explicit `type:` auto-dispatch as `loaf check --hook < | UserPromptSubmit | Every user message | No | Context injection, orchestration conventions | | TaskCompleted | Task marked complete | No | Journal auto-entry for task events | -There is no SessionEnd or Stop journal obligation under journal-first (SPEC-056): the SessionEnd hook was removed, and no hook writes back to a session record (the general Stop-circularity caution still governs any future stateful hook — see [ARCHITECTURE.md](../ARCHITECTURE.md#hook-type-behavioral-constraints)). +There is no SessionEnd or Stop journal obligation: the SessionEnd hook is absent, and no hook writes back to a session record. The general Stop-circularity caution still governs any future stateful hook; see [ARCHITECTURE.md](../ARCHITECTURE.md#hook-type-behavioral-constraints). ### Hook JSON Context @@ -127,7 +127,7 @@ The `detect-linear-magic` hook runs as a pre-tool command (`loaf journal log --d ## Conversation Hooks -Registered under `session:` in hooks.yaml with an `event:` field. Journal-first (SPEC-056) removed the session entity, so these hooks emit the derived continuity digest or auto-log events — none of them open, close, or mutate a session record: +Registered under `session:` in hooks.yaml with an `event:` field. These hooks emit the derived continuity digest or auto-log events; none opens, closes, or mutates a session record: | Hook | Event | Dispatch | Purpose | |------|-------|----------|---------| @@ -150,19 +150,19 @@ Post-tool hooks that perform background maintenance: | `generate-task-board` | Edit\|Write | Regenerates TASKS.md when task files change (`loaf task refresh`) | | `kb-staleness-nudge` | Edit\|Write | Tracks covered edits and nudges when covered knowledge is stale | -## Migration History +## Current Hook Boundary -As of SPEC-020, ~30 shell hooks were migrated to skill instructions (Verification sections in SKILL.md) or replaced by `loaf check` enforcement hooks. Eliminated categories: +Language, infrastructure, design, and advisory quality guidance belongs in skill instructions. Deterministic enforcement belongs in `loaf check` hooks. Retired shell-hook categories include: - Language hooks (python-\*, typescript-\*, rails-\*) - Infrastructure hooks (k8s, dockerfile, terraform) - Design hooks (a11y, tokens) - Quality hooks (format-check, tdd-advisory, validate-changelog) -The 4 shared bash libraries (`json-parser.sh`, `config-reader.sh`, `agent-detector.sh`, `timeout-manager.sh`) were also removed. +The former shared Bash helpers (`json-parser.sh`, `config-reader.sh`, `agent-detector.sh`, `timeout-manager.sh`) are no longer part of the active hook runtime. ## Hook Type Behavioral Constraints -Hook types have hard behavioral limits discovered through SPEC-026 and SPEC-030. See [ARCHITECTURE.md](../ARCHITECTURE.md#hook-type-behavioral-constraints) for the full list. Key constraints: +Hook types have hard behavioral limits. See [ARCHITECTURE.md](../ARCHITECTURE.md#hook-type-behavioral-constraints) for the full list. Key constraints: - **Prompt hooks** are binary gates — any non-empty LLM response blocks. Never use for advisory guidance. - **Agent hooks** are read-only (no Edit/Write/Bash). Max 50 turns. diff --git a/docs/knowledge/knowledge-management-design.md b/docs/knowledge/knowledge-management-design.md index 8870d72d1..91f92f369 100644 --- a/docs/knowledge/knowledge-management-design.md +++ b/docs/knowledge/knowledge-management-design.md @@ -8,7 +8,7 @@ topics: covers: - internal/cli/kb.go - docs/knowledge/*.md -last_reviewed: '2026-07-03' +last_reviewed: '2026-07-14' --- # Knowledge Management Design @@ -48,34 +48,35 @@ No AI coding tool does this today. The `covers:` field links knowledge to code p ## Growth Loops -**Loop 1: Staleness → Review → Update.** Code edited → `covers:` match → agent nudged → reviews/updates → resets `last_reviewed`. +**Staleness → Review → Update.** Code edited → `covers:` match → agent nudged → reviews or updates → resets `last_reviewed`. -**Loop 2: Session → Consolidation → Knowledge.** Session ends → hook asks "learned anything?" → agent creates knowledge file → human reviews. +**Conversation → Consolidation → Knowledge.** Before compaction or at an optional wrap → agent identifies durable learning → agent creates or updates a knowledge file → human reviews. ### Hook Scope (Extended Beyond Knowledge) **SessionStart hook** surfaces both knowledge health AND spark status: -- "3 knowledge files relevant. 1 stale." -- "5 unprocessed sparks across 2 brainstorm documents." +- Relevant knowledge files and any stale coverage +- Unprocessed sparks from exploration artifacts This reminds the agent that exploration artifacts exist and may need processing. **PreCompact hook and `/wrap`** prompt for both knowledge consolidation AND spark capture: -- "You modified 3 paths covered by knowledge files. Any updates needed?" +- "You modified paths covered by knowledge files. Any updates needed?" - "This conversation involved exploration. Any sparks worth noting?" -Journal-first (SPEC-056) removed the SessionEnd hook, so this nudge lives at the PreCompact journal-flush point and in the voluntary `/wrap` checkpoint rather than a session-close event. If the conversation produced a brainstorm document, it reminds about the `## Sparks` section. +There is no SessionEnd journal hook, so this nudge lives at the PreCompact journal-flush point and in the voluntary `/wrap` checkpoint rather than a conversation-close event. If the conversation produced a brainstorm document, it reminds about the `## Sparks` section. -## The Original Problem (5 Overlapping Surfaces) +## Memory Surface Boundary -Knowledge accumulates across 5+ surfaces that don't coordinate: -1. `docs/knowledge/` — structured domain knowledge -2. `docs/decisions/` — immutable ADRs -3. Claude Code `MEMORY.md` — cross-session AI context (drifts) -4. Serena `.serena/memories/` — separate AI memory (goes stale) -5. SQLite sessions + temporary draft context — temporary but may become permanent +Knowledge can accumulate across surfaces that serve different owners: -Same facts recorded in 2-3 places. Nothing triggers updates when code changes. Memory layers drift silently. The knowledge management system consolidates these into clear ownership (see Memory Surface Policy below). +- `docs/knowledge/` holds structured project knowledge. +- `docs/decisions/` holds immutable architectural decisions. +- Personal agent memory holds user-level preferences and cross-project context. +- The project journal holds durable events and optional synthesis. +- Conversation context holds temporary working hypotheses. + +Do not duplicate the same fact across these surfaces. The knowledge management system assigns clear ownership and uses coverage metadata to surface potential drift. ## GridSight as Reference Implementation @@ -103,21 +104,21 @@ QMD handles retrieval (collections, search, MCP). Loaf wraps QMD for setup + add canonical terms, aliases, candidate terms, and stabilization without moving glossary prose into the operational task/session index. -## Three Knowledge Lifetimes +## Knowledge Lifetimes ``` PERSISTENT (this person) — crosses all projects, grows over career └→ DURABLE (this project) — lives in git, shared with team - └→ EPHEMERAL (this session) — lives in context window, dies at session end + └→ EPHEMERAL (this conversation) — lives in the context window ``` | Lifetime | What | Where | |----------|------|-------| | **Persistent** | User preferences, expertise, patterns | `~/.config/claude/` (CLAUDE.md, PROFILE.md, memory/) | | **Durable** | Domain knowledge, conventions, decisions | `docs/knowledge/` + `docs/decisions/` + CLAUDE.md | -| **Ephemeral** | Active task context, working hypotheses | SQLite sessions + conversation | +| **Ephemeral** | Active work context, working hypotheses | Conversation context | -Flow: persistent informs durable, durable informs ephemeral. Upward: session insights consolidate into durable knowledge, durable patterns graduate to persistent memory. +Flow: persistent informs durable, durable informs ephemeral. Upward: conversation insights consolidate into durable knowledge, and durable patterns may graduate to persistent memory. ## Knowledge as Extended Agent Memory @@ -130,12 +131,13 @@ The knowledge base is primarily for agents — it's their extended memory. This | `docs/knowledge/` | Domain rules, contracts, architectural patterns, roadmap context | | `docs/decisions/` | Immutable ADRs | | `MEMORY.md` | User preferences, session pointers | -| SQLite sessions | Ephemeral work context | +| Project journal | Durable project events and optional synthesis | +| Conversation context | Ephemeral work context | | Serena memories | **Deprecated for knowledge** — code analysis state only | **Serena:** Keep code intelligence tools (find_symbol, get_symbols_overview). Deprecate memory system for knowledge persistence — with knowledge files + MEMORY.md, Serena memories become a redundant third layer. -## Growth Loop 3: Personal Knowledge Graduation +## Personal Knowledge Graduation Personal knowledge grows through correction, not capture. When you say "don't use bare except clauses," that's a personal preference that applies everywhere — not just this project. @@ -145,7 +147,7 @@ Per-project correction → repeated across N projects → pattern recognized → suggested promotion to global CLAUDE.md → user approves → permanent ``` -v1: convention + documentation only (no automation for cross-project pattern detection). The skill documents what belongs in global CLAUDE.md vs per-project memory. Future: cross-project pattern detection (Mem0 territory), personal knowledge Zettelkasten, expertise graph. +This is a convention and documentation boundary, not an automated cross-project pattern detector. The skill documents what belongs in personal agent instructions versus project knowledge; promotion still requires user approval. ## The Boundary Test: What Goes Where diff --git a/docs/knowledge/skill-architecture.md b/docs/knowledge/skill-architecture.md index b0cfa4616..af2825f1f 100644 --- a/docs/knowledge/skill-architecture.md +++ b/docs/knowledge/skill-architecture.md @@ -13,7 +13,7 @@ covers: consumers: - implementer - reviewer -last_reviewed: '2026-07-03' +last_reviewed: '2026-07-14' --- # Skill Architecture @@ -66,14 +66,14 @@ Skill-specific templates live in `content/skills/{name}/templates/` and are not ## Agent Profiles -SPEC-014 replaced 8 role-based agents with 4 functional profiles and 1 system profile. Each profile is a tool-boundary contract. +Each profile is a tool-boundary contract. Functional profiles define what an agent may touch; the background runner supplies the asynchronous system role. | Profile | Tool Access | Purpose | |---------|-------------|---------| | **implementer** | Full write | Code, tests, config, docs — specialty via skills | | **reviewer** | Read-only | Audits, reviews — mechanical independence | | **researcher** | Read + web | Research, comparison — structured reports | -| **librarian** | Read + Edit (.agents/) | Session lifecycle, state, wrap, pre-compaction preservation | +| **librarian** | Read + Edit (.agents/) | Journal curation, durable artifacts, wrap, pre-compaction preservation | | **background-runner** | Read + Edit | Async non-blocking tasks (system) | Skills load into profiles at spawn time. What an agent *can do* is fixed by profile; what it *knows* comes from skills. @@ -85,8 +85,6 @@ Skills load into profiles at spawn time. What an agent *can do* is fixed by prof | Reference/Knowledge | `false` | python-development, database-design, foundations, git-workflow, orchestration | | Workflow/Process | `true` (default) | implement, research, shape, breakdown, ship, release, housekeeping, wrap | -35 skills total: 19 workflow/default-invocable, 16 non-invocable with `user-invocable: false` (reference/knowledge skills plus the brainstorm technique consumed by explore). - ## Cross-References - [build-system.md](build-system.md) — how skills get distributed to targets diff --git a/docs/knowledge/task-system.md b/docs/knowledge/task-system.md index 092758195..d3489a33e 100644 --- a/docs/knowledge/task-system.md +++ b/docs/knowledge/task-system.md @@ -1,11 +1,12 @@ --- topics: + - changes - tasks - specs - - shape-up - journal - orchestration covers: + - docs/changes/**/*.md - .agents/specs/**/*.md - internal/cli/cli.go - internal/state/task_*.go @@ -15,50 +16,57 @@ covers: consumers: - implementer - reviewer -last_reviewed: '2026-07-03' +last_reviewed: '2026-07-14' --- -# Task System +# Work Records -Loaf implements a Shape Up-inspired task management system: specs define bounded work, tasks break it down, the project journal records execution. +Loaf uses Change artifacts for new bounded work. Existing specs and tasks remain durable compatibility records with supported CLI surfaces, while the project journal records what happened across conversations. -## Key Rules - -- **Complexity-based sizing.** Size by complexity (small/medium/large), not time. Agents don't have time budgets. -- **Priority ordering.** Ship tracks in order; drop from the end if scope tightens. -- **Go/no-go gates.** Binary checks between priority tracks using test conditions. -- **One concern per task.** One agent type, one concern, fits in context with room for exploration. -- **Tasks are agent-authored, human-reviewed.** Agents create tasks via `/breakdown`, humans approve. - -## Pipeline +## Current Workflow ``` -/shape → SPEC file → /breakdown → SQLite tasks → /implement → project journal → Done +/idea or /brainstorm → /shape → docs/changes/YYYYMMDD-slug/change.md + ↓ + loaf change check + ↓ + /implement → review → /ship + ↓ + project journal and /reflect ``` -## Structure +`/release` publishes already-landed work separately. A Change may land through more than one coherent pull request; implementation order belongs in the Change contract and PR boundaries, not in generic permanent labels. + +## Record Types -| Artifact | Location | Purpose | -|----------|----------|---------| -| Specs | `.agents/specs/SPEC-XXX-slug.md` | Bounded work definitions (scope, test conditions, priority order) | -| Tasks | SQLite (`loaf task show/list`) | Individual work items (acceptance criteria, verification) | -| Journal | SQLite (`loaf journal recent/show`) | Project-scoped execution record across every conversation | +| Record | Location | Purpose | +|--------|----------|---------| +| Change | `docs/changes/YYYYMMDD-slug/change.md` | Primary bounded-work contract for new work: problem, scope, implementation units, verification, and done conditions | +| Task | SQLite (`loaf task show/list`) | Existing durable work items with criteria, relationships, and status | +| Spec | `.agents/specs/SPEC-XXX-slug.md` | Existing bounded-work records retained for compatibility and deliberate conversion | +| Journal | SQLite (`loaf journal recent/show`) | Project-scoped decisions, discoveries, commits, and execution context | -`findAgentsDir()` remains relevant for durable `.agents/` content such as -specs, reports, councils, handoffs, and project config. Ephemeral task, -idea, spark, brainstorm, and draft records live in the global SQLite -store after the SPEC-045 cutover; the journal is SQLite-native as well. +`loaf change check` validates Change structure and reports derived executability; `loaf change check --require-executable` requires the implementation contract to be complete. Existing `loaf spec` and `loaf task` commands continue to operate on their records, but they do not define the default artifact for newly shaped work. -## TASKS.json +## Working Rules -`.agents/TASKS.json` was removed by the SPEC-045 cutover. It is rollback -material only, restored by `loaf state restore-ephemerals ` when -explicitly undoing the cutover. Do not recreate it as an index or compatibility -mirror. `loaf check --hook ephemeral-provenance` fails if `TASKS.json` or -tracked ephemeral markdown returns. +- **Bound the outcome before implementation.** State the problem, scope, rabbit holes, implementation units, verification contract, and definition of done in the Change. +- **Keep implementation units coherent.** Use branches, commits, and pull requests as containment boundaries that can be reviewed and landed independently without inventing generic sequencing labels. +- **Use tasks when they carry durable value.** A task should represent one concern with observable completion and explicit relationships; do not create task ceremony merely to mirror a Change section. +- **Keep progress derived where possible.** Git, pull requests, checks, and journal entries are the evidence. Do not add mutable progress fields to Change frontmatter. +- **Preserve compatibility records deliberately.** Existing specs and tasks remain supported until converted; do not rewrite or delete them just to make the vocabulary look current. ## CLI Commands +### `loaf change` + +| Subcommand | Purpose | +|------------|---------| +| `init ` | Scaffold `docs/changes/-/change.md` | +| `check [path]` | Validate a Change and report derived executability | +| `check [path] --require-executable` | Fail unless the implementation contract is structurally executable | +| `list --lineage ` | List retained Changes in one lineage | + ### `loaf task` | Subcommand | Purpose | @@ -68,7 +76,7 @@ tracked ephemeral markdown returns. | `show ` | Display single task details | | `status` | Summary counts | | `create` | Create new task | -| `update ` | Update metadata (status, priority, depends_on, spec) | +| `update ` | Update metadata such as status, priority, relationships, and spec linkage | | `archive [ids...]` | Archive completed tasks in SQLite state | | `refresh` | Compatibility diagnostic; no-op in SQLite-backed projects | | `sync` | Compatibility diagnostic; no-op in SQLite-backed projects | @@ -77,7 +85,7 @@ tracked ephemeral markdown returns. | Subcommand | Purpose | |------------|---------| -| `list` | Show specs with status | +| `list` | Show existing specs with status | | `archive [ids...]` | Move completed specs to `archive/` | ### `loaf journal` @@ -88,32 +96,34 @@ tracked ephemeral markdown returns. | `recent` | Show the recent journal timeline (`--branch`, `--since-last-wrap`) | | `search ` | Full-text search across the project journal | | `show ` | Read one journal entry | -| `context` | Emit the layered continuity digest (latest wrap + branch entries + open tasks) | +| `context` | Emit the layered continuity digest (latest wrap, branch entries, and open tasks) | | `export` | Export the journal to Markdown or JSONL | -## Journal Model (SPEC-056) +## Storage Provenance and Compatibility -The project journal is the only session-related structure. There is no session -entity, status, or lifecycle. Key behaviors: +The SQLite cutover recorded by historical work identity `SPEC-045` moved ephemeral task, idea, spark, brainstorm, and draft records into the global state store. `.agents/TASKS.json` and the corresponding ephemeral Markdown directories are rollback material, not compatibility mirrors. `findAgentsDir()` remains relevant for durable `.agents/` content such as existing specs, reports, councils, handoffs, and project config. -- **Project-scoped events, correlated by harness id.** `journal_entries` rows carry `project_id NOT NULL` and an opaque `harness_session_id` that groups one conversation's entries. Nobody opens, closes, or transitions anything. -- **Concurrency-safe by construction.** Two conversations logging at once — across branches, worktrees, or harnesses — interleave rows with different `harness_session_id` tags, which is correct rather than corrupt. There is no router to misroute and no branch-fallback tier (SPEC-032's session router was superseded). -- **Wrap is an optional checkpoint.** `loaf journal log "wrap(scope): …"` records synthesis worth saving; nothing is ever "unwrapped," and a conversation that ends without one leaves a valid journal. -- **Continuity is derived and ephemeral.** The SessionStart hook runs `loaf journal context --from-hook` to emit a read-time digest that is shown, then discarded. Subagent invocations (`agent_id` present in hook JSON) exit silently and write nothing. +Do not recreate `.agents/TASKS.json` as an index. `loaf state restore-ephemerals ` may restore it only when explicitly undoing the cutover, and `loaf check --hook ephemeral-provenance` detects tracked ephemeral files that return outside that rollback procedure. + +Stale branches may still carry deleted ephemeral files. Rebase or merge current main, keep the deletion side for `.agents/{tasks,ideas,sparks,sessions,brainstorms,drafts}/` and `.agents/TASKS.json`, then run `loaf check --hook ephemeral-provenance`. If rollback is intentional, restore and re-import through the supported state commands rather than maintaining hand-edited mirrors. -### Cross-Branch Reconciliation +The journal-first model was established by historical work identity `SPEC-056`, which superseded the session router associated with `SPEC-032`. These identifiers document provenance, not current workflow instructions. -After SPEC-045, stale branches may still carry deleted ephemeral files. Rebase -or merge main, keep the deletion side for `.agents/{tasks,ideas,sparks,sessions,brainstorms,drafts}/` -and `.agents/TASKS.json`, then run `loaf check --hook ephemeral-provenance`. -If rollback is intentionally needed, use `loaf state restore-ephemerals -` and re-import forward; do not hand-edit restored files as a mirror. +## Journal Model + +The project journal is the only session-related structure. There is no session entity, status, or lifecycle. + +- **Project-scoped events, correlated by harness id.** `journal_entries` rows carry `project_id NOT NULL` and an opaque `harness_session_id` that groups one conversation's entries. Nobody opens, closes, or transitions anything. +- **Concurrency-safe by construction.** Conversations across branches, worktrees, or harnesses may interleave rows with different `harness_session_id` tags without a mutable router. +- **Wrap is an optional checkpoint.** `loaf journal log "wrap(scope): …"` records synthesis worth saving; a conversation that ends without one still leaves a valid journal. +- **Continuity is derived and ephemeral.** The SessionStart hook runs `loaf journal context --from-hook` to emit a read-time digest that is shown and discarded. Subagent invocations with `agent_id` present exit silently and write nothing. ## Linear Integration -Optional sync layer. Local tasks are the primary interface. Linear pushes for team visibility when configured. Integration toggled via `integrations.linear.enabled` in `.agents/loaf.json` (set by `loaf install`). When disabled, skills use local `loaf task` commands exclusively. +Linear is an optional task backend. When `integrations.linear.enabled` is true in `.agents/loaf.json`, compatible spec/task workflows use Linear issues for execution visibility; when it is false or absent, they use local `loaf task` records. Git-canonical deliberation artifacts remain with the code rather than being re-hosted in the tracker. ## Cross-References - [cli-design.md](cli-design.md) — CLI design philosophy and command patterns -- [knowledge-management-design.md](knowledge-management-design.md) — knowledge system uses similar Shape Up patterns +- [knowledge-management-design.md](knowledge-management-design.md) — knowledge system conventions +- [../changes/](../changes/) — retained Change contracts and implementation lineage diff --git a/internal/cli/build_amp.go b/internal/cli/build_amp.go index 36b0a2aa7..d97b2aa78 100644 --- a/internal/cli/build_amp.go +++ b/internal/cli/build_amp.go @@ -540,6 +540,7 @@ func nativeAmpHookEntryFor(hook nativeBuildHook) nativeAmpHookEntry { var nativeBuildRuntimePluginCheckHooks = map[string]bool{ "artifact-body-write": true, + "artifact-names": true, "check-" + "sec" + "rets": true, "github-account": true, "render-drift": true, diff --git a/internal/cli/build_claude_code.go b/internal/cli/build_claude_code.go index 2fa2e4f56..92b705bb8 100644 --- a/internal/cli/build_claude_code.go +++ b/internal/cli/build_claude_code.go @@ -454,6 +454,7 @@ func nativeCheckAdvisorySuffix(hook nativeBuildHook) string { var nativeClaudeBinaryPathHooks = map[string]bool{ "artifact-body-write": true, + "artifact-names": true, "check-" + "sec" + "rets": true, "ephemeral-provenance": true, "github-account": true, diff --git a/internal/cli/build_codex.go b/internal/cli/build_codex.go index ca357cd60..1edd3b1c3 100644 --- a/internal/cli/build_codex.go +++ b/internal/cli/build_codex.go @@ -15,6 +15,7 @@ import ( var codexEnforcementHooks = map[string]bool{ "artifact-body-write": true, + "artifact-names": true, "check-" + "sec" + "rets": true, "github-account": true, "render-drift": true, diff --git a/internal/cli/build_cursor.go b/internal/cli/build_cursor.go index ea046764e..c2d9f6747 100644 --- a/internal/cli/build_cursor.go +++ b/internal/cli/build_cursor.go @@ -511,6 +511,7 @@ func nativeCursorHookCommand(hook nativeBuildHook) string { var nativeBuildCursorBinaryPathHooks = map[string]bool{ "artifact-body-write": true, + "artifact-names": true, "check-" + "sec" + "rets": true, "ephemeral-provenance": true, "github-account": true, diff --git a/internal/cli/check.go b/internal/cli/check.go index c1f95669e..94365581e 100644 --- a/internal/cli/check.go +++ b/internal/cli/check.go @@ -82,6 +82,7 @@ var nativeCheckSecretPatterns = []secretPattern{ var validCheckHooks = map[string]bool{ "artifact-body-write": true, + "artifact-names": true, "check-secrets": true, "ephemeral-provenance": true, "github-account": true, @@ -112,6 +113,8 @@ func (r Runner) runCheck(args []string, out io.Writer, runtimeRoot string) error switch options.hook { case "artifact-body-write": result = runNativeArtifactBodyWriteGuard(context, runtimeRoot) + case "artifact-names": + result = runNativeArtifactNames(context, runtimeRoot) case "check-secrets": result = runNativeCheckSecrets(context) case "ephemeral-provenance": diff --git a/internal/cli/check_artifact_names.go b/internal/cli/check_artifact_names.go new file mode 100644 index 000000000..72720bade --- /dev/null +++ b/internal/cli/check_artifact_names.go @@ -0,0 +1,264 @@ +package cli + +import ( + "fmt" + "io/fs" + "os" + "os/exec" + "path/filepath" + "regexp" + "sort" + "strings" + + "github.com/levifig/loaf/internal/project" +) + +// Loaf artifacts are named for what they are, never for the work unit that +// produced them. The directory or Change that contains an artifact already +// supplies that provenance, so repeating a work identity in the filename +// inverts the reference and rots the moment that work closes: the unit points +// at its artifacts, artifacts never point back. +// +// The guard is deliberately location-independent. It matches any directory +// whose basename is a known Loaf artifact directory, wherever that directory +// currently lives, plus retained Change research evidence. Relocating those +// directories — including moving them out of .agents/ entirely — therefore +// needs no change here. +// +// Two things that look similar are explicitly legal. A version is identity, not +// reference, so claude-code-2.1.218-plugin-startup-smoke.json is fine. A +// timestamp records when, not which work unit, so 20260512-122202-audit.md is +// fine. Only a numbered work identity is rejected. + +type workIdentifierPattern struct { + label string + re *regexp.Regexp +} + +// Each pattern is segment-anchored so that incidental matches inside ordinary +// words cannot trip it: "startup" and "u2f" are not implementation units. +var workIdentifierPatterns = []workIdentifierPattern{ + {"implementation unit", regexp.MustCompile(`(?i)(^|[-_])u[0-9]+([-_]|$)`)}, + {"spec record", regexp.MustCompile(`(?i)(^|[-_])spec[-_]?[0-9]+([-_]|$)`)}, + {"task record", regexp.MustCompile(`(?i)(^|[-_])task[-_]?[0-9]+([-_]|$)`)}, + {"decision record", regexp.MustCompile(`(?i)(^|[-_])adr[-_]?[0-9]+([-_]|$)`)}, + {"pull request", regexp.MustCompile(`(?i)(^|[-_])pr[-_]?[0-9]+([-_]|$)`)}, + {"issue", regexp.MustCompile(`(?i)(^|[-_])issue[-_]?[0-9]+([-_]|$)`)}, +} + +// artifactNameIdentityOwners record the one place each numbered entity may name +// itself. A spec record inside a specs directory *is* SPEC-042; it does not +// refer to it. Everywhere else, that same string is a backward reference. +var artifactNameIdentityOwners = []struct { + dirBase string + prefix string +}{ + {dirBase: "specs", prefix: "spec-"}, + {dirBase: "decisions", prefix: "adr-"}, +} + +// artifactNameSkipDirs are never walked: build output, dependencies, and VCS +// internals are not authored artifacts. +var artifactNameSkipDirs = map[string]bool{ + ".git": true, + "node_modules": true, + "dist": true, + "plugins": true, + "bin": true, + "vendor": true, +} + +func runNativeArtifactNames(context checkHookContext, runtimeRoot string) checkResult { + result := checkResult{Passed: true, Warnings: []string{}, Errors: []string{}, Findings: []string{}} + // Resolve the project root explicitly rather than treating the runtime root as + // the scan root: the two diverge when loaf runs from an installed location. + root := firstNonEmpty(strings.TrimSpace(runtimeRoot), ".") + if resolved, err := project.ResolveRoot(root); err == nil { + root = resolved.Path() + } + + violations, err := findWorkIdentifierArtifactNames(root) + if err != nil { + result.Passed = false + result.Blocked = true + result.Errors = append(result.Errors, fmt.Sprintf("scan artifact names: %v", err)) + return result + } + for _, violation := range violations { + result.Passed = false + result.Blocked = true + result.Errors = append(result.Errors, violation.message()) + } + if result.Passed { + result.Findings = append(result.Findings, "artifact names carry no work identity") + } else { + result.Findings = append(result.Findings, + "A work identity in a filename inverts the reference: the unit points at its artifacts, never the reverse.", + "Rename the artifact for what it is. Run with --advisory to report without blocking.") + } + return result +} + +type artifactNameViolation struct { + rel string + label string +} + +func (v artifactNameViolation) message() string { + return fmt.Sprintf( + "%s names a %s. The containing directory already records that provenance; name the artifact for what it is.", + v.rel, v.label) +} + +// findWorkIdentifierArtifactNames reports every Loaf-authored artifact whose +// filename carries a work identity. +// +// Tracked paths are the unit of judgement: an untracked scratch file is nobody's +// published artifact, and blocking a commit over one the author never staged +// would be an obstruction rather than a gate. Outside a Git repository the +// filesystem is the only available source of truth, so the walk stands in. +func findWorkIdentifierArtifactNames(root string) ([]artifactNameViolation, error) { + candidates, err := trackedRepositoryPaths(root) + if err != nil { + candidates, err = walkedRepositoryPaths(root) + if err != nil { + return nil, err + } + } + var violations []artifactNameViolation + for _, rel := range candidates { + if !isLoafAuthoredArtifact(rel) { + continue + } + label, found := workIdentityInArtifactName(rel) + if !found { + continue + } + // A finalized or archived artifact is a historical record. This principle + // governs how new artifacts are named, not whether closed ones get rewritten, + // and a durable render's filename is bound to its state record, which has no + // rename path today. Enforcing retroactively would block every commit on a + // name nobody can legally change. + if isFinalizedArtifact(root, rel) { + continue + } + violations = append(violations, artifactNameViolation{rel: rel, label: label}) + } + sort.Slice(violations, func(i, j int) bool { return violations[i].rel < violations[j].rel }) + return violations, nil +} + +// trackedRepositoryPaths lists repository-relative tracked paths, which includes +// anything already staged for the commit being gated. +func trackedRepositoryPaths(root string) ([]string, error) { + output, err := exec.Command("git", "-C", root, "ls-files").Output() + if err != nil { + return nil, err + } + var paths []string + for _, line := range strings.Split(strings.TrimSpace(string(output)), "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + paths = append(paths, filepath.ToSlash(line)) + } + return paths, nil +} + +// walkedRepositoryPaths enumerates candidate paths without Git. +func walkedRepositoryPaths(root string) ([]string, error) { + var paths []string + err := filepath.WalkDir(root, func(path string, entry fs.DirEntry, err error) error { + if err != nil { + // An unreadable subtree is not evidence of compliance, but it is also + // not this check's business to fail on; skip it and keep scanning. + if entry != nil && entry.IsDir() { + return fs.SkipDir + } + return nil + } + if entry.IsDir() { + if artifactNameSkipDirs[entry.Name()] { + return fs.SkipDir + } + return nil + } + rel, relErr := filepath.Rel(root, path) + if relErr != nil { + return nil + } + paths = append(paths, filepath.ToSlash(rel)) + return nil + }) + if err != nil { + return nil, err + } + return paths, nil +} + +var artifactNameFinalizedStatusRE = regexp.MustCompile(`(?mi)^status:\s*["']?(final|archived)["']?\s*$`) + +// isFinalizedArtifact reports whether rel's front matter closes it. Only the +// leading front-matter block is consulted, so a status word in the body cannot +// silence the guard. +func isFinalizedArtifact(root string, rel string) bool { + body, err := os.ReadFile(filepath.Join(root, filepath.FromSlash(rel))) + if err != nil { + return false + } + text := string(body) + if !strings.HasPrefix(text, "---") { + return false + } + end := strings.Index(text[3:], "\n---") + if end < 0 { + return false + } + return artifactNameFinalizedStatusRE.MatchString(text[3 : 3+end]) +} + +// isLoafAuthoredArtifact reports whether rel lives somewhere Loaf itself writes +// artifacts. Matching artifact directories by basename rather than by full path +// keeps the guard correct when those directories move. +func isLoafAuthoredArtifact(rel string) bool { + segments := strings.Split(rel, "/") + if len(segments) < 2 { + return false + } + dirs := segments[:len(segments)-1] + for index, segment := range dirs { + if _, known := artifactBodyPathDirs[segment]; known { + return true + } + // Retained Change research evidence: docs/changes//research/... + if segment == "research" && index > 0 && dirs[index-1] != "" { + return true + } + } + return false +} + +// workIdentityInArtifactName reports the kind of work identity embedded in +// rel's basename, unless the artifact is the entity that identity names. +func workIdentityInArtifactName(rel string) (string, bool) { + segments := strings.Split(rel, "/") + name := strings.TrimSuffix(segments[len(segments)-1], filepath.Ext(segments[len(segments)-1])) + lowerName := strings.ToLower(name) + for _, owner := range artifactNameIdentityOwners { + if !strings.HasPrefix(lowerName, owner.prefix) { + continue + } + for _, dir := range segments[:len(segments)-1] { + if dir == owner.dirBase { + return "", false + } + } + } + for _, pattern := range workIdentifierPatterns { + if pattern.re.MatchString(name) { + return pattern.label, true + } + } + return "", false +} diff --git a/internal/cli/check_artifact_names_test.go b/internal/cli/check_artifact_names_test.go new file mode 100644 index 000000000..af9c5393a --- /dev/null +++ b/internal/cli/check_artifact_names_test.go @@ -0,0 +1,215 @@ +package cli + +import ( + "os" + "os/exec" + "path/filepath" + "testing" +) + +func TestWorkIdentityInArtifactNameClassifiesReferenceVersusIdentity(t *testing.T) { + cases := []struct { + name string + rel string + flagged bool + label string + }{ + // Outward references: the name points at the work that produced the file. + {"implementation unit prefix", "cli/scripts/u8-claude-smoke.mjs", true, "implementation unit"}, + {"implementation unit mid-name", "docs/changes/x/research/claude-u8-smoke.json", true, "implementation unit"}, + {"task record", ".agents/reports/archive/TASK-074-sidecar-audit-report.md", true, "task record"}, + {"spec record mid-name", ".agents/reports/report-spec-053-taxonomy-signoff.md", true, "spec record"}, + {"pull request mid-name", ".agents/handoffs/20260713-222603-land-pr-106-and-continue.md", true, "pull request"}, + {"issue", ".agents/plans/issue-42-triage.md", true, "issue"}, + {"underscore separator", ".agents/reports/u12_findings.md", true, "implementation unit"}, + + // Identity, not reference: the artifact IS the numbered entity, in the + // directory that owns that entity. + {"spec in specs dir", ".agents/specs/SPEC-016-council-advisory-redesign.md", false, ""}, + {"archived spec in specs dir", ".agents/specs/archive/SPEC-001-loaf-self-sufficiency.md", false, ""}, + {"adr in decisions dir", "docs/decisions/ADR-007-project-config-location.md", false, ""}, + + // A spec identity outside the directory that owns specs is a reference again. + {"spec outside specs dir", ".agents/reports/SPEC-016-review.md", true, "spec record"}, + + // Versions are identity and timestamps record when, not which work unit. + {"harness version", "docs/changes/x/research/claude-code-2.1.218-plugin-startup-smoke.json", false, ""}, + {"codex version", "docs/changes/x/research/codex-0.145.0-isolated-startup-smoke.json", false, ""}, + {"cursor build id", "docs/changes/x/research/cursor-agent-2026.05.09-0afadcc-isolation-preflight.json", false, ""}, + {"timestamp prefix", ".agents/reports/20260620-214448-audit-loaf-skills-deep-audit.md", false, ""}, + + // Ordinary words that merely contain the letters must not trip the guard. + {"startup is not a unit", "docs/changes/x/research/opencode-1.18.4-isolated-request-smoke.json", false, ""}, + {"u2f is not a unit", ".agents/plans/u2f-auth-rollout.md", false, ""}, + {"utf8 is not a unit", ".agents/reports/utf8-normalization.md", false, ""}, + {"semantic name", "docs/changes/x/research/target-capability-survey.md", false, ""}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + label, flagged := workIdentityInArtifactName(tc.rel) + if flagged != tc.flagged { + t.Fatalf("workIdentityInArtifactName(%q) flagged = %v, want %v (label %q)", tc.rel, flagged, tc.flagged, label) + } + if flagged && label != tc.label { + t.Fatalf("workIdentityInArtifactName(%q) label = %q, want %q", tc.rel, label, tc.label) + } + }) + } +} + +func TestIsLoafAuthoredArtifactMatchesDirectoriesByBasename(t *testing.T) { + // Matching by basename is what keeps the guard correct when artifact + // directories move; none of these paths may depend on a .agents/ prefix. + authored := []string{ + ".agents/reports/note.md", + ".agents/specs/archive/note.md", + "docs/reports/note.md", + "workspace/nested/handoffs/note.md", + "docs/changes/20260710-slug/research/evidence.json", + } + for _, rel := range authored { + if !isLoafAuthoredArtifact(rel) { + t.Errorf("isLoafAuthoredArtifact(%q) = false, want true", rel) + } + } + + notAuthored := []string{ + "src/main.go", + "README.md", + "internal/cli/check.go", + "docs/changes/20260710-slug/change.md", + "toplevel.md", + } + for _, rel := range notAuthored { + if isLoafAuthoredArtifact(rel) { + t.Errorf("isLoafAuthoredArtifact(%q) = true, want false", rel) + } + } +} + +func TestFindWorkIdentifierArtifactNamesWalksAndSkips(t *testing.T) { + root := t.TempDir() + write := func(rel string) { + path := filepath.Join(root, filepath.FromSlash(rel)) + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + t.Fatalf("MkdirAll(%s) error = %v", rel, err) + } + if err := os.WriteFile(path, []byte("body\n"), 0o644); err != nil { + t.Fatalf("WriteFile(%s) error = %v", rel, err) + } + } + + write(".agents/reports/TASK-074-audit.md") + write(".agents/reports/semantic-audit.md") + write(".agents/specs/SPEC-016-redesign.md") + write("docs/changes/20260710-slug/research/u8-evidence.json") + write("docs/changes/20260710-slug/change.md") + write("src/u9-handler.go") // outside artifact dirs: not this check's business + write("dist/reports/u8-generated.md") // build output is skipped wholesale + write("node_modules/reports/u8-dep.md") // dependencies are skipped wholesale + + violations, err := findWorkIdentifierArtifactNames(root) + if err != nil { + t.Fatalf("findWorkIdentifierArtifactNames error = %v", err) + } + got := make([]string, 0, len(violations)) + for _, violation := range violations { + got = append(got, violation.rel) + } + want := []string{ + ".agents/reports/TASK-074-audit.md", + "docs/changes/20260710-slug/research/u8-evidence.json", + } + if len(got) != len(want) { + t.Fatalf("violations = %v, want %v", got, want) + } + for index := range want { + if got[index] != want[index] { + t.Fatalf("violations = %v, want %v", got, want) + } + } +} + +func TestFindWorkIdentifierArtifactNamesJudgesTrackedPathsOnly(t *testing.T) { + root := t.TempDir() + write := func(rel string) { + path := filepath.Join(root, filepath.FromSlash(rel)) + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + t.Fatalf("MkdirAll(%s) error = %v", rel, err) + } + if err := os.WriteFile(path, []byte("body\n"), 0o644); err != nil { + t.Fatalf("WriteFile(%s) error = %v", rel, err) + } + } + git := func(args ...string) { + cmd := exec.Command("git", append([]string{"-C", root}, args...)...) + cmd.Env = append(os.Environ(), + "GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@example.com", + "GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@example.com") + if output, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git %v error = %v\n%s", args, err, output) + } + } + + write(".agents/reports/TASK-074-tracked.md") + write(".agents/reports/u8-untracked-scratch.md") + git("init", "-q") + git("add", ".agents/reports/TASK-074-tracked.md") + + violations, err := findWorkIdentifierArtifactNames(root) + if err != nil { + t.Fatalf("findWorkIdentifierArtifactNames error = %v", err) + } + if len(violations) != 1 || violations[0].rel != ".agents/reports/TASK-074-tracked.md" { + var got []string + for _, violation := range violations { + got = append(got, violation.rel) + } + t.Fatalf("violations = %v, want only the tracked path", got) + } +} + +func TestFindWorkIdentifierArtifactNamesGrandfathersClosedArtifacts(t *testing.T) { + root := t.TempDir() + write := func(rel string, body string) { + path := filepath.Join(root, filepath.FromSlash(rel)) + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + t.Fatalf("MkdirAll(%s) error = %v", rel, err) + } + if err := os.WriteFile(path, []byte(body), 0o644); err != nil { + t.Fatalf("WriteFile(%s) error = %v", rel, err) + } + } + + write(".agents/reports/u8-draft.md", "---\nstatus: draft\n---\n\nbody\n") + write(".agents/reports/u8-final.md", "---\nstatus: final\n---\n\nbody\n") + write(".agents/reports/u8-archived.md", "---\nstatus: archived\n---\n\nbody\n") + write(".agents/reports/u8-quoted-final.md", "---\nstatus: \"final\"\n---\n\nbody\n") + // A status word in the body must not silence the guard. + write(".agents/reports/u8-body-claims-final.md", "# Notes\n\nstatus: final\n") + // Nor may a file with no front matter at all. + write(".agents/reports/u8-bare.md", "just prose\n") + + violations, err := findWorkIdentifierArtifactNames(root) + if err != nil { + t.Fatalf("findWorkIdentifierArtifactNames error = %v", err) + } + got := make([]string, 0, len(violations)) + for _, violation := range violations { + got = append(got, violation.rel) + } + want := []string{ + ".agents/reports/u8-bare.md", + ".agents/reports/u8-body-claims-final.md", + ".agents/reports/u8-draft.md", + } + if len(got) != len(want) { + t.Fatalf("violations = %v, want %v", got, want) + } + for index := range want { + if got[index] != want[index] { + t.Fatalf("violations = %v, want %v", got, want) + } + } +} diff --git a/internal/cli/cli_reference.go b/internal/cli/cli_reference.go index af17a14c8..516cbe2bc 100644 --- a/internal/cli/cli_reference.go +++ b/internal/cli/cli_reference.go @@ -913,7 +913,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project "| `deferred-intent` | Open deferred-intent decision and spark pairs. |", "| `active-changes` | Git-derived active Change evidence and worktree state. |", "| `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. |", - "| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. |", + "| `transitional-tasks` | Open task-board records retained for compatibility. |", "", "Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic.", "", diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 7017bcea9..8e6501a89 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -733,8 +733,8 @@ func TestRunnerAllowsFreshWorktreeWithIdenticalAgentsCheckout(t *testing.T) { }); ok && exitErr.ExitCode() == 2 && exitErr.Silent() { t.Fatalf("doctor in fresh identical worktree hit pre-A3 refusal\nstdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String()) } - if strings.Contains(stderr.String(), "SPEC-036") || strings.Contains(stdout.String(), "SPEC-036") { - t.Fatalf("fresh identical worktree output contained SPEC-036 refusal\nstdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String()) + if strings.Contains(stderr.String(), "Linked worktrees keep .agents/") || strings.Contains(stdout.String(), "Linked worktrees keep .agents/") { + t.Fatalf("fresh identical worktree output contained migration refusal\nstdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String()) } raw, err := os.ReadFile(filepath.Join(linked, ".agents", worktreeBackPointerFile)) if err != nil { @@ -757,8 +757,8 @@ func TestRunnerAllowsFreshWorktreeWithIdenticalAgentsCheckout(t *testing.T) { }); ok && exitErr.ExitCode() == 2 && exitErr.Silent() { t.Fatalf("second doctor in bootstrapped identical worktree hit pre-A3 refusal\nstdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String()) } - if strings.Contains(stderr.String(), "SPEC-036") || strings.Contains(stdout.String(), "SPEC-036") { - t.Fatalf("second identical worktree output contained SPEC-036 refusal\nstdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String()) + if strings.Contains(stderr.String(), "Linked worktrees keep .agents/") || strings.Contains(stdout.String(), "Linked worktrees keep .agents/") { + t.Fatalf("second identical worktree output contained migration refusal\nstdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String()) } raw, err = os.ReadFile(filepath.Join(linked, ".agents", worktreeBackPointerFile)) if err != nil { @@ -788,7 +788,7 @@ func TestRunnerRefusesLinkedWorktreeWithLocalOnlyAgentsFile(t *testing.T) { if !ok || exitErr.ExitCode() != 2 || !exitErr.Silent() { t.Fatalf("Run() error = %#v, want silent exit code 2", err) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(stderr.String(), want) { t.Fatalf("stderr = %q, want %q", stderr.String(), want) } @@ -814,7 +814,7 @@ func TestRunnerRefusesLinkedWorktreeWithDivergentAgentsFile(t *testing.T) { if !ok || exitErr.ExitCode() != 2 || !exitErr.Silent() { t.Fatalf("Run() error = %#v, want silent exit code 2", err) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(stderr.String(), want) { t.Fatalf("stderr = %q, want %q", stderr.String(), want) } @@ -841,7 +841,7 @@ func TestRunnerRefusesLinkedWorktreeWithValidPointerAndDivergentAgentsFile(t *te if !ok || exitErr.ExitCode() != 2 || !exitErr.Silent() { t.Fatalf("Run() error = %#v, want silent exit code 2", err) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(stderr.String(), want) { t.Fatalf("stderr = %q, want %q", stderr.String(), want) } @@ -874,7 +874,7 @@ func TestRunnerRefusesLinkedWorktreeWithSymlinkAgentsFile(t *testing.T) { if !ok || exitErr.ExitCode() != 2 || !exitErr.Silent() { t.Fatalf("Run() error = %#v, want silent exit code 2", err) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(stderr.String(), want) { t.Fatalf("stderr = %q, want %q", stderr.String(), want) } @@ -906,7 +906,7 @@ func TestRunnerRefusesLinkedWorktreeWithOnlySymlinkAgentsFile(t *testing.T) { if !ok || exitErr.ExitCode() != 2 || !exitErr.Silent() { t.Fatalf("Run() error = %#v, want silent exit code 2", err) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(stderr.String(), want) { t.Fatalf("stderr = %q, want %q", stderr.String(), want) } @@ -931,7 +931,7 @@ func TestRunnerRefusesPreA3LinkedWorktreeBeforeDispatch(t *testing.T) { if !ok || exitErr.ExitCode() != 2 || !exitErr.Silent() { t.Fatalf("Run() error = %#v, want silent exit code 2", err) } - for _, want := range []string{"SPEC-036", "loaf migrate worktree-storage", "LOAF_DEBUG_RESOLVE"} { + for _, want := range []string{"Linked worktrees keep .agents/", "loaf migrate worktree-storage", "LOAF_DEBUG_RESOLVE"} { if !strings.Contains(stderr.String(), want) { t.Fatalf("stderr = %q, want %q", stderr.String(), want) } @@ -956,7 +956,7 @@ func TestRunnerRefusesPreA3LinkedWorktreeWithUnknownCommandFeedback(t *testing.T if !ok || exitErr.ExitCode() != 2 || !exitErr.Silent() { t.Fatalf("Run() error = %#v, want silent exit code 2", err) } - for _, want := range []string{"unknown command 'not-a-command'", "SPEC-036", "loaf migrate worktree-storage"} { + for _, want := range []string{"unknown command 'not-a-command'", "Linked worktrees keep .agents/", "loaf migrate worktree-storage"} { if !strings.Contains(stderr.String(), want) { t.Fatalf("stderr = %q, want %q", stderr.String(), want) } diff --git a/internal/cli/doctor.go b/internal/cli/doctor.go index ce835a164..fd4a5b29f 100644 --- a/internal/cli/doctor.go +++ b/internal/cli/doctor.go @@ -868,4 +868,3 @@ func hasDoctorFencedSection(path string) bool { text := string(body) return strings.Contains(text, "") } - diff --git a/internal/cli/install_target.go b/internal/cli/install_target.go index 37d6b86d4..a2d54ec10 100644 --- a/internal/cli/install_target.go +++ b/internal/cli/install_target.go @@ -32,7 +32,7 @@ var legacyLoafHookSignatures = map[string]bool{ "command:loaf check --hook validate-commit|matcher:Bash|if:": true, "command:loaf task refresh|matcher:Edit|Write|if:": true, "command:bash $HOME/.cursor/hooks/post-tool/kb-staleness-nudge.sh|matcher:Edit|Write|if:": true, - // Journal-first hook signatures (SPEC-056). + // Journal-first hook signatures. "command:loaf journal log --detect-linear|matcher:Bash|if:": true, "command:loaf journal log --from-hook|matcher:Bash|if:Bash(git commit:*)": true, "command:loaf journal log --from-hook|matcher:Bash|if:Bash(gh pr create:*)": true, diff --git a/internal/cli/journal.go b/internal/cli/journal.go index 9469c77b5..1a286a46c 100644 --- a/internal/cli/journal.go +++ b/internal/cli/journal.go @@ -14,7 +14,7 @@ import ( "github.com/levifig/loaf/internal/state" ) -// runJournal dispatches the project-scoped journal command namespace (SPEC-056). +// runJournal dispatches the project-scoped journal command namespace. // The journal is the only session-related structure: entries are project events // tagged with an opaque harness_session_id correlation column. func (r Runner) runJournal(args []string, out io.Writer, runtime state.Runtime) error { @@ -521,7 +521,7 @@ func (r Runner) runJournalSearch(args []string, out io.Writer, runtime state.Run // Journal search queries only the journal_search FTS table joined to // journal_entries. It never refreshes or scans the docs index, so a // journal-only read cannot mutate docs state or fail on unrelated docs - // scanning (SPEC-056 M1). + // scanning. result, err := state.SearchJournal(context.Background(), projectRoot, state.PathResolver{StateHome: r.StateHome}, state.SearchOptions{ Query: options.query, AllProjects: options.allProjects, diff --git a/internal/cli/journal_hooks.go b/internal/cli/journal_hooks.go index 77ece7be8..8b420c705 100644 --- a/internal/cli/journal_hooks.go +++ b/internal/cli/journal_hooks.go @@ -13,7 +13,7 @@ import ( // journalHookInput is the harness hook payload read from stdin for journal // hooks (SessionStart, PreCompact, PostCompact, UserPromptSubmit, TaskCompleted, -// and git/gh PostToolUse). Under the journal-first model (SPEC-056) there is no +// and git/gh PostToolUse). Under the journal-first model there is no // session entity: the only lifecycle-relevant field is agent_id, which flags a // subagent invocation the hooks must silently ignore. type journalHookInput struct { diff --git a/internal/cli/release_dry_run.go b/internal/cli/release_dry_run.go index eca352b01..6628fcc53 100644 --- a/internal/cli/release_dry_run.go +++ b/internal/cli/release_dry_run.go @@ -1342,7 +1342,7 @@ func releaseBumpReason(bump string) string { case "patch": return "bug fixes only" case "prerelease": - return "development milestone" + return "prerelease version" case "release": return "stable release" default: diff --git a/internal/cli/worktree_storage_migration.go b/internal/cli/worktree_storage_migration.go index 76193389c..d01721163 100644 --- a/internal/cli/worktree_storage_migration.go +++ b/internal/cli/worktree_storage_migration.go @@ -18,7 +18,7 @@ const worktreePartialSuffix = ".partial.loaf-migrate" const debugResolveEnv = "LOAF_DEBUG_RESOLVE" const preA3RefusalMessageNative = `This worktree has unmigrated agentic state under .agents/. -SPEC-036 centralizes .agents/ to the main worktree, so this command is refused +Linked worktrees keep .agents/ in the main worktree, so this command is refused until you run: loaf migrate worktree-storage # dry-run preview @@ -120,7 +120,7 @@ func writeWorktreeMigrationHelp(out io.Writer) { fmt.Fprintln(out, strings.Join([]string{ "Usage: loaf migrate worktree-storage [options]", "", - "Move a linked worktree's local .agents/ into the main worktree (SPEC-036).", + "Move a linked worktree's local .agents/ into the main worktree.", "dry-run by default; pass --apply to mutate.", "", "Options:", diff --git a/internal/project/project.go b/internal/project/project.go index 57d80cb0e..62710a427 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -48,7 +48,7 @@ type Root struct { // ResolveRoot returns the project root for state identity. Linked Git // worktrees resolve to the main worktree root by comparing git-dir with -// git-common-dir, matching the existing TypeScript resolver's SPEC-036 model. +// git-common-dir, matching the existing TypeScript resolver's worktree model. func ResolveRoot(start string) (Root, error) { workingDir, err := ResolveWorkingDirectory(start) if err != nil { diff --git a/internal/state/artifact_entities.go b/internal/state/artifact_entities.go index 3b0630d01..ae2eb6eb1 100644 --- a/internal/state/artifact_entities.go +++ b/internal/state/artifact_entities.go @@ -163,9 +163,9 @@ VALUES (?, ?, ?, ?, ?, NULL, ?, ?) return ArtifactEntityCreateResult{}, fmt.Errorf("insert %s %s: %w", kind, alias, err) } case "handoff": - // The handoff correlation column is journal-first (harness_session_id) - // after the SPEC-056 migration but session_id on the pre-migration - // schema. Match the live table so the write works on both shapes. + // The handoff correlation column is harness_session_id on the current + // schema and session_id on the pre-migration schema. Match the live table + // so the write works on both shapes. correlationColumn, err := handoffCorrelationColumn(ctx, tx) if err != nil { return ArtifactEntityCreateResult{}, err diff --git a/internal/state/backup_test.go b/internal/state/backup_test.go index ed01c2315..90e36022a 100644 --- a/internal/state/backup_test.go +++ b/internal/state/backup_test.go @@ -199,7 +199,7 @@ func TestBackupWithDestinationValidatesExplicitDirectory(t *testing.T) { }) } volatileRoot := t.TempDir() - volatilePath := filepath.Join(volatileRoot, "loaf-u4-volatile") + volatilePath := filepath.Join(volatileRoot, "backup-test-volatile") _, err := backupWithDestination(ctx, root, resolver, volatilePath, &backupOperations{volatileRoots: []string{volatileRoot}}) var volatileErr *BackupDestinationError if !errors.As(err, &volatileErr) || volatileErr.Code != BackupDestinationVolatileCode { @@ -217,26 +217,26 @@ func TestBackupWithDestinationValidatesExplicitDirectory(t *testing.T) { } func TestVolatileRootInventoryUsesCurrentPlatformAndDurableControl(t *testing.T) { - probe := filepath.Join(os.TempDir(), "loaf-u4-classification-probe") + probe := filepath.Join(os.TempDir(), "backup-test-classification-probe") if !pathWithinVolatileRoot(probe) { t.Fatalf("default volatile roots do not classify %q", probe) } switch runtime.GOOS { case "linux": for _, root := range []string{"/dev/shm", "/run/user", "/run/lock", "/run/shm"} { - if !pathWithinVolatileRoots(filepath.Join(root, "loaf-u4-probe"), []string{root}) { + if !pathWithinVolatileRoots(filepath.Join(root, "backup-test-probe"), []string{root}) { t.Fatalf("Linux volatile root %q was not classified", root) } } - if !pathWithinVolatileRoots("/var/run/loaf-u4-probe", nil) { + if !pathWithinVolatileRoots("/var/run/backup-test-probe", nil) { t.Fatal("Linux legacy /var/run runtime namespace was not classified") } - if pathWithinVolatileRoots("/run/media/loaf-u4-probe", []string{"/run/user", "/run/lock", "/run/shm"}) { + if pathWithinVolatileRoots("/run/media/backup-test-probe", []string{"/run/user", "/run/lock", "/run/shm"}) { t.Fatal("Linux durable /run/media control was over-classified as volatile") } case "darwin": for _, root := range []string{"/var/folders", "/private/var/folders"} { - if _, err := os.Stat(root); err == nil && !pathWithinVolatileRoot(filepath.Join(root, "loaf-u4-probe")) { + if _, err := os.Stat(root); err == nil && !pathWithinVolatileRoot(filepath.Join(root, "backup-test-probe")) { t.Fatalf("Darwin volatile root %q was not classified", root) } } @@ -297,13 +297,13 @@ func TestBackupWithDestinationRejectsVolatileSymlinkBeforeCreatingTail(t *testin if err := os.Symlink(volatileTarget, link); err != nil { t.Fatalf("Symlink() error = %v", err) } - tail := filepath.Join(link, "loaf-u4-must-not-create") + tail := filepath.Join(link, "backup-test-must-not-create") _, err := backupWithDestination(ctx, root, resolver, tail, &backupOperations{volatileRoots: []string{volatileTarget}}) var destinationErr *BackupDestinationError if !errors.As(err, &destinationErr) || destinationErr.Code != BackupDestinationVolatileCode { t.Fatalf("volatile symlink error = %v, want code %q", err, BackupDestinationVolatileCode) } - if _, err := os.Stat(filepath.Join(volatileTarget, "loaf-u4-must-not-create")); !os.IsNotExist(err) { + if _, err := os.Stat(filepath.Join(volatileTarget, "backup-test-must-not-create")); !os.IsNotExist(err) { t.Fatalf("volatile tail stat error = %v, want no directory created", err) } } diff --git a/internal/state/durable_render.go b/internal/state/durable_render.go index 7b790ded6..50d47bfe3 100644 --- a/internal/state/durable_render.go +++ b/internal/state/durable_render.go @@ -32,7 +32,7 @@ type DurableRenderDocument struct { // environments, so emitting it would make the same logical spec render to // different bytes depending on where the state database lives. Committed durable // renders must contain only reproducible content so CI can re-render against a -// fresh database in any location (SPEC-044). +// fresh database in any location. func DurableSpecRenderDocument(spec SpecDetail) DurableRenderDocument { fields := []DurableRenderField{ {Key: "id", Value: firstNonEmpty(spec.Alias, spec.ID)}, diff --git a/internal/state/export.go b/internal/state/export.go index 454604dc1..f7e7aa5c9 100644 --- a/internal/state/export.go +++ b/internal/state/export.go @@ -621,7 +621,8 @@ func normalizeExportValue(value any) any { } } -// ValidateExternalMarkdownExport checks generated external Markdown against the SPEC-038 boundary. +// ValidateExternalMarkdownExport checks generated external Markdown for private +// Loaf references that must not appear in external exports. func ValidateExternalMarkdownExport(content string) error { for _, pattern := range externalLeakPatterns { if match := pattern.FindString(content); match != "" { diff --git a/internal/state/journal.go b/internal/state/journal.go index d7f08aa50..7ee6b84eb 100644 --- a/internal/state/journal.go +++ b/internal/state/journal.go @@ -309,9 +309,9 @@ WHERE project_id = ? AND id = ? `, projectID, journalEntryID).Scan(&rowID); err != nil { return fmt.Errorf("read journal entry rowid %s: %w", journalEntryID, err) } - // The FTS correlation column is journal-first (harness_session_id) after the - // SPEC-056 migration but session_id on the pre-migration schema. Match the - // live table so the write works on both shapes. + // The FTS correlation column is harness_session_id on the current schema and + // session_id on the pre-migration schema. Match the live table so the write + // works on both shapes. correlationColumn, err := journalSearchCorrelationColumn(ctx, tx) if err != nil { return err diff --git a/internal/state/journal_context.go b/internal/state/journal_context.go index df5189d83..8af8c29d8 100644 --- a/internal/state/journal_context.go +++ b/internal/state/journal_context.go @@ -74,7 +74,7 @@ type JournalContext struct { Diagnostics []JournalContextDiagnostic `json:"diagnostics"` // Deprecated compatibility fields. The v2 CLI should consume the named - // layers above; these keep existing callers source-compatible during U6. + // layers above; these keep existing callers source-compatible. LatestWrap *JournalEntryRecord `json:"-"` BranchEntries []JournalEntryRecord `json:"-"` OpenTasks []JournalContextTask `json:"-"` @@ -214,7 +214,7 @@ type JournalContextTaskLayer struct { Items []JournalContextTask `json:"items"` } -// JournalContextTask is an open transitional task surfaced in continuity. +// JournalContextTask is an open task-board record retained for compatibility. type JournalContextTask struct { Ref string `json:"ref"` Title string `json:"title"` diff --git a/internal/state/journal_first_migration.go b/internal/state/journal_first_migration.go index da94717b6..dc4005290 100644 --- a/internal/state/journal_first_migration.go +++ b/internal/state/journal_first_migration.go @@ -20,7 +20,7 @@ const ( JournalFirstMigrationActionApply = "apply" ) -// JournalFirstMigrationResult reports the outcome of a journal-first (SPEC-056) +// JournalFirstMigrationResult reports the outcome of a journal-first // migration run. Counts are measured across the whole global database because // the migration is schema-wide and touches every project's rows. type JournalFirstMigrationResult struct { diff --git a/internal/state/journal_search.go b/internal/state/journal_search.go index 1cdfce8bc..8dac1fe49 100644 --- a/internal/state/journal_search.go +++ b/internal/state/journal_search.go @@ -9,7 +9,7 @@ import ( // SearchJournal runs a journal-only full-text search against initialized SQLite // state. Unlike the global Search, it queries only the journal_search FTS table // joined to journal_entries: it never touches the docs index, so a journal read -// cannot refresh docs state or fail on unrelated docs scanning (SPEC-056 M1). +// cannot refresh docs state or fail on unrelated docs scanning. func SearchJournal(ctx context.Context, root project.Root, resolver PathResolver, options SearchOptions) (SearchResult, error) { store, err := openProjectStoreReadExistingForJournalSearch(ctx, root, resolver) if err != nil { diff --git a/internal/state/markdown_import.go b/internal/state/markdown_import.go index 5d5b08b0a..1263cf697 100644 --- a/internal/state/markdown_import.go +++ b/internal/state/markdown_import.go @@ -424,7 +424,7 @@ func (m markdownImporter) importShapingDrafts(ctx context.Context, agentsPath st } // importSessionJournals imports legacy .agents/sessions/*.md files as -// project-scoped journal entries. Under the journal-first model (SPEC-056) the +// project-scoped journal entries. Under the journal-first model the // session entity no longer exists: each session file's journal lines become // project-scoped journal_entries tagged with the file's harness session id, and // its spark lines become sparks. No session row, body, or alias is created. diff --git a/internal/state/runtime.go b/internal/state/runtime.go index 0a9ae3560..797fde492 100644 --- a/internal/state/runtime.go +++ b/internal/state/runtime.go @@ -3,7 +3,7 @@ package state import "github.com/levifig/loaf/internal/project" // Runtime is the minimal state-runtime boundary. SQLite storage, migrations, -// and state commands build on this package in later SPEC-040 tasks. +// and state commands build on this package. type Runtime struct { root project.WorkingDirectory } diff --git a/internal/state/schema.go b/internal/state/schema.go index 4a0a5839d..259653f2c 100644 --- a/internal/state/schema.go +++ b/internal/state/schema.go @@ -120,14 +120,14 @@ func SchemaMigrations() []SchemaMigration { } // journalFirstMigrationVersion is the schema version introduced by the -// journal-first (SPEC-056) transformation. It is intentionally excluded from +// journal-first transformation. It is intentionally excluded from // SchemaMigrations() so that opening a store does not auto-apply this // destructive migration; it runs only through the explicit journal-first // migrate command, which takes a mandatory pre-migration backup first. const journalFirstMigrationVersion = 10 -// JournalFirstMigration returns the destructive SPEC-056 journal-first -// migration. It is applied explicitly (not on store open) and is recorded in +// JournalFirstMigration returns the destructive journal-first migration. It is +// applied explicitly (not on store open) and is recorded in // schema_migrations like any other migration. func JournalFirstMigration() SchemaMigration { return SchemaMigration{ @@ -138,7 +138,7 @@ func JournalFirstMigration() SchemaMigration { } // CurrentSchemaVersion returns the highest auto-applied Go-owned migration -// version. The journal-first migration (SPEC-056) remains intentionally +// version. The journal-first migration remains intentionally // excluded from SchemaMigrations() so it never auto-applies on store open. func CurrentSchemaVersion() int { migrations := SchemaMigrations() diff --git a/plugins/loaf/.loaf-target-manifest.json b/plugins/loaf/.loaf-target-manifest.json index 700ed3c03..899ed4492 100644 --- a/plugins/loaf/.loaf-target-manifest.json +++ b/plugins/loaf/.loaf-target-manifest.json @@ -76,7 +76,7 @@ "kind": "hook-projection", "source_path": "hooks/hooks.json", "destination": "hooks/hooks.json", - "sha256": "5c7343a34af37d6c6e930981f71e405b8023975de4146822058f98c15251b7c2" + "sha256": "564917493bfa795fee8a067e235e13eec5f992e098cb94540d2202cc6fe3cad4" }, { "id": "managed-instructions", diff --git a/plugins/loaf/bin/native/darwin-arm64/loaf b/plugins/loaf/bin/native/darwin-arm64/loaf index f3beae887..a2de1b2de 100755 Binary files a/plugins/loaf/bin/native/darwin-arm64/loaf and b/plugins/loaf/bin/native/darwin-arm64/loaf differ diff --git a/plugins/loaf/hooks/hooks.json b/plugins/loaf/hooks/hooks.json index a9d0dd78d..85ee3a152 100644 --- a/plugins/loaf/hooks/hooks.json +++ b/plugins/loaf/hooks/hooks.json @@ -43,7 +43,15 @@ "command": "\"${CLAUDE_PLUGIN_ROOT}/bin/loaf\" check --hook ephemeral-provenance", "if": "Bash(git push:*)", "timeout": 30, - "description": "Block active specs from pointing at deleted ephemeral Markdown after cutover", + "description": "Block tracked ephemeral Markdown and dangling references from retained spec records", + "failClosed": true + }, + { + "type": "command", + "command": "\"${CLAUDE_PLUGIN_ROOT}/bin/loaf\" check --hook artifact-names", + "if": "Bash(git commit:*)", + "timeout": 30, + "description": "Block artifact filenames that name the work unit that produced them", "failClosed": true }, { diff --git a/plugins/loaf/skills/architecture/SKILL.md b/plugins/loaf/skills/architecture/SKILL.md index 5421c8859..4cc609573 100644 --- a/plugins/loaf/skills/architecture/SKILL.md +++ b/plugins/loaf/skills/architecture/SKILL.md @@ -38,7 +38,7 @@ ADRs are reserved for **architecturally significant** decisions — those affect The bar is a **disjunction**: either canonical-domain effect, or difficulty of reversal, satisfies it (Microsoft Well-Architected). The Triage Gate below operationalizes the bar more strictly — `(Q1 OR Q2) AND Q3` — to keep ADRs rare and binding. -The bar is constant. **The number of decisions clearing it scales with project maturity.** Early/exploratory projects clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt during early phases, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In early phases, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. +The bar is constant. **The number of decisions clearing it scales with project maturity.** Projects still exploring their foundational shape clear the bar rarely — usually only foundational shape commitments (language/runtime/standard adoption, primary architectural shape). Mature projects clear it more often as cost-of-change rises across the codebase. **When in doubt while the project is still exploring its foundations, prefer SPEC over ADR** — SPECs evolve, ADRs supersede. In exploratory projects, foundational commitments typically pass via Q2's "Later" prong — the future-cost is the reason to record the rationale while it's fresh, not the current-cost. **An ADR captures a choice.** At least one credible alternative was considered and rejected. Without alternatives, you have a principle, vision, or aspiration — record those in `ARCHITECTURE.md` or `VISION.md` instead. The presence of an "Alternatives Considered" section in the ADR template is structural, not optional. diff --git a/plugins/loaf/skills/bootstrap/SKILL.md b/plugins/loaf/skills/bootstrap/SKILL.md index ae0d5792f..fd3de80c8 100644 --- a/plugins/loaf/skills/bootstrap/SKILL.md +++ b/plugins/loaf/skills/bootstrap/SKILL.md @@ -220,7 +220,7 @@ A brief exists but needs validation and gap-filling. Moderate depth. **Interview focus (8-12 questions):** - Confirm extracted understanding ("Here's what I got from your brief -- is this right?") - Challenge assumptions ("Your brief says X, but have you considered Y?") -- Fill gaps in whichever interview phases are weakest +- Fill gaps in whichever interview sections are weakest - Don't re-ask what the brief already answers well **Opening pattern:** Quote the brief back, confirm accuracy, then pivot to gaps. @@ -229,14 +229,14 @@ A brief exists but needs validation and gap-filling. Moderate depth. No code, no brief, just a person with an idea. Deepest interview. -**Run all four phases from [references/interview-guide.md](references/interview-guide.md):** +**Run all four sections from [references/interview-guide.md](references/interview-guide.md):** 1. **Excavation (The Spark)** -- understand the problem, who has it, what they do today 2. **Sharpening (The Shape)** -- define scope, boundaries, no-gos, complexity 3. **Grounding (The Architecture)** -- technical direction, build vs. buy, hard problems 4. **Synthesis (The Documents)** -- transition to drafting -**Expect 15-25 questions across all phases.** Follow the phase transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. +**Expect 15-25 questions across all sections.** Follow the transition signals in the interview guide. Be patient -- the builder may circle back or contradict themselves. That is normal. **Opening pattern:** "Tell me about what you're building. What problem are you solving?" @@ -246,9 +246,9 @@ Avoid these across all modes: - **The Form** -- don't run through questions mechanically like a survey - **The 45-Minute Interrogation** -- if the builder is losing energy, cut to synthesis -- **Premature Architecture** -- don't ask about databases in Phase 1 +- **Premature Architecture** -- don't ask about databases during Excavation - **The Echo Chamber** -- challenge, don't just agree -- **Asking for Permission to Proceed** -- transition between phases naturally +- **Asking for Permission to Proceed** -- transition between sections naturally - **Over-Indexing on Frameworks** -- use frameworks as lenses, not vocabulary --- diff --git a/plugins/loaf/skills/bootstrap/references/interview-guide.md b/plugins/loaf/skills/bootstrap/references/interview-guide.md index 9e859e93e..052e21408 100644 --- a/plugins/loaf/skills/bootstrap/references/interview-guide.md +++ b/plugins/loaf/skills/bootstrap/references/interview-guide.md @@ -5,10 +5,10 @@ A structured interview framework for helping builders go from a vague idea to a ## Contents - How This Guide Works - Framework Foundations -- Phase 1: Excavation (The Spark) -- Phase 2: Sharpening (The Shape) -- Phase 3: Grounding (The Architecture) -- Phase 4: Synthesis (The Documents) +- Excavation (The Spark) +- Sharpening (The Shape) +- Grounding (The Architecture) +- Synthesis (The Documents) - Adapting Interview Depth - Anti-Patterns - Transitioning to Document Drafting @@ -17,16 +17,16 @@ A structured interview framework for helping builders go from a vague idea to a This is a **builder interview**, not a user research interview. The interviewer (the agent) is helping the builder crystallize their own thinking -- not extracting requirements from a stakeholder. The builder has context, intuition, and taste that need to be surfaced, challenged, and structured. -The interview flows through four phases, each producing progressively sharper artifacts: +The interview flows through four sections, each producing progressively sharper artifacts: -| Phase | Focus | Primary Output | Frameworks | +| Section | Focus | Primary Output | Frameworks | |-------|-------|----------------|------------| -| 1. Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | -| 2. Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | -| 3. Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | -| 4. Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | +| Excavation | What exists, why it matters | Raw problem + context | Mom Test, JTBD, First Principles | +| Sharpening | Who, what, boundaries | Bounded scope + complexity | Shape Up, Lean Canvas, Design Sprint | +| Grounding | How, where, what evolves | Technical direction + landscape | Wardley Mapping, First Principles | +| Synthesis | Drafting documents | BRIEF, VISION, STRATEGY, ARCHITECTURE | All, integrated | -Phases are not rigid walls. A strong answer in Phase 1 might skip half of Phase 2. A weak answer in Phase 2 might loop back to Phase 1. Follow the energy. +Sections are not rigid walls. A strong answer in Excavation might skip half of Sharpening. A weak answer in Sharpening might loop back to Excavation. Follow the energy. --- @@ -80,7 +80,7 @@ What each framework contributes and what to skip. **What to skip:** Customer interview logistics, meeting scheduling advice. The Mom Test is about question quality, not interview operations. -**Connection to documents:** Informs the quality of every answer in every phase. The Mom Test isn't a phase -- it's a lens applied to ALL questioning. It keeps the interview honest. +**Connection to documents:** Informs the quality of every answer in every section. The Mom Test isn't a section -- it's a lens applied to ALL questioning. It keeps the interview honest. ### Design Sprint - Understand Phase (Google Ventures) @@ -120,7 +120,7 @@ What each framework contributes and what to skip. --- -## Phase 1: Excavation (The Spark) +## Excavation (The Spark) **Goal:** Understand what exists, why it matters, and whether the problem is real. @@ -157,9 +157,9 @@ The builder's own experience with the problem is the richest source of insight. - "Have you seen anyone spend money or significant time on this problem?" *(Mom Test: evidence of pain)* - "Is this problem getting worse or better over time? Why?" *(Wardley: movement awareness)* -### Phase 1 Signals +### Excavation Signals -**Strong signal (move to Phase 2):** Builder can describe a specific person with a specific problem and knows what they do about it today. +**Strong signal (move to Sharpening):** Builder can describe a specific person with a specific problem and knows what they do about it today. **Weak signal (dig deeper):** Builder describes a category ("developers need better tools") without specifics. Ask for a story: "Tell me about a specific moment when this problem was most painful." @@ -167,13 +167,13 @@ The builder's own experience with the problem is the richest source of insight. --- -## Phase 2: Sharpening (The Shape) +## Sharpening (The Shape) **Goal:** Define who this is for, what it does, and -- critically -- what it does NOT do. Set complexity and boundaries. -**Mood:** Constructive pressure. Phase 1 was expansive; Phase 2 is reductive. The builder will want to include everything. Your job is to help them cut. +**Mood:** Constructive pressure. Excavation was expansive; Sharpening is reductive. The builder will want to include everything. Your job is to help them cut. -**Duration:** This is typically the longest phase. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. +**Duration:** This is typically the longest section. 8-12 questions for a fresh idea, 4-6 for an idea with an existing brief. ### Must-Ask Questions @@ -210,17 +210,17 @@ Surface the riskiest assumptions. "Will users actually switch from their current - "How might we make [the hardest part] effortless?" *(Design Sprint: HMW)* - "What would definitely make this fail?" *(First Principles: inversion)* -### Phase 2 Signals +### Sharpening Signals -**Strong signal (move to Phase 3):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. +**Strong signal (move to Grounding):** Builder can state the job, the differentiator, and at least 3 no-gos. Complexity is sized. **Weak signal (iterate):** Builder keeps expanding scope. "It should also..." is a signal to tighten. Ask: "If you could only do ONE thing, what would it be?" -**Red flag (loop back to Phase 1):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" +**Red flag (loop back to Excavation):** The "who" keeps shifting. If the user persona changes every other answer, the problem isn't defined yet. Go back to "Who has this problem?" --- -## Phase 3: Grounding (The Architecture) +## Grounding (The Architecture) **Goal:** Establish technical direction, identify what to build vs. buy, and surface hidden complexity. @@ -257,19 +257,19 @@ These become the rabbit holes in the spec. The builder often knows where the dra - "If you had to ship something in one week, what would you cut?" *(Shape Up: scope pressure test)* - "Are there regulatory, legal, or compliance considerations?" *(Often forgotten at 0-to-1)* -### Phase 3 Signals +### Grounding Signals -**Strong signal (move to Phase 4):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. +**Strong signal (move to Synthesis):** Builder can trace a rough value chain, knows what's novel vs. commodity, and has identified the hard problems. **Weak signal (iterate):** Builder wants to build everything from scratch. Challenge: "What's the thing ONLY YOU can build? Build that. Use existing solutions for the rest." -**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Phase 3 and note that ARCHITECTURE.md will be populated later when technical decisions are made. +**Not applicable:** If the project is purely conceptual or non-technical at this stage, skip Grounding and note that ARCHITECTURE.md will be populated later when technical decisions are made. --- -## Phase 4: Synthesis (The Documents) +## Synthesis (The Documents) -**Goal:** Transform interview insights into draft documents. This is NOT a phase of the interview -- it's the transition from interviewing to drafting. +**Goal:** Transform interview insights into draft documents. This is NOT an interview section -- it's the transition from interviewing to drafting. **Mood:** Collaborative, iterative. The agent drafts, the builder reacts and refines. @@ -319,11 +319,11 @@ Allow the builder to approve all remaining sections at once if they're satisfied ## Adapting Interview Depth -The interview adapts to three contexts, per SPEC-013's mode detection: +The interview adapts to three contexts based on the detected project mode: ### Greenfield + Empty (Full Interview) -Run all four phases in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all phases. This is where the interview guide earns its keep. +Run all four sections in full. The builder has minimal clarity and needs the most support. Expect 15-25 questions total across all sections. This is where the interview guide earns its keep. **Key adaptation:** Be patient. The builder may circle back, contradict themselves, or get stuck. That's normal. Let them think out loud. Silence after a question is productive, not awkward. @@ -332,9 +332,9 @@ Run all four phases in full. The builder has minimal clarity and needs the most Read and analyze the brief first. Then run a compressed interview that: - Confirms understanding ("Here's what I extracted -- is this right?") - Challenges assumptions ("Your brief says X, but have you considered Y?") -- Fills gaps (which phases have missing information?) +- Fills gaps (which sections have missing information?) -Expect 8-12 questions total, concentrated in whichever phases the brief is weakest. +Expect 8-12 questions total, concentrated in whichever sections the brief is weakest. **Key adaptation:** Don't re-ask what the brief already answers well. Quote the brief back and ask "Is this still accurate?" to confirm, then move to gaps. @@ -345,7 +345,7 @@ The project exists. Code exists. Docs may exist. The interview focuses on: - What the builder wants to CHANGE (current pain, technical debt, strategic shifts) - What conventions and preferences exist but aren't documented -Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered by the existing codebase. +Expect 6-10 questions total, mostly in Excavation and Sharpening. Grounding is largely answered by the existing codebase. **Key adaptation:** Show the builder what you learned from their code. "I see a Python/FastAPI project with PostgreSQL and Docker. The test suite uses pytest. Is that the intended stack going forward?" Let the codebase speak first, then fill gaps. @@ -361,13 +361,13 @@ Expect 6-10 questions total, mostly in Phases 1-2. Phase 3 is largely answered b **The Therapist.** "And how does that make you feel about your product?" No. This is a builder interview, not a feelings exploration. Emotions matter (JTBD switching forces), but ask about user emotions, not builder emotions. -**Premature Architecture.** Jumping to "What database should we use?" in Phase 1. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. +**Premature Architecture.** Jumping to "What database should we use?" during Excavation. Technical decisions come after the problem and scope are clear. Architecture without clarity is random technology selection. **The Echo Chamber.** Reflecting back everything the builder says without challenging anything. The Mom Test exists because people are too polite. Be constructive, not agreeable. "That's a big scope. Are you sure you need ALL of that for v1?" **Solution-First Questioning.** "What features should it have?" is the wrong question. "What job does it do for the user?" is the right one. Features are an output of the interview, not an input. -**Asking for Permission to Proceed.** Don't ask "Should we move to the next phase?" Just move when the signals are strong. If the builder has more to say, they'll say it. +**Asking for Permission to Proceed.** Don't ask "Should we move to the next section?" Just move when the signals are strong. If the builder has more to say, they'll say it. **Over-Indexing on Frameworks.** Don't say "Let's do a JTBD analysis" or "Let me apply Wardley Mapping here." The frameworks are lenses for the interviewer, not vocabulary for the builder. Just ask good questions. @@ -413,12 +413,12 @@ The bootstrap interview creates the foundation. Other skills deepen specific are ## Framework Attribution -| Framework | Primary Contribution | Phase(s) | +| Framework | Primary Contribution | Section(s) | |-----------|---------------------|----------| -| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | 2, 3 | -| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | 1, 2 | -| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | 1, 2 | -| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All phases | -| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | 2, 3 | -| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | 3 | -| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | 1, 3 | +| Shape Up | Complexity sizing, no-gos, rabbit holes, pitch format | Sharpening, Grounding | +| Jobs to Be Done | Job statements, switching forces, competing with non-consumption | Excavation, Sharpening | +| Lean Canvas | Problem/UVP/unfair advantage triangle, existing alternatives | Excavation, Sharpening | +| The Mom Test | Question quality lens, evidence of pain, past behavior over future prediction | All sections | +| Design Sprint | Long-term goal, sprint questions, HMW reframing, journey mapping | Sharpening, Grounding | +| Wardley Mapping | Value chain, evolution axis, build vs. buy, movement awareness | Grounding | +| First Principles | Assumption excavation, root cause questioning, inversion, real vs. perceived constraints | Excavation, Grounding | diff --git a/plugins/loaf/skills/breakdown/SKILL.md b/plugins/loaf/skills/breakdown/SKILL.md index b247d64c5..18293b644 100644 --- a/plugins/loaf/skills/breakdown/SKILL.md +++ b/plugins/loaf/skills/breakdown/SKILL.md @@ -91,7 +91,7 @@ Decompose specifications into atomic, implementable tasks. 1. Can a single implementer complete this? If no, split by concern 2. Does it touch multiple unrelated concerns? If yes, split by concern -3. Will the agent need too much context? If yes, split into phases +3. Will the agent need too much context? If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? If yes, merge back ### Anti-Patterns diff --git a/plugins/loaf/skills/foundations/SKILL.md b/plugins/loaf/skills/foundations/SKILL.md index 68310c3e3..79494adc7 100644 --- a/plugins/loaf/skills/foundations/SKILL.md +++ b/plugins/loaf/skills/foundations/SKILL.md @@ -115,6 +115,22 @@ Engineering foundations for consistent, high-quality code. | Constants | `UPPER_SNAKE` | `UPPER_SNAKE` | | Tests | `test___` | `describe/it` blocks | +### Artifact Names Never Cite Their Work Unit + +Name an artifact for what it is, never for the work unit that produced it. The directory or Change that contains it already records that provenance, so repeating it in the filename inverts the reference and rots the moment the work closes: a work unit points at its artifacts, artifacts never point back. + +| Instead of | Write | +|------------|-------| +| `u8-claude-smoke.mjs` | `smoke-claude-code-startup.mjs` | +| `report-spec-053-taxonomy-signoff.md` | `taxonomy-signoff.md` | +| `TASK-074-sidecar-audit-report.md` | `sidecar-audit.md` | + +Provenance belongs in a front-matter field such as `source:`, where it can be read and updated, not in a name that has to be renamed to stay true. + +Two look-alikes are correct and stay. A **version** is identity, not reference: `claude-code-2.1.218-plugin-startup-smoke.json`. A **timestamp** records when, not which work unit: `20260620-214448-skills-audit.md`. And a numbered record living in the directory that owns it *is* that entity, so `.agents/specs/SPEC-042-slug.md` and `docs/decisions/ADR-007-slug.md` are its own name rather than a citation. + +`loaf check --hook artifact-names` enforces this at commit time over tracked artifacts, grandfathering anything already `final` or `archived`. + ## Test Patterns Scenario-based fixture naming: diff --git a/plugins/loaf/skills/git-workflow/references/commits.md b/plugins/loaf/skills/git-workflow/references/commits.md index b4b87499c..9c6e391cb 100644 --- a/plugins/loaf/skills/git-workflow/references/commits.md +++ b/plugins/loaf/skills/git-workflow/references/commits.md @@ -185,7 +185,7 @@ Internal terms that have no meaning outside the team's working context: - Spec IDs and task IDs (`SPEC-024`, `TASK-042`) - Session, sprint, or branch references - Internal terminology from skills/docs that isn't part of the user's mental model — e.g. `Q1`/`Q2`/`Q3` question numbers from a Triage Gate, internal gate-logic notation like `(Q1 OR Q2) AND Q3`, hook IDs that aren't user-facing -- "How the work got done" framing — interview steps, breakdown phases, review gates +- "How the work got done" framing — interview steps, breakdown steps, review gates ### Keep @@ -252,7 +252,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE] Four hooks automatically enforce the conventions documented in this file: -| Hook | Phase | Behavior | +| Hook | Timing | Behavior | |------|-------|----------| | `github-account` | Pre-tool (Bash) | Force-switch: switches the active `gh` account to the configured one before `gh` commands run (passes with a warning), exempting `gh auth` administration, and blocks only when the switch fails. It writes the shared global account pointer on every mismatched `gh` call -- read-only ones included -- so concurrent sessions on different identities collide on that pointer more often. | | `workflow-pre-pr` | Pre-tool (Bash) | Advisory: reminds about CHANGELOG [Unreleased] entries and PR format. Non-blocking. | @@ -269,26 +269,14 @@ BREAKING CHANGE: Description of breaking change. ### Pre-Release Versions -When developing toward a major version, use pre-release suffixes to mark development milestones: - -``` -2.0.0-dev.0 → dev.1 → dev.2 → ... → 2.0.0 - ↑ ↑ ↑ ↑ - start dev milestone milestone stable release -``` - | Suffix | Meaning | When to use | |--------|---------|-------------| -| `-dev.N` | Development milestone | Active development toward a target version | | `-alpha.N` | Alpha pre-release | Feature-complete but untested broadly | | `-beta.N` | Beta pre-release | Testing with wider audience | | `-rc.N` | Release candidate | Final validation before stable | **Convention:** -- Set the target version with `-dev.0` when starting a major effort (e.g. `2.0.0-dev.0`) -- Bump the dev counter (`-dev.N` → `-dev.N+1`) when a meaningful batch of landed work is ready to publish — a completed spec, a related feature group, or a release train -- Don't bump for every commit — that's what git history is for -- Strip the suffix (`-dev.N` → `2.0.0`) when all planned work is complete +- Use standard SemVer pre-release identifiers (`alpha`, `beta`, or `rc`) when publishing pre-release versions. - `loaf release` handles all bump types: `prerelease`, `release`, `major`, `minor`, `patch` -**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects with multi-milestone development cycles. +**Not required** — projects using simple `MAJOR.MINOR.PATCH` versioning can ignore pre-release suffixes entirely. This convention is for projects publishing staged pre-releases before stable releases. diff --git a/plugins/loaf/skills/handoff/SKILL.md b/plugins/loaf/skills/handoff/SKILL.md index d38d056f2..094433b43 100644 --- a/plugins/loaf/skills/handoff/SKILL.md +++ b/plugins/loaf/skills/handoff/SKILL.md @@ -120,3 +120,7 @@ Set `deprecated_at` and `deprecated_by` only when moving to `deprecated`. - **orchestration** — Maintains journal continuity and cross-agent coordination - **wrap** — Writes an optional end-of-conversation checkpoint to the journal - **housekeeping** — Deletes deprecated handoffs after confirmation + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/plugins/loaf/skills/housekeeping/SKILL.md b/plugins/loaf/skills/housekeeping/SKILL.md index 0827880d2..717a341ea 100644 --- a/plugins/loaf/skills/housekeeping/SKILL.md +++ b/plugins/loaf/skills/housekeeping/SKILL.md @@ -138,3 +138,7 @@ After housekeeping, suggest `/loaf:reflect` if the session produced key decision | Report Template | [templates/report.md](templates/report.md) | Creating cleanup reports | | Linear Integration | `orchestration/references/linear.md` | Checking external issue status | | Journal Continuity | `orchestration/references/journal.md` | Understanding the project journal model | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/plugins/loaf/skills/implement/SKILL.md b/plugins/loaf/skills/implement/SKILL.md index 53a74e92e..a4eee6b52 100644 --- a/plugins/loaf/skills/implement/SKILL.md +++ b/plugins/loaf/skills/implement/SKILL.md @@ -92,9 +92,9 @@ Parse `$ARGUMENTS` to determine the work type: | Input Pattern | Type | Action | |---------------|------|--------| | `TASK-XXX` | Local task | Load via `loaf task show`, log the task coupling | -| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency waves | -| `TASK-XXX..YYY` | Task range | Expand range, build dependency waves | -| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency waves | +| `SPEC-XXX` | Spec orchestration | If spec frontmatter has `linear_parent`, resolve to that Linear parent and follow Linear-Native Routing. Otherwise resolve local tasks and build dependency-ready rounds | +| `TASK-XXX..YYY` | Task range | Expand range, build dependency-ready rounds | +| `TASK-XXX,YYY,ZZZ` | Task list | Parse list, build dependency-ready rounds | | `PLT-123`, `ENG-198`, `PROJ-123` | Linear issue | **If `integrations.linear.enabled` is `true`:** fetch via `get_issue`, then branch on parent vs sub-issue — see [Linear-Native Routing](#linear-native-routing). **Otherwise:** treat as label text or create local task | | Description text | Ad-hoc | Auto-create local task from description, then fall through to task-coupled flow | @@ -346,7 +346,7 @@ When multiple valid approaches exist: spawn council (5-7 agents, odd), present r | Topic | Reference | Use When | |-------|-----------|----------| -| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency waves | +| Batch Orchestration | [batch-orchestration.md](references/batch-orchestration.md) | Running specs, task ranges, or task lists with dependency-ready rounds | | Branch and Completion | [branch-and-completion.md](references/branch-and-completion.md) | Branch management, team routing, diagrams, Linear sync, journaling, task completion | --- diff --git a/plugins/loaf/skills/implement/references/batch-orchestration.md b/plugins/loaf/skills/implement/references/batch-orchestration.md index 8e4aa0310..0f9d3d217 100644 --- a/plugins/loaf/skills/implement/references/batch-orchestration.md +++ b/plugins/loaf/skills/implement/references/batch-orchestration.md @@ -2,63 +2,63 @@ ## Contents - Orchestration Options -- Batch Resolution and Wave Planning +- Batch Resolution and Dependency-Ready Scheduling - Option Handling - Batch Execution Model - Blocked-State Recovery -Detailed reference for running specs, task ranges, or task lists with dependency waves. +Detailed reference for running specs, task ranges, or task lists with dependency-ready scheduling. ## Orchestration Options | Option | Behavior | |--------|----------| -| `--dry-run` | Show dependency/wave execution plan, do not run agents | -| `--parallel` | Run tasks in the same wave concurrently (max 3 at once) | -| `--continue` | Resume a blocked orchestration from the recorded task/wave | +| `--dry-run` | Show dependency-ready execution plan, do not run agents | +| `--parallel` | Run tasks in the same dependency-ready group concurrently (max 3 at once) | +| `--continue` | Resume a blocked orchestration from the recorded task/group | | `--skip TASK-XXX` | Mark one blocked task as skipped and continue | | `--abort` | Mark orchestration as aborted and stop remaining work | -## Batch Resolution and Wave Planning +## Batch Resolution and Dependency-Ready Scheduling For `SPEC-XXX`, `TASK-XXX..YYY`, and `TASK-XXX,YYY,ZZZ`: 1. Resolve selected tasks and validate each task file exists. 2. Extract `depends_on` from each task and build a dependency graph. -3. Group tasks into dependency waves: - - Wave 1: tasks with no unresolved dependencies - - Wave N: tasks whose dependencies are completed in earlier waves -4. If `--parallel` is set, allow parallel execution only within a wave and only for non-conflicting tasks. -5. Present execution plan (tasks, waves, mode, total count) and ask for confirmation unless `--dry-run`. -6. Track progress in the journal and in task statuses: log wave boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. +3. Group tasks into dependency-ready rounds: + - First round: tasks with no unresolved dependencies + - Each subsequent round: tasks whose dependencies are completed in earlier rounds +4. If `--parallel` is set, allow parallel execution only within a dependency-ready round and only for non-conflicting tasks. +5. Present execution plan (tasks, dependency-ready rounds, mode, total count) and ask for confirmation unless `--dry-run`. +6. Track progress in the journal and in task statuses: log round boundaries and the current task with `loaf journal log`, and drive each task's status with `loaf task update`. The journal plus task statuses are the durable record of where the batch is. ## Option Handling (`--continue`, `--skip`, `--abort`) 1. Recover batch progress from the journal: `loaf journal recent --since-last-wrap` (or `loaf journal context`) plus `loaf task list --json` to see which tasks are still open. -2. If `--continue`: resume from the last logged wave and task. -3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same wave. +2. If `--continue`: resume from the last logged dependency-ready round and task. +3. If `--skip TASK-XXX`: mark that task `skipped` via `loaf task update`, log the reason with `loaf journal log`, continue the same dependency-ready round. 4. If `--abort`: log `block(orchestration): aborted`, print a summary, and stop. 5. If no in-flight batch is evident from the journal, report that and ask for fresh selection input. ## Batch Execution Model -When input resolves to multiple tasks, run a wave-based loop: +When input resolves to multiple tasks, run a dependency-ready round loop: 1. Set orchestration mode (`sequential` by default, `parallel` only with `--parallel`). -2. For each wave: - - Log the wave start with `loaf journal log` +2. For each dependency-ready round: + - Log the round start with `loaf journal log` - Run each task (sequentially, or concurrently within safety limits) - For each task: set `in_progress` -> spawn agent -> run task verification -> mark `done`/`failed` via `loaf task update` 3. If any task fails verification, stop immediately and log `block(orchestration): failed `. -4. Consider a wave complete only when all its tasks are `done` or skipped. -5. Continue until all waves complete, then log a closing entry summarizing the batch. +4. Consider a round complete only when all its tasks are `done` or skipped. +5. Continue until all rounds complete, then log a closing entry summarizing the batch. ## Blocked-State Recovery When blocked, always print: - Failed task ID and title -- Wave number and current progress +- Dependency-ready round and current progress - Failure reason + key error output - Recovery commands: @@ -71,5 +71,5 @@ When blocked, always print: Use these semantics: - `--continue`: after fixes are applied, retry from the blocked task -- `--skip`: skip only the specified task and continue remaining tasks in the current wave +- `--skip`: skip only the specified task and continue remaining tasks in the current dependency-ready round - `--abort`: finalize the orchestration as aborted with no further execution diff --git a/plugins/loaf/skills/implement/references/branch-and-completion.md b/plugins/loaf/skills/implement/references/branch-and-completion.md index 0f715e4c5..250c8cdca 100644 --- a/plugins/loaf/skills/implement/references/branch-and-completion.md +++ b/plugins/loaf/skills/implement/references/branch-and-completion.md @@ -195,7 +195,7 @@ never implement through open `blockedBy`. **Print the current date and timestamp when:** - Waiting for user input or decision -- Completing a phase of work +- Completing a coherent unit of work - Encountering a blocker - Wrapping up the conversation diff --git a/plugins/loaf/skills/loaf-reference/SKILL.md b/plugins/loaf/skills/loaf-reference/SKILL.md index 3896aa200..7a2a61739 100644 --- a/plugins/loaf/skills/loaf-reference/SKILL.md +++ b/plugins/loaf/skills/loaf-reference/SKILL.md @@ -45,7 +45,7 @@ The Loaf operating manual for agents: how to discover commands, diagnose project | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent entries on the selected branch after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each layer reports `source_available`, `available_count`, `shown_count`, `truncated`, and an exact `expand_command`; paginated layers also return a cursor. `source_available: false` means the source could not be derived and is not an empty result. In particular, an unavailable Change source marks both `active-changes` and `active-lineage` unavailable and emits a diagnostic. diff --git a/plugins/loaf/skills/loaf-reference/references/command-routing.md b/plugins/loaf/skills/loaf-reference/references/command-routing.md index 7fcf2d64f..3bb5802e8 100644 --- a/plugins/loaf/skills/loaf-reference/references/command-routing.md +++ b/plugins/loaf/skills/loaf-reference/references/command-routing.md @@ -6,8 +6,9 @@ Which command a task needs. For exact flags, run `loaf --help`. | Intent | Route | |--------|-------| -| Shape new work | `loaf change init `, then `loaf change check` | -| Start working on a task | the implement workflow (/loaf:implement); `loaf task`/`loaf spec` stay transitional until the conversion pass — see the TRANSITIONAL note in CLAUDE.md | +| Shape new bounded work | `loaf change init `, then `loaf change check` | +| Start implementing new bounded work | the implement workflow (/loaf:implement) after shaping and validating its Change | +| Continue an existing task or spec record | `loaf task` and `loaf spec` remain supported for existing records | | Continue after a restart | `loaf journal context` | | Skills or content changed | `loaf build && loaf install --to ` | | See what is in progress | `loaf task list --active` | diff --git a/plugins/loaf/skills/orchestration/SKILL.md b/plugins/loaf/skills/orchestration/SKILL.md index b4a5c49bd..138b7dacf 100644 --- a/plugins/loaf/skills/orchestration/SKILL.md +++ b/plugins/loaf/skills/orchestration/SKILL.md @@ -20,7 +20,7 @@ version: 2.0.0-alpha.13 - Philosophy - Configuration - Artifact Locations -- Three-Phase Workflow +- Workflow by Lifecycle Comprehensive patterns for orchestration: coordinating multi-agent work, keeping the project journal current, running councils, delegating to specialized agents, and integrating with Linear. @@ -132,7 +132,7 @@ This skill uses paths from `.agents/loaf.json`: **Rule:** Agents write artifacts to disk, orchestrator reasons over artifacts, users retrieve from disk. -## Three-Phase Workflow +## Workflow by Lifecycle ### BEFORE (Planning) - Create/check external issue (Linear, GitHub) diff --git a/plugins/loaf/skills/orchestration/references/context-management.md b/plugins/loaf/skills/orchestration/references/context-management.md index 4a577309f..fd07ec254 100644 --- a/plugins/loaf/skills/orchestration/references/context-management.md +++ b/plugins/loaf/skills/orchestration/references/context-management.md @@ -19,7 +19,7 @@ Patterns for keeping long work resumable while using the project journal as exte Compaction is normal in long workflows. Design work that spans many exchanges so important state is already outside chat context. 1. **The journal is external memory.** Record decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. **Artifacts carry detail.** Changes, transitional tasks, reports, ADRs, and commits hold rich detail; journal entries point to them. +2. **Artifacts carry detail.** Changes, task-board records, reports, ADRs, and commits hold rich detail; journal entries point to them. 3. **Delegated work absorbs exploration.** Use delegated agents for broad investigation and return concise findings to the main context. 4. **`wrap` captures synthesis.** When meaningful work holds intentions or abandoned paths worth saving, write an optional `wrap` journal entry. @@ -36,7 +36,7 @@ Compaction is normal in long workflows. Design work that spans many exchanges so | `deferred-intent` | Open deferred-intent decision and spark pairs. | | `active-changes` | Git-derived active Change evidence and worktree state. | | `branch-recency` | Recent branch entries after entries already surfaced as active truth are removed. | -| `transitional-tasks` | Open task-board records retained during the Markdown-to-native transition. | +| `transitional-tasks` | Open task-board records retained for compatibility. | Each returned layer includes `source_available`, `available_count`, `shown_count`, `truncated`, and `expand_command`; paginated layers also include a cursor. Treat `source_available: false` as an explicit unavailable source, never as “nothing is active.” If Change discovery is unavailable, `active-changes` and `active-lineage` are unavailable and the digest carries a diagnostic. @@ -60,7 +60,7 @@ Use `/clear` when starting a completely new task, after the previous task is com PreCompact: 1. Flush unrecorded decisions, discoveries, blockers, and next actions with `loaf journal log`. -2. Reference Changes, transitional tasks, reports, commits, and files by stable ID or path. +2. Reference Changes, task-board records, reports, commits, and files by stable ID or path. 3. On an exact target mode with supported PreCompact delivery, let the hook nudge the flush; otherwise flush manually before compacting. PostCompact: diff --git a/plugins/loaf/skills/orchestration/references/linear.md b/plugins/loaf/skills/orchestration/references/linear.md index c794446bc..99877d957 100644 --- a/plugins/loaf/skills/orchestration/references/linear.md +++ b/plugins/loaf/skills/orchestration/references/linear.md @@ -103,7 +103,7 @@ In Linear-native mode (`integrations.linear.enabled: true`), each spec produces one parent **rollup issue** and N sub-issues under it. ``` -[SPEC-024] Agent framework alignment ← parent, label: `spec` +Agent framework alignment ← parent, label: `change` ├── Split reviewer profile into reviewer/auditor ← sub-issue, label: type/refactor ├── Harden MCP fallback path ← sub-issue, label: type/feature └── Migrate legacy task references ← sub-issue, label: type/refactor @@ -127,8 +127,8 @@ researcher). Consolidate historical profile variants and add tool-boundary tests so profiles can't drift without a test failing. ## Context -See `.agents/specs/SPEC-024-agent-framework-alignment.md` for full text, -council references, rabbit holes, and strategic tensions. +See the canonical change file in the repository for full text, council +references, rabbit holes, and strategic tensions. ## Progress Sub-issues track execution. @@ -213,7 +213,7 @@ None currently. |-------|---------| | `Working on API` | `- [ ] API implementation` | | `Done with schema` | `- [x] Schema updated` | -| `Phase 1: Discovery` | `Discovery - COMPLETE` | +| `Discovery: IN PROGRESS` | `Discovery: COMPLETE` | | `Journal entry: ...` | *(omit entirely)* | | `Council decision: ...` | *(omit entirely)* | | `Week 1 deliverables` | `Initial deliverables` | @@ -373,6 +373,6 @@ Use `scripts/suggest-team.py "task desc"` to get suggestions. ### DON'T - Use emoji in progress lists - Reference local files (sessions, councils, plans) -- Use phase/stage/week terminology +- Use numbered development-stage terminology - Include absolute file paths - Duplicate issue titles after IDs diff --git a/plugins/loaf/skills/orchestration/references/local-tasks.md b/plugins/loaf/skills/orchestration/references/local-tasks.md index d378226f6..d0d2417e9 100644 --- a/plugins/loaf/skills/orchestration/references/local-tasks.md +++ b/plugins/loaf/skills/orchestration/references/local-tasks.md @@ -167,7 +167,7 @@ project journal (`loaf journal recent`, `loaf journal search`). 1. Can a single specialized agent complete this? → If no, split by agent type 2. Does it touch multiple unrelated concerns? → If yes, split by concern -3. Will the agent need too much context? → If yes, split into phases +3. Will the agent need too much context? → If yes, split into smaller coherent units 4. Am I splitting just to have more tasks? → If yes, merge back ### Agent Scope diff --git a/plugins/loaf/skills/orchestration/references/parallel-agents.md b/plugins/loaf/skills/orchestration/references/parallel-agents.md index dd7a60758..c03352ca5 100644 --- a/plugins/loaf/skills/orchestration/references/parallel-agents.md +++ b/plugins/loaf/skills/orchestration/references/parallel-agents.md @@ -119,7 +119,7 @@ When streams complete: |---------|---------------------| | `/loaf:breakdown` | Identify parallelizable tasks during decomposition | | `/loaf:implement` | Single task, usually sequential | -| `/loaf:implement` | Runs dependency-wave orchestration, including parallel-safe tasks | +| `/loaf:implement` | Runs dependency-aware orchestration, including parallel-safe tasks | ## Conflict Resolution diff --git a/plugins/loaf/skills/refactor-deepen/SKILL.md b/plugins/loaf/skills/refactor-deepen/SKILL.md index 02c44a282..4664b7356 100644 --- a/plugins/loaf/skills/refactor-deepen/SKILL.md +++ b/plugins/loaf/skills/refactor-deepen/SKILL.md @@ -83,12 +83,12 @@ adds new ones when a deepening clearly names a structural module. ### Grilling Protocol -The interview phase imports the shared +The interview imports the shared [templates/grilling.md](templates/grilling.md) template — relentless interview, walk the decision tree, recommend per question, prefer exploration when the codebase can answer. Do not re-derive the protocol; follow it. -### INTERFACE-DESIGN Phase: 3 Unprimed Sub-Agents +### Interface Design: 3 Unprimed Sub-Agents When the grilling loop reaches interface design for a candidate, spawn **exactly 3 sub-agents with identical briefs**. Do not prime them with @@ -149,11 +149,12 @@ node -e 'const c=JSON.parse(require("fs").readFileSync(".agents/loaf.json","utf- If exit code is `1` (Linear-native enabled), continue in report-only mode and surface the exact storage constraint once: -> Linear-native plan storage pending artifact-taxonomy spec — continuing with a read-only report. +> Linear-native plan storage unavailable — continuing with a read-only report. Do **not** write the PLAN file, do **not** invoke `loaf kb glossary upsert`, and do **not** call Codex review. Partial state across local PLAN + remote -glossary is the explicit failure mode SPEC-034 forbids (see line 81 No-Gos). +glossary is an explicit failure mode: do not leave partial local PLAN state +when the remote glossary write is unavailable. The report is allowed because it is read-only and can feed a later brief. ### Termination @@ -210,7 +211,7 @@ surface adds plugin-level detection, this rule can switch to it. being proposed - Output uses the eight source terms verbatim — zero occurrences of "boundary," "service," "component," or "layer" in their place -- INTERFACE-DESIGN phase spawned exactly 3 sub-agents with identical briefs +- Interface Design spawned exactly 3 sub-agents with identical briefs - Whole-repo scans excluded generated/vendor/cache/build trees unless the user explicitly asked to inspect them - Report-only mode produced a complete read-only report and wrote nothing to @@ -310,7 +311,7 @@ speed but are unlikely at human pace. |-------|-----------|----------| | Vocabulary | [references/language.md](references/language.md) | Naming any module, interface, or seam — read first, every invocation | | Deepening Patterns | [references/deepening.md](references/deepening.md) | Classifying dependencies and applying seam discipline | -| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent INTERFACE-DESIGN phase | +| Interface Design | [references/interface-design.md](references/interface-design.md) | Running the parallel 3-agent Interface Design | | Grilling Protocol | [templates/grilling.md](templates/grilling.md) | Interview discipline during the candidate-selection loop | | PLAN Template | [templates/plan.md](templates/plan.md) | Writing the terminating PLAN artifact | diff --git a/plugins/loaf/skills/refactor-deepen/references/interface-design.md b/plugins/loaf/skills/refactor-deepen/references/interface-design.md index e79ab1e2c..a8e89253c 100644 --- a/plugins/loaf/skills/refactor-deepen/references/interface-design.md +++ b/plugins/loaf/skills/refactor-deepen/references/interface-design.md @@ -1,6 +1,6 @@ # Interface Design — Parallel Sub-Agent Pattern -The INTERFACE-DESIGN phase of `/loaf:refactor-deepen` proposes the public surface +The Interface Design activity of `/loaf:refactor-deepen` proposes the public surface of a deepened module by sampling three independent design attempts and presenting all three to the user. Variety must come from sampling, not from manufactured opposition. @@ -31,10 +31,8 @@ optimizes for minimalism, Agent 2 for flexibility, Agent 3 for the common-caller path. That choice is reasonable when the agents are domain-agnostic and the orchestrator wants guaranteed surface variety. -Loaf rejects that choice. The decision is captured in -[SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md), -specifically in the Rabbit Holes and No-Gos sections (lines 96 and 107). The -short version: priming manufactures diversity rather than letting it emerge, +Loaf rejects that choice. The active rule is to use identical briefs: priming +manufactures diversity rather than letting it emerge, and manufactured diversity is dishonest signal. If the three designs do converge, the response is more agents or rerun — not priming. See [Convergence Fallback](#convergence-fallback) below. @@ -71,7 +69,7 @@ Three reasons, in order of importance: 2. **No dominant lens upfront.** Picking which constraint each agent optimizes for is itself a design decision. Doing it pre-grilling biases - the entire phase toward whatever lens the orchestrator happened to + the entire activity toward whatever lens the orchestrator happened to pick. Loaf's grilling protocol is supposed to surface tradeoffs from the codebase and the user, not from the orchestrator's pre-commitments. @@ -91,7 +89,7 @@ Justification: researcher contract: "Return findings as structured reports: summary, options (ranked with trade-offs), evidence sources, and a recommendation." See [content/agents/researcher.md](../../../agents/researcher.md). -- Read-only access matches the phase's purpose. The INTERFACE-DESIGN phase +- Read-only access matches the activity's purpose. Interface Design proposes designs; it does not implement them. Granting write access invites scope creep into "let me just sketch the implementation" and pollutes the parallel sampling. @@ -102,14 +100,14 @@ Justification: ### When `implementer` Could Be an Alternative -If the design phase needs to write probe code — a quick spike to verify +If the design activity needs to write probe code — a quick spike to verify that a proposed interface compiles against the existing call sites, for example — the `implementer` profile becomes viable. See [content/agents/implementer.md](../../../agents/implementer.md). The default remains `researcher` because: -- Probe code at this phase is rarely necessary; the deepening review +- Probe code during this activity is rarely necessary; the deepening review catches most fatal interface mistakes before code is written. - Three implementers writing probe code in parallel risks three divergent partial implementations of the same module — a merge problem the user @@ -162,7 +160,7 @@ Inside the grilling loop, after dependency classification, only when: If the interface is obvious from the dependency category and the call sites — for example, a thin adapter over a true-external dependency — -skip the parallel phase. A single proposed interface is enough. +skip parallel exploration. A single proposed interface is enough. ## Convergence Fallback @@ -172,7 +170,7 @@ implementation strategy, same tradeoffs. Two cases: 1. **Convergence is real.** The problem has a single best answer. Accept the convergence as a genuine finding and proceed to the PLAN with that single design. Note in the PLAN's "rejected alternatives" section that - the parallel phase produced no meaningful variation. + parallel exploration produced no meaningful variation. 2. **Convergence feels accidental.** The designs are suspiciously similar, the user senses a missed branch, or the briefing was so @@ -226,7 +224,7 @@ escalates on its own. ## Cost Note -A single invocation of the parallel phase is approximately **3 × +A single invocation of parallel exploration is approximately **3 × deep-exploration cost** in tokens — three sub-agents each running a full design pass against the same context. With more-agents escalation, the cost scales linearly (4 agents = ~4 ×, 5 agents = ~5 ×). @@ -235,10 +233,10 @@ This pattern is **opt-in inside the grilling loop**. It is not auto-triggered on every `/loaf:refactor-deepen` invocation. The 3-agent default is the cost ceiling for the default settings — the skill does not scale agent count silently. If a candidate's interface is obvious, skip the -phase entirely and propose a single design. +activity entirely and propose a single design. The cost is an explicit tradeoff the user accepts when they enter the -INTERFACE-DESIGN phase for a non-obvious interface. The skill should +Interface Design activity for a non-obvious interface. The skill should surface the cost briefly before spawning: > Spawning 3 design agents in parallel (~3 × token cost). Proceed? @@ -265,7 +263,7 @@ After the three sub-agents return: | Don't | Do Instead | |-------|------------| | Prime agents with opposing constraints by default | Use identical briefs; let sampling produce variety | -| Auto-trigger the parallel phase on every invocation | Invoke only when interface is non-obvious | +| Auto-trigger parallel exploration on every invocation | Invoke only when interface is non-obvious | | Use `implementer` profile for design sub-agents | Use `researcher`; switch to `implementer` only on explicit user request | | Add a "lens" to the brief silently | Surface the tradeoff to the user before priming | | Pre-rank the three designs in the output | Present in arbitrary order, let the user pick | @@ -283,6 +281,3 @@ After the three sub-agents return: agent profile for design sub-agents - [content/agents/implementer.md](../../../agents/implementer.md) — Alternative profile when probe code is needed -- [SPEC-034](../../../../.agents/specs/SPEC-034-refactor-deepen-grilling-glossary.md) - — The shape decision (lines 64, 96, 107, 117) that established the - identical-brief default diff --git a/plugins/loaf/skills/refactor-deepen/templates/plan.md b/plugins/loaf/skills/refactor-deepen/templates/plan.md index cc04f240d..678132e1f 100644 --- a/plugins/loaf/skills/refactor-deepen/templates/plan.md +++ b/plugins/loaf/skills/refactor-deepen/templates/plan.md @@ -27,7 +27,7 @@ write a new file rather than updating an existing one. |-------|----------|-------| | `title` | Yes | One-line description of the deepening, not the candidate name | | `created` | Yes | ISO 8601 UTC, e.g. `2026-05-02T01:30:00Z` (must match the filename timestamp) | -| `status` | Yes | `drafting` on first write — lifecycle states are deferred to a follow-up spec | +| `status` | Yes | `drafting` on first write; this template does not define additional lifecycle states | | `spec` | Yes | `SPEC-NNN` if the plan is scoped under a spec; `null` otherwise (do not omit the key) | | `related` | No | List of related artifact IDs (`ADR-*`, `SPEC-*`, idea filenames, other plan filenames) | @@ -36,8 +36,7 @@ identity, mirroring councils and ideas. ## Required Sections -The five sections below are the *minimal shape* defined in SPEC-034. Order is -load-bearing: each section assumes the previous one is settled. Do not reorder. +The five sections below are the *minimal shape* for a PLAN. Order is load-bearing: each section assumes the previous one is settled. Do not reorder. 1. **Candidate** — what's being considered for deepening. Name the **module** verbatim (use the canonical glossary term — run `loaf kb glossary check` @@ -111,14 +110,12 @@ proportional to actual usage, matching how `.agents/specs/` behaves. ## Linear-Native Mode: Fail Fast -PLAN files are **local-only storage**. Per SPEC-034 line 81, write commands -must fail fast in Linear-native mode rather than silently degrade. The -consuming skill (`/loaf:refactor-deepen`) is responsible for: +PLAN files are **local-only storage**. Write commands must fail fast in Linear-native mode rather than silently degrade. The consuming skill (`/loaf:refactor-deepen`) is responsible for: 1. Reading `.agents/loaf.json` and checking `integrations.linear.enabled`. 2. If true: aborting before `mkdir -p .agents/plans` and before any write, with the verbatim error - `"Linear-native plan storage pending artifact-taxonomy spec — local mode only for now."` + `"Linear-native plan storage unavailable — continuing with a read-only report."` 3. If false: proceeding with the write as documented above. This template intentionally does **not** wrap the write in a diff --git a/plugins/loaf/skills/research/SKILL.md b/plugins/loaf/skills/research/SKILL.md index b319446d8..93d93d2e6 100644 --- a/plugins/loaf/skills/research/SKILL.md +++ b/plugins/loaf/skills/research/SKILL.md @@ -145,3 +145,7 @@ frontmatter to represent operational status. - **reflect** - For updating strategy post-shipping - **architecture** - For making technical decisions - **strategy** - For discovering strategic context + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/plugins/loaf/skills/shape/SKILL.md b/plugins/loaf/skills/shape/SKILL.md index e70dde14c..f52b53ec0 100644 --- a/plugins/loaf/skills/shape/SKILL.md +++ b/plugins/loaf/skills/shape/SKILL.md @@ -159,3 +159,7 @@ Offer to push the branch and open a draft PR, using [the PR template](templates/ | Decomposition | [references/decomposition.md](references/decomposition.md) | Sizing and ordering Implementation Units | | CLI boundary | [references/cli-boundary.md](references/cli-boundary.md) | Reading `loaf change init`/`check` output, or explaining `--require-executable` | | Critique Gate | [references/critique-gate.md](references/critique-gate.md) | Self-challenging scope and boundaries before finalizing | + +## Artifact Naming + +Name every artifact you create for what it is, never for the work unit that produced it: the containing directory or Change already records that provenance. Put the source in a front-matter field, not the filename. Versions and timestamps are identity and stay. See the `foundations` skill for the full rule; `loaf check --hook artifact-names` enforces it at commit. diff --git a/plugins/loaf/skills/shape/references/cli-boundary.md b/plugins/loaf/skills/shape/references/cli-boundary.md index efb3cc1b5..7f5816b03 100644 --- a/plugins/loaf/skills/shape/references/cli-boundary.md +++ b/plugins/loaf/skills/shape/references/cli-boundary.md @@ -13,7 +13,7 @@ Folder resolution: an explicit `[folder]` argument always wins; otherwise the cu Output splits into two tiers: - **Violations** — always fail (exit code 2), regardless of flags: status-like frontmatter keys (`readiness`, `status`, `state`) or values matching the canonical change-state vocabulary; frontmatter not opening the file at byte one; malformed `YYYYMMDD-slug` folder naming; identity mismatch between `change:`/`created:` and the folder name; missing Product Contract sections (Problem, Hypothesis, Scope, Observable Workflow, Rabbit Holes and No-Gos). -- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A shaping-stage Change with open gaps is valid; the report just says what's still missing. +- **Derived executability** — reported, never gating by default. A Change is executable when Planning Contract, Implementation Units, Verification Contract, and Definition of Done are all present and non-empty (bracket placeholders and HTML comments don't count as content). A Change with open gaps is incomplete and non-executable; the report just says what's still missing. `--require-executable` turns structural executability into a gate (exit code 1 if not structurally executable); it does not prove implementation completion. This is implement's preflight and CI's non-draft-PR check, not something shape itself passes during shaping. diff --git a/plugins/loaf/skills/shape/references/decomposition.md b/plugins/loaf/skills/shape/references/decomposition.md index edf38530b..5ffefbe74 100644 --- a/plugins/loaf/skills/shape/references/decomposition.md +++ b/plugins/loaf/skills/shape/references/decomposition.md @@ -4,7 +4,7 @@ Shaping step absorbed from the retired breakdown skill: dependency awareness, gr ## What Survives -- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into phases. Are you splitting just to have more units? If yes, merge back. +- **The Right Size Test** — before finalizing a unit boundary, check: Can a single implementer complete this? If no, split by concern. Does it touch multiple unrelated concerns? If yes, split by concern. Will the agent need too much context? If yes, split into smaller coherent units. Are you splitting just to have more units? If yes, merge back. - **Right-sizing rules** — one agent type per unit (completable by a single implementer), one concern per unit (one layer, service, or component), context-appropriate (fits in model context with room for exploration), not over-fragmented (don't split what naturally belongs together). - **Per-unit verification discipline** — every unit includes its own observable done condition. Never a separate "verify" unit; keep tests with the code they test. - **Own the decisions** — decide granularity and unit boundaries autonomously. Ask the user only when two orderings are genuinely equally valid with different trade-offs; otherwise decide and move on.