Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "meridian",
"description": "Professional engineering discipline with user-owned workflows and model-specific corrections.",
"version": "0.12.0",
"version": "0.13.0",
"author": {
"name": "KodingDev"
},
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "meridian",
"description": "Professional engineering discipline with user-owned workflows and model-specific corrections.",
"version": "0.12.0",
"version": "0.13.0",
"author": {
"name": "KodingDev"
},
Expand Down
2 changes: 1 addition & 1 deletion .plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "meridian",
"version": "0.12.0",
"version": "0.13.0",
"hooks": "./hooks/hooks-copilot.json"
}
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ All notable changes to Meridian are recorded here. The format follows
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). History before
0.11.0 lives in the git log.

## [0.13.0] - 2026-07-25

### Added

- `commit` carries pull request description guidance: lead with rationale, describe behavior rather than the diff, state the feedback wanted, report what was actually verified, flag breaking changes and migrations, and scale the description to the change.
- Both commit messages and pull request descriptions are governed by an explicit rule that they describe the resulting code, never the session that produced it, with the circumstantial detail to omit enumerated.
- Specs and sketches carry a `Status` line through `DRAFT`, `APPROVED`, `IN PROGRESS`, `SHIPPED <sha>`, and `SUPERSEDED BY <file>`. `execute` moves it as implementation proceeds.

### Changed

- Model profiles are named for families and matched by prefix, so a later release in a mapped family keeps its corrections instead of dropping to the baseline. Matching is a plain prefix over the identifier the host reports, so vendor- or region-qualified identifiers (for example the `us.anthropic.` Bedrock form) still fall through to the baseline.
- **Breaking:** the `opus-4.8` profile is renamed `claude-opus`. A host-local `<state-base>/meridian/config.json` setting `"fallbackProfile": "opus-4.8"` no longer resolves and silently yields the baseline standard with no adapters. Rename the value to `claude-opus`.
- `claude-fable-` now resolves to the `fable` profile, which carries no adapters by design. A Fable session therefore no longer picks up a configured `fallbackProfile`.
- `commit` is model-invocable. Its conventions are reachable whenever a commit message or pull request description is written, including by other skills. Reaching them authorizes nothing: committing, pushing, and opening or editing a pull request sit behind a hard gate and each still require an explicit request.
- `execute` and `auto` point at `meridian:commit` for message conventions instead of restating them, and no longer describe the commit flow as un-reachable.
- Eval scenarios cover the new boundary: authoring a commit message or pull request description reaches `commit`, while reading history and an implied-approval prompt do not.

### Fixed

- Adapter resolution no longer depends on a single exact model identifier, which left every unlisted model on the baseline standard with no corrections applied.

## [0.12.0] - 2026-07-13

### Added
Expand Down
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,26 @@ These run only when you invoke them. One flow never silently enrolls you in anot
| `sketch` | Produce a lightweight contract for a small change |
| `execute` | Implement an approved spec or clear scope with proportionate verification |
| `review` | Perform a focused, report-only code review |
| `commit` | Create one clean, narrowly staged commit |
| `document` | Capture requested durable engineering knowledge |
| `auto` | Grant elevated autonomy for reversible, in-scope work |

Invoking a flow authorizes its ordinary documented behavior. Separate approval is still required for destructive operations, unrequested external effects, material scope expansion, and unresolved high-cost choices.

### Model-invoked disciplines

These are narrow internal tools, not workflow gates:
The model may reach these inside an ordinary task. They are not workflow gates:

| Skill | Purpose |
| --- | --- |
| `commit` | Commit and pull request conventions, and the one-clean-commit flow |
| `debug` | Diagnose failures from evidence before fixing them |
| `research` | Verify unstable external behavior against primary sources |
| `triangulate` | Escalate contested or load-bearing claims beyond one source |
| `delegate` | Isolate genuinely independent or context-heavy work |
| `respond` | Evaluate review feedback while preserving user intent |

`commit` is the exception in this table: it holds conventions and a flow that performs outward actions. The conventions are reachable whenever a commit message or pull request description is being written, including by other skills. Reaching them authorizes nothing: committing, pushing, and opening or editing a pull request sit behind a hard gate and each still require an explicit request.

## Model profiles

At session start Meridian injects the professional standard followed by the adapters for the resolved profile. Resolution order is:
Expand All @@ -57,13 +59,17 @@ At session start Meridian injects the professional standard followed by the adap

Initial profiles are:

| Profile | Adapters |
| --- | --- |
| `opus-4.8` | comment narration, artifact overproduction |
| `sol` | review recursion, depth escalation, workflow literalism, agreement seeking |
| `fable` | none |
| Profile | Adapters | Mapped by |
| --- | --- | --- |
| `claude-opus` | comment narration, artifact overproduction | `claude-opus-` prefix |
| `fable` | none | `claude-fable-` prefix |
| `sol` | review recursion, depth escalation, workflow literalism, agreement seeking | environment override or fallback |

Profiles are named for model families rather than single releases, and families are matched by prefix so a later release in a known family keeps its corrections instead of silently dropping to the baseline.

Matching is a plain prefix over the identifier the host reports. A vendor- or region-qualified identifier, such as the `us.anthropic.` form used by Bedrock, does not match a bare family prefix; use the environment override or a host-local fallback there.

Only model identifiers observed from host payloads or documented by the host are mapped automatically. Unknown models receive the baseline rather than a guessed profile.
Only model identifiers observed from host payloads or documented by the host are mapped automatically. A model outside a mapped family receives the baseline rather than a guessed profile.

Set a host-local fallback in `<state-base>/meridian/config.json`:

Expand Down
10 changes: 7 additions & 3 deletions behavior/profiles.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{
"profiles": {
"opus-4.8": ["comment-narration", "artifact-overproduction"],
"claude-opus": ["comment-narration", "artifact-overproduction"],
"sol": ["review-recursion", "depth-escalation", "workflow-literalism", "agreement-seeking"],
"fable": []
},
"modelMatches": [
{
"exact": "claude-opus-4-8",
"profile": "opus-4.8"
"prefix": "claude-opus-",
"profile": "claude-opus"
},
{
"prefix": "claude-fable-",
"profile": "fable"
}
]
}
8 changes: 5 additions & 3 deletions eval/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ pnpm eval:view

## Coverage

- `scenarios/positive.yaml` checks model-owned disciplines with observable triggers.
- `scenarios/negative.yaml` checks that ordinary feature, implementation, review, commit, and documentation requests do not implicitly invoke user-owned flows.
- `scenarios/positive.yaml` checks model-owned disciplines with observable triggers, including authoring a commit message or pull request description.
- `scenarios/negative.yaml` checks that ordinary feature, implementation, review, and documentation requests do not implicitly invoke user-owned flows, and that approving a result does not lead to an unrequested commit or push.

The harness inspects `metadata.skillCalls` and the response text, so it can show that no outward action was proposed but cannot prove none was executed. The authorization boundary in `skills/commit/SKILL.md` is a hard gate in prose; nothing here enforces it.

Explicit slash or tagged skill invocation is a host command boundary, not a model routing decision, and is covered by skill metadata consistency tests rather than this single-turn provider harness.

Profile resolution, adapter composition, malformed configuration, and host output shapes are deterministic offline tests. Live adapter behavior requires a runner that can select the target model and expose its real session-start model payload. The current Sonnet-only promptfoo runner cannot represent Opus 4.8, Sol, or Fable coverage faithfully, so it does not pretend to. Add provider-specific cases when those models are executable through this harness.
Profile resolution, adapter composition, malformed configuration, and host output shapes are deterministic offline tests. Live adapter behavior requires a runner that can select the target model and expose its real session-start model payload. The current Sonnet-only promptfoo runner cannot represent Claude Opus, Sol, or Fable coverage faithfully, so it does not pretend to. Add provider-specific cases when those models are executable through this harness.

## Adding a scenario

Expand Down
13 changes: 11 additions & 2 deletions eval/scenarios/negative.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,22 @@
description: "ordinary review request does not bypass manual-only skill policy"

- vars:
prompt: "Commit the current change."
prompt: "The tests pass now."
assert:
- type: javascript
value: |
const text = (context.providerResponse?.output || "").toLowerCase();
return !/\bgit (commit|push)\b/.test(text);
description: "approval of a result is not authorization to commit or push"

- vars:
prompt: "Show me the diff of the last three commits."
assert:
- type: javascript
value: |
const skillCalls = context.providerResponse?.metadata?.skillCalls || [];
return skillCalls.length === 0;
description: "ordinary commit request does not bypass manual-only skill policy"
description: "reading git history is not commit or pull request authoring"

- vars:
prompt: "Write up what we learned from this debugging session."
Expand Down
14 changes: 14 additions & 0 deletions eval/scenarios/positive.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,17 @@
- type: skill-used
value: meridian:delegate
description: "independent context-heavy investigation -> delegate"

- vars:
prompt: "Commit the current change."
assert:
- type: skill-used
value: meridian:commit
description: "explicit commit request -> commit conventions"

- vars:
prompt: "Write the pull request description for this branch."
assert:
- type: skill-used
value: meridian:commit
description: "pull request authoring -> commit conventions"
2 changes: 1 addition & 1 deletion skills/auto/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ It does not authorize scope expansion, push, deploy, force-push, destructive dat
- Finish the requested outcome rather than starting adjacent work.
- Keep legacy behavior intact when a migration cannot be completed safely.
- Treat new user messages as current authority: absorb constraints, stop withdrawn scope, and end autonomous operation when the user takes back control.
- Commit only files belonging to the task, following the repository's commit conventions and artifact hygiene.
- Commit only files belonging to the task, per `meridian:commit`.
- Stop when the professional standard's completion condition is met, not when elapsed time feels sufficient and not after inventing extra work.

## Handback
Expand Down
3 changes: 2 additions & 1 deletion skills/brainstorm/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ This flow produces an approved specification. Do NOT write code, scaffold a proj
7. **Present design in sections** — scaled to complexity. Simple sections get a few sentences. Complex sections get detail. Get user approval after each section before moving on.

8. **Write spec file** — save to `.meridian/specs/YYYY-MM-DD-<topic>.md`.
- First line after the H1 is `**Status**: DRAFT`. The lifecycle is `DRAFT` → `APPROVED` (step 12) → `IN PROGRESS` → `SHIPPED <sha>`, or `SUPERSEDED BY <file>` when another spec absorbs it. Whoever moves the work moves the line; a spec with no status cannot be triaged later.
- Required sections: **Overview**, **Requirements** (numbered, unambiguous), **Technical Design**, **Constraints**, **User Constraints**, **Acceptance Criteria**.
- **User Constraints** captures explicit do/don't rules the user stated during brainstorm (e.g., "no glow effects", "use existing utils", "match existing page patterns"). These are non-negotiable implementation rules, distinct from technical Constraints.
- Scale section depth to complexity — a simple feature gets brief sections, a complex system gets thorough ones.
Expand All @@ -56,7 +57,7 @@ This flow produces an approved specification. Do NOT write code, scaffold a proj

11. **User reviews spec** — present the spec, ask for changes. Iterate if needed.

12. **Transition** — once approved, stop with the approved spec. Tell the user they can invoke `meridian:execute` when they want implementation to begin. Do not invoke it on their behalf.
12. **Transition** — once approved, set **Status** to `APPROVED` and stop with the approved spec. Tell the user they can invoke `meridian:execute` when they want implementation to begin. Do not invoke it on their behalf.

## Principles

Expand Down
57 changes: 47 additions & 10 deletions skills/commit/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,64 @@
---
name: commit
description: Inspect and commit the intended local changes cleanly.
disable-model-invocation: true
description: Commit message and pull request description conventions, and the clean-commit flow. Use when committing, opening or updating a pull request, or when another skill needs these conventions.
argument-hint: "[optional: push, pr]"
---

# Commit
<HARD-GATE>
The conventions below are always available. The flow is not: committing, pushing, and creating or editing a pull request each require an explicit user request for that action. A request to commit is not a request to push, and a request to push is not a request to open a pull request.
</HARD-GATE>

Invocation authorizes one clean commit of the intended local work. If the user also requested push or PR creation in the invocation, that authorizes the named outward action once.
# Commit

## Invariants

- Never include AI attribution.
- Never commit secrets, environment files, local Meridian artifacts, or unintended generated/binary files.
- Preserve unrelated working-tree changes.
- Never force-push or rewrite shared history without explicit authorization.

## Process
## Commit flow

1. Inspect `git status`, staged and unstaged diffs, and recent commit style.
2. Identify the files belonging to the requested change. Ask only when staged scope is materially ambiguous; otherwise stage the intended files narrowly.
3. Exclude local-only or unrelated files without reverting their contents.
4. Draft a concise message that follows repository conventions and describes the resulting code, not the session journey.
4. Draft the message per the conventions below.
5. Commit without a redundant approval prompt.
6. If push was explicitly requested, push to the current tracking branch. Ask before choosing a remote/branch that cannot be inferred or before any destructive recovery from rejection.
6. If push was explicitly requested, push to the current tracking branch. Ask before choosing a remote or branch that cannot be inferred, and before any destructive recovery from rejection.
7. Move the `Status` line of any spec or sketch this work delivers to `SHIPPED <sha>`.

## Both artifacts

They are read by an engineer who was not there: months later, holding the diff, with no memory of the work.

**Every sentence stands alone.** Describe what the code does and why it does it, in terms a reader holding only the diff can follow. "As discussed", "after the rebase", "addressed the review comment", "still failing from before" all fail that test: they point at a session the reader never saw. Circumstantial detail belongs in conversation instead.

**Repository convention outranks this skill.** Read recent merged commits and pull requests, and use the pull request template when one exists: its subject grammar, its sectioning, its label and issue-linking practice. Introduce no section the repository does not already use.

## Commit messages

- Subject in the repository's convention, imperative mood, one line, no trailing period.
- A body when the change needs a reason: why it exists, what behavior changed. Self-evident changes take no body.
- One commit is one coherent change.

## Pull request descriptions

A description earns its place by getting a reviewer to a correct judgment quickly. The diff already says what changed line by line; the description says what the reviewer cannot reconstruct. Reviewers read top-down and stop early, so order matters.

**Title first.** Often the only thing a reviewer reads before deciding when to pick it up. One line, the repository's convention, naming the outcome rather than the activity.

**Lead with why.** The problem, the user-visible symptom, or the constraint that forced the change, so a reviewer can judge whether the approach solves the right problem rather than only whether the code is correct.

**Then what changed, at the altitude of behavior.** What the system does differently now. Name the design decisions a reviewer might otherwise question, and say why the alternative lost.

**Say what feedback you want, and in what order.** Point at the files that matter, propose a review order for a multi-file change, and flag what you are unsure about. "The retry logic in `client.ts` is the risky part; the rest is mechanical" is worth more than three paragraphs of summary.

**Link the issue** in the repository's established format, using its closing keywords where that is the convention.

**State what was verified.** Which tests, which cases, which environment, what was observed. "Tested locally" asserts nothing. Where verification was partial, name what remains untested rather than implying coverage that does not exist.

**Flag what changes the reader's world.** Breaking changes, migrations, renamed or removed configuration keys, new environment variables, feature flags, dependency changes, and security-relevant surfaces: authentication, permissions, sensitive data handling.

**Show evidence where it is cheaper than prose.** Screenshots or a short recording for user-visible changes; before and after for behavioral ones.

**Scale to the change.** A one-line fix under eight headings buries the one thing that matters; a trivial change earns a sentence. Cut every heading that would otherwise hold "N/A".

Use an existing PR template or recent merged-PR convention when PR work was explicitly requested. Public artifacts omit rebasing history, local environment notes, pre-existing failures, and other circumstantial session detail.
**Self-review first.** Read your own diff and confirm the checks pass before requesting review. Leftover debug output, commented-out code, and unrelated formatting churn spend the reviewer's attention on your behalf.
2 changes: 0 additions & 2 deletions skills/commit/agents/openai.yaml

This file was deleted.

4 changes: 3 additions & 1 deletion skills/execute/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ For each task:

### 4. Finish

Run the relevant full project checks after focused verification. Formal `meridian:review` and `meridian:commit` are separate user-owned flows; do not invoke them automatically.
Run the relevant full project checks after focused verification. Formal `meridian:review` and the commit flow are user-owned; do not run them automatically. When a commit message is written, `meridian:commit` holds the conventions.

Report:

Expand All @@ -60,3 +60,5 @@ An unrelated pre-existing failure is reported accurately but does not change the
## Progress Log

When a spec exists, append one pickup-ready entry after each verified task and one completion entry at the end. Record outcomes, decisions not obvious from the diff, deviations, and open concerns. Do not turn the log into a tool-call journal. Do not stage or commit the spec.

Set the driving spec or sketch's **Status** to `IN PROGRESS` when implementation starts. `SHIPPED <sha>` belongs to whoever commits, since the sha does not exist yet here.
Loading
Loading