diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 58a2235..aa5942a 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,7 +5,7 @@ "email": "mho@looplia.run" }, "metadata": { - "version": "3.2.1", + "version": "3.3.0", "description": "Skills for product planning, project scaffolding, and agentic development workflows." }, "plugins": [ @@ -49,6 +49,13 @@ "./skills/agentic-development-workflow/git-ref" ] }, + { + "name": "human-alignment", + "description": "Project pulse from product-context.yaml: where it stands, what is owed to a human and for how long, and what changed since you last looked.", + "source": "./", + "strict": false, + "skills": ["./skills/human-alignment"] + }, { "name": "patterns", "description": "Reusable design patterns: gen/eval, executor abstraction, autopilot orchestration, dynamic workflows, workflow-feedback, design-lens (HCI theory + heuristic health-check).", diff --git a/.oxfmtrc.json b/.oxfmtrc.json index c871730..1a35687 100644 --- a/.oxfmtrc.json +++ b/.oxfmtrc.json @@ -1,3 +1,3 @@ { - "ignorePatterns": [] + "ignorePatterns": ["docs/human-alignment/example-*/**"] } diff --git a/CHANGELOG.md b/CHANGELOG.md index f2eaaf5..8004ba8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,74 @@ bug fixes → **patch**; removing or breaking a skill contract → **major**. > `/envision`, `/dispatch`, `/reflect`, …), which records product-state history > for that project. See [`docs/glossary.md`](docs/glossary.md). +## [3.3.0] - 2026-07-27 + +`/aep-human-alignment` — a project pulse. One command answers where a project +stands, what is owed to a human and for how long, and what changed since you +last looked, derived from `product-context.yaml`. + +The design went through ten revisions and two independent generator/evaluator +rounds, both of which failed the artifact it originally set out to produce. What +ships is what survived that: the deterministic half. + +### Added + +- **`skills/human-alignment/`** — a standalone top-level skill, a fifth + marketplace plugin, emitting on three clocks rather than one: + - **The fact plane** (`derive.mjs` + `census.mjs` + `facts.schema.json`) — + every number the surface can state, derived from the plan file and git, + validated against its own schema. `census.mjs` classifies every populated + path in the consumer's plan file as derived / ignored-with-a-reason / + unhandled, so what the tooling cannot see is a number rather than a + surprise. + - **The pulse** (`pulse.mjs`) — the read-time answer to _what happened since I + last looked_. It writes nothing, asserts nothing, and deals in events rather + than states. Four sections: obligations with their age, transitions since + your cursor, what needs a human, and open work that has stopped moving. + - **The deterministic architecture pipeline** (`scan-workspace.mjs` → + `arch-rules.mjs` → `receipt-consumer.mjs`) — the real package topology, with + concepts bound to code units by measurement from the work record, rendered + through archify's layout gates and repaired only by its own receipts. +- **Two framework specs** in `skills/product-context/_shared/references/` — + `attention-set.md` (what needs a human, its priority order, per-predicate + schema tolerance) and `drift-facts.md` (where reality drifted). + +### Changed + +- **`/aep-validate` gains a blocking coherence precheck.** Five plan-file + defects that want an action rather than a reader — completed work under a gate + recorded as never started, an undefined gate status, a roll-up that disagrees + with the record it summarizes, a module used but never declared, and fields a + consumer invented — now run mechanically before any agent is spawned, and + fail. They were previously narrated in a document while nothing stopped. +- **`scripts/build-skills.sh` materializes shared resources into top-level + skills and shared `scripts/`**, on the same per-file rule it has always used + for references. The coherence detector is shared rather than copied: two + copies of a drift detector drift. +- **Pre-commit hooks no longer fail a docs-only commit.** oxlint and oxfmt error + rather than no-op when handed nothing they handle; both now carry a glob and + oxfmt guards on the post-filter set. + +### Not yet ready + +- **The one-page HTML brief (emission 3) ships unproven and is documented as + such.** Two independent evaluations failed it — not on machinery, which + passes, but on prose asserting more than the facts carried. Its per-layer + regeneration trigger is unbuilt; today it generates per invocation, which the + decision doc identifies as the central design error. Findings and a generated + example are committed at `docs/human-alignment/example-looplia/` as evidence, + not as a model to copy. Use the pulse. + +### Notes + +- Only a `passed` gate yields an unchipped capability; `scripted_passed` appears + solely under an EXP chip naming the acceptance run that would settle it, and a + gate whose sign-off was withdrawn yields neither. +- A roll-up field being zero is a statement about the roll-up, not about the + data. Spend derives from `stories[].cost_usd`; the concept-to-code binding + derives from `stories[].module` × `files_affected`. +- Consumers must re-pin to `@v3.3.0` before `/aep-human-alignment` is available. + ## [3.2.1] - 2026-07-18 Patch: the `secret_scan` example in the scaffolded `policy.md` named diff --git a/README.md b/README.md index 6f8ae9d..8b0b598 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,7 @@ The `skills` CLI selects by skill name (there's no "group" flag). The groups map | **Product** (product-context) | `aep-envision`, `aep-map`, `aep-model`, `aep-dispatch`, `aep-validate`, `aep-calibrate`, `aep-reflect`, `aep-watch` | | **Setup** (project-setup) | `aep-onboard`, `aep-scaffold`, `aep-e2e-skill-scaffolding` | | **Patterns** (patterns) | `aep-gen-eval`, `aep-executor`, `aep-autopilot`, `aep-workflow`, `aep-workflow-feedback`, `aep-design-lens` | +| **Alignment** (human-alignment) | `aep-human-alignment` | > **Releasing:** bumping `metadata.version` in `.claude-plugin/marketplace.json` must come with a matching [CHANGELOG.md](CHANGELOG.md) entry in the same PR (move the `[Unreleased]` notes under the new `[X.Y.Z] - DATE` heading), and a `vX.Y.Z` git tag on merge to `main`. @@ -626,30 +627,31 @@ Generate a dimension-specific brief, explore or discuss, capture decisions for a ## All Skills -| Skill | Plugin | Purpose | -| ---------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------- | -| `/aep-envision` | product-context | Opportunity brief + context document | -| `/aep-map` | product-context | System map + story graph + agent topology | -| `/aep-model` | product-context | Object-first UI structure (OOUX/ORCA Object Map) for UI products | -| `/aep-validate` | product-context | Generator/evaluator validation of any AEP artifact | -| `/aep-dispatch` | product-context | Pick next story + create OpenSpec change | -| `/aep-calibrate` | product-context | Human alignment checkpoint for any quality dimension | -| `/aep-reflect` | product-context | Classify feedback + update context | -| `/aep-watch` | product-context | Ingest telemetry/errors → auto-file stories (self-feeding loop) | -| `/aep-onboard` | project-setup | Verify tools + install plugins | -| `/aep-scaffold` | project-setup | Scaffold monorepo + initialize OpenSpec; idempotent audit→converge for existing projects | -| `/aep-e2e-skill-scaffolding` | project-setup | Generate/upgrade the canonical BDD layer-gate e2e-test skill | -| `/aep-design` | agentic-development-workflow | Explore + propose + review a feature | -| `/aep-launch` | agentic-development-workflow | Spawn workspace (Claude bg subagents/sessions; Codex subagents/exec; tmux when pinned) + optional evaluator | -| `/aep-build` | agentic-development-workflow | Implement → test → PR → merge | -| `/aep-wrap` | agentic-development-workflow | Archive + cleanup + suggest reflect | -| `/aep-git-ref` | agentic-development-workflow | AEP git + worktree conventions (on-demand) | -| `/aep-gen-eval` | patterns | Generator/evaluator separation for honest validation | -| `/aep-executor` | patterns | Host-agnostic backend for spawning/steering workspace agents | -| `/aep-autopilot` | patterns | Autonomous dispatch-launch-monitor-wrap loop via `/loop` | -| `/aep-workflow` | patterns | Dynamic workflows — author a custom multi-agent harness for a task (+ sub-pattern catalog) | -| `/aep-workflow-feedback` | patterns | Capture + review process learnings between downstream projects and AEP | -| `/aep-design-lens` | patterns | Theory-grounded design guideline + heuristic health-check (HCI/design-theory catalog + task/data lens selection) | +| Skill | Plugin | Purpose | +| ---------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `/aep-envision` | product-context | Opportunity brief + context document | +| `/aep-map` | product-context | System map + story graph + agent topology | +| `/aep-model` | product-context | Object-first UI structure (OOUX/ORCA Object Map) for UI products | +| `/aep-validate` | product-context | Generator/evaluator validation of any AEP artifact | +| `/aep-dispatch` | product-context | Pick next story + create OpenSpec change | +| `/aep-calibrate` | product-context | Human alignment checkpoint for any quality dimension | +| `/aep-reflect` | product-context | Classify feedback + update context | +| `/aep-watch` | product-context | Ingest telemetry/errors → auto-file stories (self-feeding loop) | +| `/aep-onboard` | project-setup | Verify tools + install plugins | +| `/aep-scaffold` | project-setup | Scaffold monorepo + initialize OpenSpec; idempotent audit→converge for existing projects | +| `/aep-e2e-skill-scaffolding` | project-setup | Generate/upgrade the canonical BDD layer-gate e2e-test skill | +| `/aep-design` | agentic-development-workflow | Explore + propose + review a feature | +| `/aep-launch` | agentic-development-workflow | Spawn workspace (Claude bg subagents/sessions; Codex subagents/exec; tmux when pinned) + optional evaluator | +| `/aep-build` | agentic-development-workflow | Implement → test → PR → merge | +| `/aep-wrap` | agentic-development-workflow | Archive + cleanup + suggest reflect | +| `/aep-git-ref` | agentic-development-workflow | AEP git + worktree conventions (on-demand) | +| `/aep-gen-eval` | patterns | Generator/evaluator separation for honest validation | +| `/aep-executor` | patterns | Host-agnostic backend for spawning/steering workspace agents | +| `/aep-autopilot` | patterns | Autonomous dispatch-launch-monitor-wrap loop via `/loop` | +| `/aep-workflow` | patterns | Dynamic workflows — author a custom multi-agent harness for a task (+ sub-pattern catalog) | +| `/aep-workflow-feedback` | patterns | Capture + review process learnings between downstream projects and AEP | +| `/aep-design-lens` | patterns | Theory-grounded design guideline + heuristic health-check (HCI/design-theory catalog + task/data lens selection) | +| `/aep-human-alignment` | human-alignment | Project pulse from `product-context.yaml` — where it stands, what is owed to a human and for how long, what changed since you last looked | Launches are **native-first** with **hub-and-spoke human gates** — see [Launch modes](#launch-modes--native-first-executor-backends) and diff --git a/docs/decisions/human-alignment.md b/docs/decisions/human-alignment.md index 81cae6b..1f7a3a8 100644 --- a/docs/decisions/human-alignment.md +++ b/docs/decisions/human-alignment.md @@ -60,6 +60,56 @@ > ruled (keep the latest 3); and the revision-6 rulings (scope names, mermaid off > the primary path) are propagated to every section that still contradicted them. +> **Revision 8 (2026-07-25):** owner rulings after the implementation run, on +> what the Engineering band is _for_. (a) The band is **prospective and +> structural**, not a deeper cut of progress — an engineer needs the current +> structure and _what the next design does to it_, and "where work happened / +> what it cost / where it failed" is Project's depth, not Engineering's. Its +> spine is **Now · Concepts · Next · Options** (D8). (b) The ontology is no +> longer a deployment taxonomy: nodes are **concept modules measured against the +> code units that carry them**, because `stories[].module` × `files_affected` +> makes that binding derivable today. (c) Suggestions are **allowed and +> welcome**, but only as a **Design Option Set** with a derived trigger, ≥3 +> options including "leave it as is", per-option cost/benefit in the project's +> own measured terms, a design sketch, and a stated ranking criterion — a bare +> one-liner recommendation is banned (D8). (d) Trigger thresholds are **fixed in +> the spec**, not configurable. (e) The mining principle: when deterministic +> signal looks insufficient, **dig further into what the project actually +> records** — do not concede the ground to agent judgment. Revision 7's own +> implementation violated this three times (D7). + +> **Revision 9 (2026-07-25):** after an independent generator/evaluator pass on +> the generated brief returned **FAIL**. Nine content defects, and all but one +> share a single shape: **the prose needed a fact the derivation had not +> produced, so the authoring agent supplied it from a diagram label, from +> ambient knowledge, or by counting manually — and the audit could not see it, +> because its unit of check was the digit rather than the claim.** The root +> cause is that the facts plane was designed top-down (what should the brief +> show?) against a source carrying **483 populated key paths**, of which the +> derivation read about **thirty**. Revision 9 replaces hole-by-hole patching +> with four mechanisms that make the gap visible and the omission illegal (D9): +> a **source census**, **claims that bind** rather than numbers that bind, +> facts that carry **predicates** rather than raw fields, and tools that +> **declare their own coverage**. Owner rulings: the census classifies at +> **path-template level**, and an `ignored` entry must carry a **reason**, not +> a checkmark. + +> **Revision 10 (2026-07-26):** after two independent reviews of the design +> itself and a re-measurement of the velocity premise revision 9 rested on. +> +> **Scope note, because revisions 7–9 blurred it.** This revision is about **the +> surface's own design**. The reference consumer's plan-file hygiene — stale +> calibration entries, gates never flipped, an unwired cost roll-up, undeclared +> modules — is that consumer's business and `/aep-validate`'s. Those findings are +> evidence about _what this surface does and does not make visible_; they are not +> requirements on it, and treating them as such is how a rendering skill grew a +> detector suite. +> +> Three rulings: the unit of delivery is the **clock, not the page** (D10); the +> skill **renders and does not detect** (D11); and it **never keeps a private +> store** (D12). Plus corrections to D7 and D9 that are the design's own, not the +> consumer's. + ## Problem AEP's planning layer captures intent and state in `product-context.yaml` — stories, @@ -218,12 +268,12 @@ surface, so no separate stakeholder mode is needed. Bands are named by **scope, not audience** (owner ruling: role names make readers self-exclude; scope names only classify depth): **Overview · Product · Project · Engineering**. -| Band | Audience | Content (block re-homed from) | Derived from | Regeneration gate | -| ------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | -| **1 · Overview** | every role, 30 seconds | what this project is, one paragraph (PRIMER's essence) · health + progress in one sentence · the one ask + the while-you-were-away narrative (NOW) | identity fields; the attention set; state diff vs. baseline | identity: era · rest: never | -| **2 · Product** | whoever uses the product | what works today (shipped, user-visible capabilities) · what recently changed for users · what the current layer will add, in user language | **net-new derivation**: `passed` `layer_gates` + changelog, translated to user-visible outcomes (authored + anchored, D4 rules); `scripted_passed` gates admitted only under an EXP chip (see below) | capability list: gate reaches `passed` · rest: never | -| **3 · Project** | plan and progress | the full layer strip + current-layer story rows (FRONTIER) · queued layers, one sentence each + disclosure · what moved, where reality drifted, cost (LEDGER's plain layer) | `stories`, `layer_gates`, `changelog`, the drift facts | never (the LEDGER block stays the dark record) | -| **4 · Engineering** | the system itself | the embedded archify architecture artifact (semantic types, boundaries, guided views, passport — revision 5) + module-group cards · the loop + story state machine, vocabulary's sole definition (LIFECYCLE) · drift technical detail, gate table, raw story lists, all provenance anchors | `architecture` (+ optional reality probe) → typed IR → archify, the canonical vocabulary | structure change | +| Band | Audience | Content (block re-homed from) | Derived from | Regeneration gate | +| ------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| **1 · Overview** | every role, 30 seconds | what this project is, one paragraph (PRIMER's essence) · health + progress in one sentence · the one ask + the while-you-were-away narrative (NOW) | identity fields; the attention set; state diff vs. baseline | identity: era · rest: never | +| **2 · Product** | whoever uses the product | what works today (shipped, user-visible capabilities) · what recently changed for users · what the current layer will add, in user language | **net-new derivation**: `passed` `layer_gates` + changelog, translated to user-visible outcomes (authored + anchored, D4 rules); `scripted_passed` gates admitted only under an EXP chip (see below) | capability list: gate reaches `passed` · rest: never | +| **3 · Project** | plan and progress | the full layer strip + current-layer story rows (FRONTIER) · queued layers, one sentence each + disclosure · what moved, where reality drifted, cost (LEDGER's plain layer) | `stories`, `layer_gates`, `changelog`, the drift facts | never (the LEDGER block stays the dark record) | +| **4 · Engineering** | the system itself | **Now** the real code structure · **Concepts** the module vocabulary measured onto it · **Next** the queued design projected onto both, and what it needs that does not exist · **Options** only when a D8 trigger fires · the loop + story state machine, vocabulary's sole definition (LIFECYCLE) · gate table, raw story lists, all provenance anchors | code scan → `stories[].module` × `files_affected` binding → typed IR → archify (`compare` for Next), the canonical vocabulary | structure change | The six SIBYL jobs all survive — NOW and PRIMER's essence fuse into band 1, FRONTIER and LEDGER's plain layer form band 3, SHAPE and LIFECYCLE anchor band 4 — @@ -305,21 +355,53 @@ Carried over from the SIBYL contract, unchanged in meaning: open count · needs-you count) keeps the glance overview present at any scroll depth. - **The architecture view is generated by a deterministic code pipeline and - rendered by archify** (owner rulings, revisions 5–6). No agent judgment in the - loop: a workspace-graph scanner reads the real package topology (package.json / - turbo graph; dependency-cruiser is the later import-level rung; LSP is rejected - for batch graph work), a rule table transforms it into typed archify IR — - R1 exclude test packages · R2 fold ubiquitous deps (in-degree ≥ 60%) into cards - · R3 layered/cascade layout · R4 fixed semantic-type map · R5 boundaries from - directory structure · R6 transitive reduction · R7 fixed package→domain table · - R8 domain-level edge aggregation · R9 generated guided views · R10 permutation - search for row order — and a **mechanical receipt consumer** applies archify's - repair receipts (via/labelAt/labelDy) within the two-round bound. Same commit in, - byte-identical artifact out. **Three tiers**: the domain overview (≈9 nodes, the - embedded default), the full package graph (deep-dive), and the declared - architecture from the YAML (the authored narrative tier — meaning, not - verification). Code is the source of truth for edges; the YAML for meaning; - their disagreement is a drift fact, never silently reconciled. + rendered by archify** (owner rulings, revisions 5–6, scope corrected in + revision 8). The ruling was never "no agent anywhere in this view" — it is + **ground truth comes from code tooling, and translating it into something a + human understands is the agent's job**. A workspace-graph scanner reads the + real package topology (package.json / turbo graph; dependency-cruiser is the + later import-level rung; LSP is rejected for batch graph work); a rule table + transforms it into typed archify IR — R1 exclude test packages · R2 fold + ubiquitous deps (in-degree ≥ 60%) into cards · R3 layered/cascade layout · + R4 semantic-type map · R5 boundaries from directory structure · R6 transitive + reduction · **R7 concept-module ↔ code-unit binding, measured (below)** · + R8 edge aggregation · R9 generated guided views · R10 permutation search for + row order — and a **mechanical receipt consumer** applies archify's repair + receipts within the two-round bound. Same commit in, byte-identical artifact + out. +- **R7 is a measurement, not a naming convention** (revision 8). The first + implementation grouped packages by splitting their names on the first hyphen. + That is deterministic and worthless: `db` and `auth` being separate "domains" + is an artifact of how packages were named, not a fact about the system, and + the grouping threw away the 32 prose module descriptions the project already + carries. It produced 14 domains from 19 packages, 11 of them singletons — no + compression, no meaning. + **The project already states its own ontology and binds it to code:** + `stories[].module` (present on 396/396 stories in the reference consumer) says + which concept each piece of work belongs to, and `stories[].files_affected` + (also 396/396, 84% resolving to a real workspace package) says where that work + landed. The concept→code binding is therefore **measured from the work record**, + not declared and not guessed. No graph-clustering alternative can replace this: + clustering yields groups with no names, and a domain's _name_ is a human + concept that exists only in prose. +- **The Engineering band is prospective and structural** (owner ruling, revision + 8): **Now · Concepts · Next**, and the payload is the tension between them. + - **Now** — the real code structure. Ground truth, tool-derived. + - **Concepts** — the module vocabulary humans reason in, bound to Now by the + R7 measurement. The gap here is "the boundary you believe in is not the + boundary that exists". + - **Next** — the queued design projected onto Now: which code units the open + stories' modules land in, which concepts are net-new, and whether each has a + home. The gap here is "what the next design needs that the structure has + not got". This is the question no status surface answers and the one an + engineer most needs; archify's `compare` (Before/Delta/After) renders it, + pointed **forwards** rather than at the previous brief. + + Progress-shaped annotations — where work happened, what it cost, where it + failed — belong to Project's depth and are **excluded** from this band. That + separation is what keeps the pyramid honest: each band is the same three + questions at higher resolution, not a different subject. + - **All diagrams are archify; mermaid leaves the primary path** (revision 6). The AEP loop renders as an archify `workflow` diagram and the story state machine as an archify `lifecycle` diagram, so the page has one diagram system, one visual @@ -366,14 +448,14 @@ Carried over from the SIBYL contract, unchanged in meaning: The generation pipeline (each phase ends in a checkable postcondition, per the deterministic-orchestration standard): -| Phase | Action | Postcondition | -| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0 · Preflight | `product-context.yaml` exists (else point to `/aep-envision`); read `docs/human-alignment/manifest.json` for the delta baseline | baseline commit known, or first-run declared | -| 1 · Derive | run `scripts/derive.mjs`: extract **facts JSON** from `product-context.yaml` + git — story counts by state and layer, the attention set (D7), the drift facts (D7), the shipped-capability inputs for band 2 (passed layer gates + their summaries), changelog entries since baseline, layer-gate status, cost roll-up — and validate it against `facts.schema.json` | facts JSON exists and validates; every fact names its YAML path | -| 1.5 · Scan | run the deterministic architecture pipeline (D3), all three scripts named in D5: `scan-workspace.mjs` (workspace-graph scan) → `arch-rules.mjs` (R1–R10 → typed IR) → `receipt-consumer.mjs` (archify validate → apply receipts → deliver), producing the domain-overview and package-graph artifacts revision-pinned to HEAD; the declared-vs-actual gap joins the drift facts (import-level dependency-cruiser diff is the later rung) | artifacts delivered `code-verified` (package level), or scanner unavailable and the view is marked degraded | -| 2 · Author | fill `assets/template.html`: no number is ever typed into markup — every one is a `data-fact=""` binding the template's renderer fills at load (see the binding rule below); narrative (PRIMER, translations, LEDGER prose) is written fresh, tense-chipped, stamped with authored-at + source commit; narrative obeys the evidence-language rule and the cold-reader authoring rules below | every section rendered or stamped | -| 3 · Audit | run `scripts/audit.mjs` for the mechanical checks (number-provenance, statically: every `data-fact` path resolves in facts JSON, and no digit appears in authored markup outside a `data-fact` element or a provenance anchor; class preflight; chip-grammar: every non-fact chipped, no fact chipped, one chip per clause; translation-anchor 1:1 — every plain sentence cites a fact id, every surfaced fact has a plain sentence; prose vocabulary-budget count) plus the judgment checks from `references/checklist.md` (vocabulary audit against the D2 closed set, evidence-language audit, glance gate, cold-reader test, so-what test) | audit passes; failures emit structured receipts; at most two correction rounds | -| 4 · Deliver | write `docs/human-alignment/brief-T