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
39 changes: 31 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### Added

- **Phase 1 — deterministic core.** Plugin scaffold (`.claude-plugin/`), the six
bash scripts that own all deterministic bookkeeping (`check-noop`, `snapshot`,
`write-state`, `diff-summary`, `inventory`, `inject-pointer`), and a Vitest
suite that exercises them against real temporary git repos. `tests/noop.test.ts`
is a case-for-case port of OpenWiki's `test/update-noop.test.ts` (the executable
parity spec). CI runs shellcheck + tests on macOS and Linux.
- **Phase 1 — deterministic core.** Plugin scaffold (`.claude-plugin/`), the
bash scripts that own the deterministic no-op / snapshot / state bookkeeping
(`check-noop`, `snapshot`, `write-state`), and a Vitest suite that exercises
them against real temporary git repos. The executable parity spec is OpenWiki's
own `test/update-noop.test.ts`, run verbatim from the vendored source, plus
`tests/parity-crossvalidate.test.ts` (wijzer's bash vs the real functions). CI
runs shellcheck + tests on macOS and Linux. (Phase 1 also shipped `inventory`,
`inject-pointer`, and `diff-summary`; P2D removed them — see Changed below.)
- `PARITY.md` pinning the validated upstream OpenWiki commit and the mapping table.
- **Phase 2 — init skill.** `/wijzer:init [focus]` (`skills/init/SKILL.md`) that
runs the deterministic inventory, optionally fans out read-only `wiki-scout`
discovers the repository, optionally fans out read-only `wiki-scout`
subagents (`agents/wiki-scout.md`), plans via `openwiki/_plan.md`, writes the
wiki, injects the `AGENTS.md`/`CLAUDE.md` pointer, and records state. The
wiki, adds the `AGENTS.md`/`CLAUDE.md` pointer section, and records state. The
parity contract is captured in `references/wiki-format.md` (page format, source
maps, ≤8-page ceiling) and `references/disciplines.md` (run / subagent /
planning / git / surgical-edit disciplines).
Expand Down Expand Up @@ -53,3 +55,24 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
output rather than its prompt. `references/state-schema.md` stays hand-authored
(it documents wijzer-only serialization facts) but its field set is now locked
to the vendored `UpdateMetadata` type by the same test.

### Changed

- **P2D — prompt-driven skills (parity-first).** Removed the three bash scripts
that had no OpenWiki counterpart and were wijzer value-adds: `inventory.sh`
(repo inventory), `inject-pointer.sh` (marker-block writer), and
`diff-summary.sh` (bespoke JSON diff), plus their tests. Discovery, git
inspection, and the `AGENTS.md`/`CLAUDE.md` pointer are now **prompt-driven**,
matching OpenWiki's own behavior:
- `/wijzer:init` and `/wijzer:update` (`skills/init`, `skills/update`) are thin
wrappers: they follow the generated run/git disciplines directly and call
only the exact-semantics bookkeeping scripts (`check-noop`, `snapshot`,
`write-state`, `check-format`). The update skill reads the baseline from
`openwiki/.last-update.json` and runs the same `git status`/`log <range>`/`diff`
commands and the same `gitHead` → `updatedAt` → recent-history fallback as
OpenWiki's `createGitSummary`.
- The pointer is written by the agent using OpenWiki's **exact `## OpenWiki`
block**, now preserved byte-for-byte in `references/disciplines.md` (fenced
literals are exempt from vocabulary translation and the residual-vocab guard).
This reverses P2C's inject-pointer.sh adaptation.
- `agents/wiki-scout.md` is aligned to the generated subagent discipline.
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ translation, drift-locked by `tests/build-disciplines.test.ts`. Edit the
generator and re-run it, never the generated files. The format side of parity is gated
deterministically too: init/update finish by running `scripts/check-format.sh`
over `openwiki/` and must fix reported problems before recording state. The scripts are unit-tested against real temp
git repos in **`tests/`** (Vitest); `tests/noop.test.ts` is a case-for-case port
of OpenWiki's `test/update-noop.test.ts` — the executable parity spec.
git repos in **`tests/`** (Vitest); the vendored `vendor/openwiki/test/update-noop.test.ts`
runs verbatim and `tests/parity-crossvalidate.test.ts` runs wijzer's bash against
the real OpenWiki functions — the executable parity spec.

Interchangeability with OpenWiki means the wiki dir stays `openwiki/` and the
state file stays `openwiki/.last-update.json` with the exact
Expand Down
6 changes: 3 additions & 3 deletions PARITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ living record of what that means and how it is verified.
| plain-MD pages, no frontmatter, source-map at page end, ≤8 pages on init | `references/wiki-format.md` + `scripts/check-format.sh` gate in init/update | `tests/check-format.test.ts` + golden run vs upstream `openwiki/` |
| `.last-update.json` = {updatedAt, command, gitHead?, model} | `scripts/write-state.sh` | `tests/state.test.ts` (CLI contract) + `tests/parity-crossvalidate.test.ts` (real-function interchange) |
| no-op: (no msg AND HEAD==state) OR only `openwiki/` changed; force when dirty | `scripts/check-noop.sh` (ports `getUpdateNoopStatus` + `shouldCheckUpdateNoop`) | `tests/parity-crossvalidate.test.ts` runs bash vs the vendored real functions; `vendor/openwiki/test/update-noop.test.ts` runs verbatim against the vendored source |
| surgical edits: ≤1–2 pages when <5 files changed | `references/disciplines.md` + `scripts/diff-summary.sh` | Phase-3 scenario |
| git evidence (`git status`/`log <range>`/`diff`) → surgical edits: ≤1–2 pages when <5 files changed | `references/disciplines.md` (git discipline) — **prompt-driven**: the update skill runs the same commands and the same `gitHead` → `updatedAt` → recent-history fallback as OpenWiki's `createGitSummary`, reading the baseline from `openwiki/.last-update.json` | Phase-3 scenario |
| SHA-256 snapshot; write state only if content changed | `scripts/snapshot.sh` (`dir:`/`file:` frames match real byte-for-byte) + update-skill gate | `tests/snapshot.test.ts` (envelope) + `tests/parity-crossvalidate.test.ts` (digest equals real) |
| init: inventory → `_plan.md` → generate → delete plan → state | `scripts/inventory.sh` + init skill | golden run |
| init: discover → `_plan.md` → generate → delete plan → state | **prompt-driven** discovery (run discipline) + init skill; no bash inventory step (OpenWiki has none) | golden run |
| run/subagent/planning/git disciplines (`src/agent/prompt.ts`) | `references/disciplines.md` + `references/wiki-format.md` (both **generated** from the vendored `prompt.ts` by `scripts/build-disciplines.mjs`) + `agents/wiki-scout.md` | `tests/build-disciplines.test.ts` — drift-locked: the committed docs must equal a fresh regenerate, so an upstream prompt change fails CI until re-derived |
| idempotent AGENTS.md/CLAUDE.md block | `scripts/inject-pointer.sh` | `tests/inject.test.ts` |
| exact `## OpenWiki` block in AGENTS.md/CLAUDE.md | **prompt-driven**: the agent writes OpenWiki's verbatim `## OpenWiki` section (preserved byte-for-byte in `references/disciplines.md`) — no bash injector | `tests/build-disciplines.test.ts` (block derived verbatim) |
| GH Action: cron 8am → update → PR `openwiki/update` | `examples/github-action.yml` (via anthropics/claude-code-action, subscription OAuth) | Phase-4 live run |

## Watch items
Expand Down
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ with a subscription OAuth token (`claude setup-token`) — no API key in CI eith

wijzer splits deterministic bookkeeping from model judgment:

- **`scripts/`** — dependency-free bash (git + coreutils) that computes the
update no-op verdict, the content snapshot, the diff summary, the repo
inventory, the state file, and the pointer injection. Each emits one JSON
object; each is unit-tested against real temp git repos (`npm test`).
- **`skills/` + `agents/`** — the model does discovery, page planning, and
writing, consuming the scripts' JSON and obeying the disciplines in
`references/`.
- **`scripts/`** — dependency-free bash (git + coreutils) that owns the
exact-semantics bookkeeping: the update no-op verdict (`check-noop`), the
content snapshot (`snapshot`), the state file (`write-state`), and the output
format gate (`check-format`). Each emits one JSON object; each is unit-tested
against real temp git repos (`npm test`).
- **`skills/` + `agents/`** — the model does discovery, git inspection, page
planning, writing, and the `AGENTS.md`/`CLAUDE.md` pointer **prompt-driven**,
obeying the disciplines in `references/` (generated from OpenWiki's own prompt)
and calling the scripts above for the bookkeeping.

See [PARITY.md](PARITY.md) for exactly what matches OpenWiki and how it's
verified, and [`CONTRIBUTING`](#contributing) below to hack on it.
Expand Down
7 changes: 7 additions & 0 deletions agents/wiki-scout.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ brief**. Your entire job is to inspect that slice of the repo and report back.
You do not write documentation and you do not decide the wiki's structure — the
main agent synthesizes every page.

You are the concrete form of the **subagent discipline** in
`references/disciplines.md` (derived from OpenWiki's prompt): parallelize
read-only research over a narrow brief — existing docs, runtime architecture,
data/storage, UI/API surface, integrations, tests/evals, or business workflows —
inspect and summarize only, and return concise findings with source paths and
open questions for the main agent to synthesize.

## Absolute constraints

- **Read-only. Never mutate anything.** Do not create, edit, move, or delete
Expand Down
48 changes: 27 additions & 21 deletions references/disciplines.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,27 @@ Use only the tools available to you. Prefer built-in discovery tools such as `Gl

## Root agent instruction files

*Distribution-method adaptation: OpenWiki has the agent hand-write this
pointer block; wijzer writes it deterministically with
[`scripts/inject-pointer.sh`](../scripts/inject-pointer.sh). The parity intent —
a top-level, idempotent pointer into the wiki — is preserved; the exact
`## OpenWiki` block OpenWiki embeds here is replaced by the script's
marker-delimited block.*

- Point coding agents at the wiki from the repository's **top-level**
`AGENTS.md` / `CLAUDE.md` — never nested `AGENTS.md`/`CLAUDE.md` files.
- Do not hand-write the block. Run `scripts/inject-pointer.sh`, which creates
or updates a marker-delimited block idempotently (safe to re-run) and
preserves the surrounding content.
- On update runs, re-run `scripts/inject-pointer.sh` so a repository that
gained an `AGENTS.md`/`CLAUDE.md` since init picks up the block; it no-ops
when the block is already present.
- Do not make formatting-only edits to these files.
- Unless the user explicitly asks you not to, always make sure the repository's top-level agent instruction files reference the OpenWiki quickstart.
- Only consider top-level AGENTS.md and CLAUDE.md for this step. Do not edit nested AGENTS.md or CLAUDE.md files.
- If AGENTS.md or CLAUDE.md exists, add or update the OpenWiki reference section there. If both exist, ensure the same section is added to both (duplicated).
- If neither exists, create top-level AGENTS.md containing only the OpenWiki reference section.
- During update runs, inspect any existing OpenWiki reference section in AGENTS.md and/or CLAUDE.md and refresh it only if the section is missing or semantically stale. This check is required even when the wiki itself is otherwise current.
- Preserve surrounding instructions in existing files. Replace/update an existing OpenWiki reference section instead of adding duplicates.
- Do not edit AGENTS.md or CLAUDE.md only to normalize formatting, blank lines, wrapping, or punctuation if the existing OpenWiki section is already semantically correct.
- Use this exact section structure every time:

```markdown
## OpenWiki

This repository has documentation located in the /openwiki directory.

Start here:
- [OpenWiki quickstart](openwiki/quickstart.md)

OpenWiki includes repository overview, architecture notes, workflows, domain concepts, operations, integrations, testing guidance, and source maps.

When working in this repository, read the OpenWiki quickstart first, then follow its links to the relevant architecture, workflow, domain, operation, and testing notes.
```

## Security and privacy rules

Expand Down Expand Up @@ -164,12 +169,13 @@ filesystem to Claude Code's real tools:
- Leading-slash openwiki path.
- matches `\/openwiki`

Two sections need more than a vocabulary swap:
Two more rules beyond the vocabulary swap:

- `OpenWiki CLI reference:` is **dropped** — its subject, the `openwiki` CLI flag
surface, is out of wijzer's parity scope, since wijzer's runtime is Claude Code
skills (`/wijzer:init`, `:update`, `:ask`), not a CLI.
- `Root agent instruction files:` is **adapted** — OpenWiki has the agent
hand-write an `## OpenWiki` pointer block; wijzer writes a marker-delimited
block deterministically with `scripts/inject-pointer.sh`, so the parity-relevant
rules are kept but the write mechanism and embedded block are replaced.
- Fenced ```code blocks are **preserved verbatim** — not translated and not
residual-vocab-checked. The `## OpenWiki` pointer block under "Root agent
instruction files" is the exact literal the agent must reproduce byte-for-byte
into a repository's AGENTS.md/CLAUDE.md, so it keeps OpenWiki's own `/openwiki`
path for an interchangeable wiki.
10 changes: 5 additions & 5 deletions references/state-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ or change the field set.

Deterministic ownership: the file is written only by
[`scripts/write-state.sh`](../scripts/write-state.sh) and read (for `gitHead`) by
[`scripts/check-noop.sh`](../scripts/check-noop.sh) and
[`scripts/diff-summary.sh`](../scripts/diff-summary.sh). Skills never hand-write
it — they call `write-state.sh`.
[`scripts/check-noop.sh`](../scripts/check-noop.sh), which surfaces the prior
`stateGitHead` the update skill uses to scope its prompt-driven git inspection.
Skills never hand-write it — they call `write-state.sh`.

## Location

Expand Down Expand Up @@ -86,8 +86,8 @@ Example (non-git directory — `gitHead` absent, model fell back):

## Reading it back

`check-noop.sh` and `diff-summary.sh` extract `gitHead` with a tolerant `sed`
(`"gitHead"\s*:\s*"…"`) rather than a JSON parser, so they read files written by
`check-noop.sh` extracts `gitHead` with a tolerant `sed`
(`"gitHead"\s*:\s*"…"`) rather than a JSON parser, so it reads files written by
either tool regardless of whitespace or key order. A file with no `gitHead`
yields the `"missing previous update git head"` verdict (`checkNoop: true`,
`noop: false`) — i.e. wijzer treats a stateless or non-git wiki as always worth a
Expand Down
11 changes: 6 additions & 5 deletions references/wiki-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,13 @@ filesystem to Claude Code's real tools:
- Leading-slash openwiki path.
- matches `\/openwiki`

Two sections need more than a vocabulary swap:
Two more rules beyond the vocabulary swap:

- `OpenWiki CLI reference:` is **dropped** — its subject, the `openwiki` CLI flag
surface, is out of wijzer's parity scope, since wijzer's runtime is Claude Code
skills (`/wijzer:init`, `:update`, `:ask`), not a CLI.
- `Root agent instruction files:` is **adapted** — OpenWiki has the agent
hand-write an `## OpenWiki` pointer block; wijzer writes a marker-delimited
block deterministically with `scripts/inject-pointer.sh`, so the parity-relevant
rules are kept but the write mechanism and embedded block are replaced.
- Fenced ```code blocks are **preserved verbatim** — not translated and not
residual-vocab-checked. The `## OpenWiki` pointer block under "Root agent
instruction files" is the exact literal the agent must reproduce byte-for-byte
into a repository's AGENTS.md/CLAUDE.md, so it keeps OpenWiki's own `/openwiki`
path for an interchangeable wiki.
Loading
Loading