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
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "spectre-marketplace",
"metadata": {
"version": "1.2.1",
"version": "1.3.0",
"description": "Spectre — deterministic spec-driven Claude Code plugin (vision → spec → evaluate → lock → implement → verify)."
},
"owner": {
Expand All @@ -11,7 +11,7 @@
{
"name": "spectre",
"description": "Three-tier pre-lock spec evaluator + persistence-tier classifier. /vision, /implement, and /implement auto skills with action/verification gates and auto-routed Spectre-finding capture.",
"version": "1.2.1",
"version": "1.3.0",
"source": "./"
}
]
Expand Down
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,52 @@

All notable changes to the Spectre plugin.

## v1.3.0 — 2026-05-16

Minor release. Three coverage and prototype items addressing the gaps surfaced across two Vidence dogfood cycles plus a walker plumbing follow-up surfaced by the Wave 3 Opus aggregate review. No spec contract changes — v1.0/v1.1/v1.1.1/v1.2.0/v1.2.1 locked specs continue to validate.

**Test count:** 1967 (v1.2.1) → 2003 (v1.3.0). +36 new tests, 0 regressions.

### Added — exemplar catalog seeded for input-shape, output-shape, ipc-rpc (item 8, #86)

- Six new exemplars under `docs/exemplars/`, two per view type:
- **input-shape:** `cli-argparse-shape.md` (POSIX §12 + GNU Coding Standards), `openapi-request-body.md` (OpenAPI 3.1 Request Body Object).
- **output-shape:** `json-rpc-response-2.0.md` (json-rpc.org 2.0 spec), `openapi-response-envelope.md` (OpenAPI 3.1 Response Object).
- **ipc-rpc:** `unix-socket-rpc.md` (POSIX bind(2), AF_UNIX SOCK_STREAM), `subprocess-rpc.md` (POSIX waitpid(2), stdin/stdout lifecycle).
- Every convention in each exemplar traces to the cited `source-url`. No invented conventions.
- Three new `axes.yml` files (input-shape, output-shape, ipc-rpc).
- `bin/cross_view_gate.py::_VIEW_TO_CATALOG_TYPES` rerouted: §9 → `{input-shape}` (was placeholder `{help-text}`), §10 → `{output-shape}`, §12 → `{api-shape, ipc-rpc}`. Specs that previously deferred §9/§10 with the `no-compatible-exemplar` reason will now find compatible exemplars and tag deferrals as `operator-deferral` instead — the `excessive-post-ship-iteration` aggregate warn will fire for two-or-more deferrals as designed.
- `bin/walker.py::_VIEW_TO_CATALOG_VIEW_TYPE` aligned: `product-input` → `input-shape`, `product-output` → `output-shape`. The walker's exemplar-suggestion path and the cross-view gate's validation path now query the same catalog. (Pre-fixup, the walker still recommended help-text exemplars for input-shape views.) The `input-exemplar-pi` concern prompt updated to reference `input-shape` instead of the v1.1 placeholder language.

### Added — vocabulary partition fail-soft UX with block-severity firewall (item 9, #85)

- `bin/substrate_wizard.py::_validate_view_trust_profile` contract changed from `raise WizardValidationError` to `return (profile, findings)`. Misplaced tokens (e.g. `untrusted-input` placed in §8.3 instead of §8.2) are **dropped from the returned profile** — the semantic firewall — and each emits one `block`-severity `trust-token-misplaced` finding whose `suggested_fix` names the correct destination view.
- The lock still cannot complete while a misplaced-token finding exists; the partition's semantic guarantee holds. What changes is operator ergonomics: a structured, actionable finding replaces an opaque `ValueError`, the walker re-prompts inline with the right-section hint, and operators don't re-read docs to fix it.
- New finding kind registered in `bin/findings.py::KNOWN_KINDS`. Glossary entry added to `docs/glossary.md`.
- 7 new tests in `tests/test_substrate_wizard_partition_fail_soft.py` covering the tuple shape, the dropped-token invariant, the multi-token case, and the suggested-fix content.

### Added — Layer 5 self-interrogation prototype (item 10, #87)

- New module `bin/_layer5.py` containing `build_trace_record(...)` and `project_substitution_trace(...)` helpers. `SPECTRE_LAYER5=off` env var disables emission for token-cost A/B comparison.
- `bin/walker.py` emits machine-parseable reasoning-trace records at two commit sites: walker concern-resolution (`record_answer`) and exemplar-binding (within `record_answer` when the answered concern is one of the six known exemplar-binding IDs). Skip when `len(prefab_options) <= 1` (no real choice). New `WalkState.layer5_trace: list[dict]` field; `persist` and `load` round-trip it.
- `bin/eval_metadata.py::write_sidecar` accepts an optional `layer5_trace` kwarg and writes it under a new top-level `layer5_trace: list[dict]` key. `bin/spec_evaluator.py` threads the walker's trace records through to the sidecar.
- Six-field schema per record (plus timestamp): `choice_point`, `step_or_concern_id`, `options_considered`, `selected`, `rationale`, `validation_anchor`, `source_anchor`. Two glossary entries added (`term:layer5-trace`, `term:layer5-choice-point`).
- 20 new tests across `tests/test_layer5_walker_trace.py`, `tests/test_layer5_substitution_trace.py`, `tests/test_layer5_exemplar_trace.py`.

### Surface bumps

- `.claude-plugin/marketplace.json` 1.2.1 → 1.3.0 (both `metadata.version` and `plugins[0].version`)
- README test-count badge: 1967 → 2003
- README version badge: 1.2.1 → 1.3.0
- `findings.Finding` `KNOWN_KINDS` gains `trust-token-misplaced`
- `substrate_wizard._validate_view_trust_profile` returns `(list[str], list[Finding])` instead of raising
- `eval_metadata.write_sidecar` gains optional `layer5_trace: list[dict] | None` kwarg
- `walker.WalkState` gains `layer5_trace: list[dict]` field

### Known follow-ups

- The Layer 5 prototype lacks an explicit `walker.persist → walker.load` roundtrip test for `WalkState.layer5_trace`. The four-site wiring is correct by inspection and 20 tests cover the emission paths, but a focused state-roundtrip test will land as a small follow-up (v1.3.1 or earlier).

## v1.2.1 — 2026-05-15

Defect-pack hotfix. Seven fixes addressing Tier-1 regex false-positives, walker stop-signal inconsistency, post-ship-iteration false-positive on zero-exemplar views, missing substitution evidence in the eval sidecar, and missing operator-mode flag on lock state. No spec contract changes — v1.0/v1.1/v1.1.1/v1.2.0 locked specs remain valid.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

> Spectre — a deterministic spec-driven Claude Code plugin. Vision → Spec → Evaluate → Lock → Implement → Verify, with three-tier pre-lock review and per-project resource locking.

[![tests](https://img.shields.io/badge/tests-1967%20passing-brightgreen)](#tests) [![python](https://img.shields.io/badge/python-3.11%2B-blue)](#install) [![stdlib only](https://img.shields.io/badge/deps-stdlib%20only-blue)](#install) [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![version](https://img.shields.io/badge/version-1.2.1-blue)](CHANGELOG.md)
[![tests](https://img.shields.io/badge/tests-2003%20passing-brightgreen)](#tests) [![python](https://img.shields.io/badge/python-3.11%2B-blue)](#install) [![stdlib only](https://img.shields.io/badge/deps-stdlib%20only-blue)](#install) [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![version](https://img.shields.io/badge/version-1.3.0-blue)](CHANGELOG.md)

## Table of Contents

Expand Down Expand Up @@ -116,7 +116,7 @@ Full vocabulary registry: [`docs/glossary.md`](docs/glossary.md) (75+ status cod

Full reference — hooks, skills, spec step schema, sidecar format, layout, finding-kind taxonomy: [`docs/API.md`](docs/API.md).

**v1.2 components** — plugin `1.2.1` ([`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json)), `EVALUATOR_VERSION = "1.0.0"` ([`bin/spec_evaluator.py`](bin/spec_evaluator.py)), `WALKER_VERSION = "1.0.0"` ([`bin/walker.py`](bin/walker.py)). Walker state files persisted under v0.9 are rejected on load; remove `state/.walk.json` and re-run `/vision` to migrate (hard cutover from v0.9; no migration tool).
**v1.3 components** — plugin `1.3.0` ([`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json)), `EVALUATOR_VERSION = "1.0.0"` ([`bin/spec_evaluator.py`](bin/spec_evaluator.py)), `WALKER_VERSION = "1.0.0"` ([`bin/walker.py`](bin/walker.py)). Walker state files persisted under v0.9 are rejected on load; remove `state/.walk.json` and re-run `/vision` to migrate (hard cutover from v0.9; no migration tool).

**`spectre` CLI surface** — top-level wrapper resolves `${CLAUDE_PLUGIN_ROOT}`, exports `PYTHONPATH`, dispatches to `python3 -m bin.<subcommand>`:

Expand All @@ -133,7 +133,7 @@ Full reference — hooks, skills, spec step schema, sidecar format, layout, find
## Tests

```bash
pytest tests/ # 1967 tests, stdlib + pytest
pytest tests/ # 2003 tests, stdlib + pytest
pytest tests/ -v # verbose
pytest tests/test_spec_evaluator.py -v # single module
```
Expand Down
10 changes: 5 additions & 5 deletions bin/walker.py
Original file line number Diff line number Diff line change
Expand Up @@ -940,10 +940,10 @@ def generate_semantic_criteria_concern(
# error-text), this map lists them in priority order; each concern that needs
# exemplar options passes the specific view-type it's filtering against.
_VIEW_TO_CATALOG_VIEW_TYPE: dict[str, str] = {
"product-input": "help-text", # placeholder; input-shape lands in v1.1
"product-output": "help-text", # placeholder; output-shape lands in v1.1
"product-input": "input-shape",
"product-output": "output-shape",
"human-user": "help-text", # error-text handled separately per concern
"integrator": "api-shape",
"integrator": "api-shape", # ipc-rpc handled by cross_view_gate too
"operator": "log-format", # observability handled separately per concern
}

Expand Down Expand Up @@ -1040,12 +1040,12 @@ def generate_product_input_concerns(
))
if _view_in_scope(state, "product-input"):
pi_fingerprint = state.answered.get("scope-product-input")
pi_options, _ = _exemplar_options_for(pi_fingerprint, "help-text")
pi_options, _ = _exemplar_options_for(pi_fingerprint, "input-shape")
for cid, summary, opts in (
("input-source-pi", "Input source — stdin, file path, network protocol, env var? Name the wire format.", []),
("input-schema-pi", "Input validation schema — JSON Schema URL or inline, or 'none' if input is opaque bytes. Include the strictness level (strict | lenient | tolerant).", []),
("input-retry-pi", "Retry budget — how many retries on malformed input before the product rejects? '0' (fail fast) | '<int>' | 'unlimited'.", []),
("input-exemplar-pi", "Exemplar binding — pick a catalog entry whose input-handling conventions match your product (run `spectre exemplars list --view-type help-text` for now; an input-shape view will surface in v1.1) or 'none' to skip exemplar-binding for this view.", pi_options),
("input-exemplar-pi", "Exemplar binding — pick a catalog entry whose input-handling conventions match your product (run `spectre exemplars list --view-type input-shape`) or 'none' to skip exemplar-binding for this view.", pi_options),
):
if cid not in existing:
new.append(Concern(
Expand Down
Loading