Skip to content

docs: make the project directory the unit, and MCP a read-only window - #5

Merged
protonspy merged 3 commits into
mainfrom
docs/project-directory-as-the-unit
Aug 1, 2026
Merged

docs: make the project directory the unit, and MCP a read-only window#5
protonspy merged 3 commits into
mainfrom
docs/project-directory-as-the-unit

Conversation

@protonspy

@protonspy protonspy commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Three decision records, and the plan they rewrite. Documentation only — there is no source in this repo yet.

What changed

adr:0013-the-project-directory-is-the-unit — the pivot. A project is a directory, opened by ow in its scope the way code . works; there is no workspace container. The harness reads the wiki off the filesystem it already has open, so MCP keeps one job: consulting another project, read-only, over stdio, spawned by the harness. No port, no token, whole pages rather than passages, and no embeddings.

It supersedes adr:0003 — four of that record's seven operative clauses are void (HTTP on the loopback started by the app, MCP exposing ingest and write, the project chosen by the application, the mandatory token); three survive and are its substance (the app calls no LLM, the agent writes, write-time validation replaces the writer). It narrows adr:0002, which loses the container and keeps everything else.

adr:0014-typescript-everywhere-except-audio-capture — Rust keeps the recorder and nothing else; the CLI is the product's spine and ships to npm as well as in the installer. Supersedes adr:0010 by applying its own reasoning: that record explicitly disclaimed its performance argument, and what remained is agnostic of language.

adr:0015-the-convention-ships-as-skillsow init scaffolds the wiki and codewiki conventions into .claude/skills/, never overwriting. Settles the question the plan had left open since the beginning, and states the ageing that scaffolding into a project reintroduces.

plans/open-wiki.md was rewritten around all three — group 9 went from an HTTP server with a token to a CLI plus a read-only stdio server, and groups 2, 8 and 10 followed. Glossary, stack, claude-code-plugins and the wiki index were brought in line.

How it was verified

npx @protonspy/scc validateexit 0, no findings.

No tests or lint were run: apps/ and packages/ do not exist yet (task 1.1 is unstarted), so there is no suite and nothing to lint. The change touches only markdown.

A code-review and a security-review pass ran on the diff before this PR, and both found substantive things. The most important:

  • A load-bearing claim was wrong. The first draft said a PreToolUse hook cannot see the content it is about to allow, which made the write gate look unrebuildable and drove ADR 0013's central consequence. It receives the complete tool_inputcontent for Write, the strings for Edit — and can answer permissionDecision: deny with a reason. Refusal survives intact for the file tools. What does not survive is coverage: a write made through Bash carries a command string, and deny Edit(wiki/**) does not constrain Bash, because permission rules are per tool. Four documents were corrected and task 9.5 now has to answer for the shell.
  • The gate's own configuration sits inside the boundary it gates. .claude/, .mcp.json and CLAUDE.md are executable configuration living in the project directory. A write path reaching them edits away its own restraint, through a change that reads as documentation in review. Now stated in 0013 and enforced by new task 9.6.
  • The raw/-in-git question was analysed on cost, not on disclosure. It weighed 11 MB against a link resolving, and never against the fact that committing recorded meeting audio puts it in every clone and fork permanently — dissolving the promise stack.md makes for whisper.cpp. .state/ is worse: it holds every page as it was before each write, so a redaction survives there. The open question now names both, and the default is deny (new task 2.8).
  • Also fixed: a cold-start socket that would have handed back the unauthenticated local listener the pivot just removed (now read-and-validate only); "no claim to forge" overstated the confinement win; registry name resolution had no confinement story (2.2 became TDD); ADR 0007's schema is now marked historical; ADR 0008's workspace-wide language clause becomes per-project; the plugin can no longer ship the skills, which would be a second copy of the convention.

Decisions left open, deliberately

Written as open questions inside the records, in the house style of adr:0010:

  1. The write gate's composition — hook, CLI verb, and what covers the shell. Task 9.5 says it cannot ship open.
  2. What of raw/ and .state/ enters git, on the disclosure axis rather than the size one.
  3. How a scaffolded skill learns it is old (adr:0015).

One thing this PR does not fix

.claude/ and CLAUDE.md are in .gitignore, so the methodology and the scc manifest exist only on the author's machine — scc validate cannot run in a worktree, in CI, or for anyone who clones. It is already task 1.4 and it blocked verification here until the files were copied in by hand. Worth doing before the next PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01C9Vv5jJqcGxrStXhLwbf9b

Summary by CodeRabbit

  • Documentation

    • Added architecture decisions covering project-directory scope, TypeScript adoption, and project-local skills.
    • Updated terminology, technology stack, plugin guidance, distribution, and roadmap documentation.
    • Clarified read-only project consultation, write validation, configuration, and security rules.
    • Added changelog coverage for plugin permissions and hook behavior.
    • Marked superseded architecture decisions accordingly.
  • Chores

    • Excluded local Claude configuration files from version control.

protonspy and others added 2 commits August 1, 2026 00:19
Three decision records, and the plan they rewrite.

0013 replaces the workspace container with a plain project directory
opened by `ow` in its scope, moves wiki reads onto the filesystem the
harness already has open, and leaves MCP one job: consulting another
project, read-only, over stdio, with no port and no token. It supersedes
0003 — four of that record's seven operative clauses are void — and
narrows 0002, which keeps everything but the container.

0014 puts everything except audio capture in TypeScript and makes the CLI
the product's spine, resolving 0010 by applying its own reasoning: that
record disclaimed its performance argument, and what remains of it is
agnostic of language.

0015 settles where the page convention lives — skills scaffolded by
`ow init`, not a generated CLAUDE.md — and states the ageing that
scaffolding reintroduces.

Reviewed before opening: a first draft claimed a PreToolUse hook cannot
see the content it is about to allow, which made the write gate look
unrebuildable. It receives the complete tool_input and can deny with a
reason, so refusal survives for the file tools; what does not survive is
coverage of writes made through the shell. Four documents were corrected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C9Vv5jJqcGxrStXhLwbf9b
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR establishes project directories as the application scope, adopts TypeScript and Node except for audio capture, defines scaffolded skills, and updates ADRs, plans, glossary, stack, and Claude Code plugin documentation.

Changes

Project architecture and convention

Layer / File(s) Summary
Architecture decisions and terminology
docs/adr/*, docs/glossary.md, .gitignore
Adds ADRs for project scope, TypeScript ownership, and skill scaffolding. Marks earlier ADRs as superseded. Ignores project-local Claude files.
Project-scoped roadmap
plans/open-wiki.md
Reframes the roadmap around project directories, agent-owned writes, validation gates, read-only stdio MCP, project registration, integrity checks, and npm distribution.
Reference documentation alignment
docs/glossary.md, docs/stack.md, docs/adr/0009-distribution-through-github-releases.md
Updates project terminology, technology ownership, repository boundaries, MCP behavior, testing scope, release manifests, and distribution channels.
Claude Code plugin documentation
docs/wiki/*
Documents plugin installation, skill scaffolding, hook-based write gating, unsupported capabilities, local project requirements, changelog findings, and read-only stdio MCP behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary documentation changes: making the project directory the unit and limiting MCP to read-only access.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/project-directory-as-the-unit

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🧹 Nitpick comments (1)
docs/wiki/claude-code-plugins.md (1)

168-173: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Pin the Claude Code hook contract used by task 9.5.

The write gate depends on the exact PreToolUse input and denial response. v2.1.x is a moving range. Record the minimum supported version and fallback behavior, or verify this contract in CI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/wiki/claude-code-plugins.md` around lines 168 - 173, Update the task 9.5
Claude Code hook documentation to pin the minimum supported version instead of
relying on the moving v2.1.x range, and document the fallback behavior when the
required PreToolUse contract is unavailable. Alternatively, add CI verification
for the complete tool_input and permissionDecision: deny behavior described in
the write gate section.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.gitignore:
- Around line 144-146: Remove the .claude/ and CLAUDE.md entries from the ignore
rules so project-scaffolded skills and shared conventions are committed and
available to every clone. Do not add a CI or release prerequisite unless task
1.4 is explicitly being implemented in this change.

In `@docs/adr/0013-the-project-directory-is-the-unit.md`:
- Around line 109-111: Update the credential claim in the ADR text near “the
application holds exactly one secret again” to say the application holds at most
one secret, and qualify that the transcription credential is held only when a
remote transcription provider is selected; preserve the reference to ADR 0003
and adr:0007.
- Around line 48-50: Specify the code fence language for the ow mcp command by
changing the unlabeled fence to a console or text fence, preserving the command
content.

In `@docs/adr/0015-the-convention-ships-as-skills.md`:
- Around line 55-68: Update the ADR roadmap to include a skill upgrade path
addressing version drift: add a generated-skill version marker, have ow init
detect and report stale skills without overwriting user edits, and provide a
user-controlled upgrade mechanism such as a reviewable diff or
confirmation-based update.

In `@docs/glossary.md`:
- Line 33: Update the glossary blockquote near the reported location to keep it
continuous: remove the blank line or prefix it with `>` so markdownlint rule
MD028 passes.
- Around line 34-39: Update the final sentence of the glossary entry for
workspace to prohibit the term only when referring to project scope or the
former user-facing domain concept. Explicitly allow established technical
repository terminology such as “pnpm workspace” and “pnpm workspaces,” while
preserving the historical ADR exception.
- Line 16: Update the recording layout in plans/open-wiki.md to include
timemap.json, matching the path defined in docs/glossary.md and referenced by
tasks 4.3, 4.7, and 4.11; keep the naming consistent across all documentation.

In `@docs/stack.md`:
- Around line 21-22: Update the Groq whisper-large-v3-turbo description to cite
a dated source for the approximately US$0.04-per-hour cost and 228x real-time
benchmark, including the benchmark context; if no suitable source is available,
remove the numerical claims and retain only the qualitative rationale.

In `@docs/wiki/claude-code-plugins.md`:
- Around line 3-6: Revise the introduction and component table in the Claude
Code plugins documentation so they do not claim this product’s plugin includes
or carries the written convention/skills. Reflect ADR 0015 and task 10.6: the
plugin should describe only its supported generic capabilities and actual
contents, while `ow init` scaffolds the product skills into the project.

In `@plans/open-wiki.md`:
- Line 86: Update the `.state/` entry in the documentation to describe it as
recovery history containing snapshots of prior pages that may retain prior or
unredacted content, rather than classifying it as non-content. Preserve the
explicit requirement that `.state/` is ignored by default.
- Around line 74-90: Update the fenced directory-layout block in the plan so its
opening fence declares the text language, resolving markdownlint MD040 while
preserving the layout content unchanged.
- Line 197: Revise task 9.1 so the project access functionality is split into a
read-only core containing read, search, and validate, and a separate
write-capable module containing write. Ensure the MCP process imports only the
read-only core, while the application and CLI may use the write-capable module.
- Line 209: Update task 9.13 in plans/open-wiki.md to explicitly require a
restrictive named-pipe ACL where supported and rejection of unauthenticated
local listeners, while preserving the existing local-socket read/validate-only
and standalone-equivalence requirements.
- Line 104: Update the project-directory workflow described in item 2.1 so
existing project directories are accepted in open mode, with validation of the
expected project layout. Restrict refusal of occupied directories to create
mode, while preserving scaffolding of raw/, wiki/, and .state/ when creating a
new project.

---

Nitpick comments:
In `@docs/wiki/claude-code-plugins.md`:
- Around line 168-173: Update the task 9.5 Claude Code hook documentation to pin
the minimum supported version instead of relying on the moving v2.1.x range, and
document the fallback behavior when the required PreToolUse contract is
unavailable. Alternatively, add CI verification for the complete tool_input and
permissionDecision: deny behavior described in the write gate section.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f679b204-2070-4a65-ac4f-898048cbd838

📥 Commits

Reviewing files that changed from the base of the PR and between 299e5cd and f70e36b.

📒 Files selected for processing (12)
  • .gitignore
  • docs/adr/0003-mcp-as-the-only-bridge-to-the-llm.md
  • docs/adr/0010-a-derived-index-engine-behind-a-cli.md
  • docs/adr/0013-the-project-directory-is-the-unit.md
  • docs/adr/0014-typescript-everywhere-except-audio-capture.md
  • docs/adr/0015-the-convention-ships-as-skills.md
  • docs/glossary.md
  • docs/stack.md
  • docs/wiki/changelog.md
  • docs/wiki/claude-code-plugins.md
  • docs/wiki/index.md
  • plans/open-wiki.md

Comment thread .gitignore
Comment on lines +144 to +146

.claude/
CLAUDE.md No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not ignore the project convention if it must be shared.

These entries exclude .claude/skills/ and CLAUDE.md, but the documented model says project-scaffolded skills reach everyone who clones the project. Until task 1.4 runs, this repository cannot provide reproducible convention or scc validation. Remove these rules in this change, or make task 1.4 a release prerequisite with a CI check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.gitignore around lines 144 - 146, Remove the .claude/ and CLAUDE.md entries
from the ignore rules so project-scaffolded skills and shared conventions are
committed and available to every clone. Do not add a CI or release prerequisite
unless task 1.4 is explicitly being implemented in this change.

Comment on lines +48 to +50
```
ow mcp --project fenix --read-only
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Specify the code fence language.

markdownlint reports MD040 for Line 48. Use console or text.

Proposed fix
-```
+```console
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
ow mcp --project fenix --read-only
```
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 48-48: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0013-the-project-directory-is-the-unit.md` around lines 48 - 50,
Specify the code fence language for the ow mcp command by changing the unlabeled
fence to a console or text fence, preserving the command content.

Source: Linters/SAST tools

Comment on lines +109 to +111
Because the token is gone, the application holds **exactly one secret again**, the
transcription credential. That is what 0003 claimed and what
`adr:0007-plaintext-credentials-in-the-config` had to walk back to two.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Use “at most one secret” for the credential claim.

The plan and docs/stack.md allow local whisper.cpp, which requires no credential. State that the transcription credential is the only secret the application may hold when a remote provider is selected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0013-the-project-directory-is-the-unit.md` around lines 109 - 111,
Update the credential claim in the ADR text near “the application holds exactly
one secret again” to say the application holds at most one secret, and qualify
that the transcription credential is held only when a remote transcription
provider is selected; preserve the reference to ADR 0003 and adr:0007.

Comment on lines +55 to +68
**Generating into the project reintroduces the ageing the skill was supposed to avoid.**
The plan's argument against the generated `CLAUDE.md` was that it is "a copy per folder that
ages from the moment it is written", and a skill written by `ow init` is a copy per folder
that ages from the moment it is written. Refusing to overwrite is right — the user edits
these files and losing that is worse — but it means a project scaffolded at v0.3 keeps a v0.3
convention forever, silently, while the validators enforce v0.7.

## The question this record does not answer

**How a scaffolded skill learns it is old.** A version marker in the generated file plus an
`ow init` that reports staleness instead of overwriting is the obvious shape, and there are
others: a skill thin enough to be a pointer at a CLI command that carries the authoritative
text, or an upgrade path that diffs and asks. Nothing here chooses, and until something
does, the ageing above is unmitigated rather than accepted.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Add a skill upgrade path before accepting silent ageing.

A project scaffolded at v0.3 can retain v0.3 instructions while validators enforce v0.7. The ADR states that this risk is unmitigated. Add a version marker, staleness check, and user-controlled upgrade path to the roadmap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0015-the-convention-ships-as-skills.md` around lines 55 - 68, Update
the ADR roadmap to include a skill upgrade path addressing version drift: add a
generated-skill version marker, have ow init detect and report stale skills
without overwriting user edits, and provide a user-controlled upgrade mechanism
such as a reviewable diff or confirmation-based update.

Comment thread docs/glossary.md
- **track** — one of the two captured streams, `mic` or `system`. Avoid: feed
- **timeline** — the two tracks merged and ordered by real time, in `timeline.json`, and written out as `timeline.vtt` for anything that reads WebVTT. Avoid: transcript
- **transcription journal** — the per-chunk record of a transcription in progress, in the recording's directory, that makes an interrupted run resumable — `adr:0012-transcription-is-a-journalled-serial-pipeline`. It is not the operation log of `.state/` and not the wiki's `log.md`.
- **time map** — the table converting an instant of the compressed audio into a real instant, in `timemap.json`. Avoid: offset table

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- candidate files ---'
git ls-files | grep -E '(^|/)(glossary\.md|open-wiki\.md)$|(^|/)docs/' | head -200
printf '%s\n' '--- glossary context ---'
glossary=$(git ls-files | grep -E '(^|/)docs/glossary\.md$' | head -1 || true)
if [ -n "$glossary" ]; then
  cat -n "$glossary" | sed -n '1,80p'
fi
printf '%s\n' '--- open-wiki references ---'
wiki=$(git ls-files | grep -E '(^|/)plans/open-wiki\.md$' | head -1 || true)
if [ -n "$wiki" ]; then
  rg -n -C 5 'time.?map|recording|canonical|4\.7|4\.11|workspace|timemap' "$wiki" || true
fi
printf '%s\n' '--- repository-wide references ---'
rg -n -i -C 2 'timemap\.json|time map|time-map|canonical recording layout|task 4\.[0-9]+|pnpm workspaces?|workspace' . --glob '!node_modules' --glob '!dist' --glob '!build' | head -400

Repository: protonspy/open-wiki

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re

glossary = Path("docs/glossary.md").read_text()
plan = Path("plans/open-wiki.md").read_text()
adr = Path("docs/adr/0006-opus-as-the-provenance-format.md").read_text()

print("glossary time-map entries:")
for i, line in enumerate(glossary.splitlines(), 1):
    if re.search(r"time map|timemap\.json", line, re.I):
        print(f"{i}: {line}")

print("\nrecording-layout block:")
lines = plan.splitlines()
for i, line in enumerate(lines, 1):
    if "fenix/" in line:
        for n in range(i, min(i + 10, len(lines) + 1)):
            print(f"{n}: {lines[n-1]}")
        break

print("\nrequired time-map tasks:")
for i, line in enumerate(lines, 1):
    if re.search(r"time map|timemap\.json", line, re.I):
        print(f"{i}: {line}")

print("\nADR 0006 time/provenance references:")
for i, line in enumerate(adr.splitlines(), 1):
    if re.search(r"time map|timemap\.json|recording|opus", line, re.I):
        print(f"{i}: {line}")

print("\ntracked timemap.json files:")
for path in Path(".").rglob("timemap.json"):
    if any(part in {".git", "node_modules", "dist", "build"} for part in path.parts):
        continue
    print(path)
PY

Repository: protonspy/open-wiki

Length of output: 2309


Document the time-map path consistently. plans/open-wiki.md omits timemap.json from the recording layout, although docs/glossary.md and tasks 4.3, 4.7, and 4.11 require it. Add the file to the layout or update both documents to use the chosen path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/glossary.md` at line 16, Update the recording layout in
plans/open-wiki.md to include timemap.json, matching the path defined in
docs/glossary.md and referenced by tasks 4.3, 4.7, and 4.11; keep the naming
consistent across all documentation.

Comment thread plans/open-wiki.md
Comment on lines 74 to 90
```
<workspace>/
fenix/ one project
raw/ sources, immutable once written and named for what they are
fenix-weekly-2026-07-31/ a recording, named for the occasion and its date
manifest.json · mic.opus · system.opus
timeline.json · timeline.vtt · text.md
journal.json · *.wav only until transcription seals the source
arquitetura-fenix.pdf/ an uploaded file, keeping its filename
manifest.json · source.pdf · text.md
wiki/ primary content, written by the agent and by the user
index.md · changelog.md · log.md
projects/*.md · people/*.md · topics/*.md
.state/ snapshots and operation log; not content
CLAUDE.md schema and methodology, for the agent operating the folder
atlas/
...
fenix/ a project — usually a repository the user already has
raw/ sources, immutable once written and named for what they are
fenix-weekly-2026-07-31/ a recording, named for the occasion and its date
manifest.json · mic.opus · system.opus
timeline.json · timeline.vtt · text.md
journal.json · *.wav only until transcription seals the source
arquitetura-fenix.pdf/ an uploaded file, keeping its filename
manifest.json · source.pdf · text.md
wiki/ primary content, written by the agent and by the user
index.md · changelog.md · log.md
projects/*.md · people/*.md · topics/*.md · codewiki/*.md
.state/ snapshots and operation log; not content
.claude/skills/ the wiki and codewiki conventions, scaffolded by `ow init`
.mcp.json other projects this one consults; never itself
CLAUDE.md short, and pointing at the skills
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Specify the layout fence language.

markdownlint reports MD040 for Line 74. Use text for this directory layout.

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/open-wiki.md` around lines 74 - 90, Update the fenced directory-layout
block in the plan so its opening fence declares the text language, resolving
markdownlint MD040 while preserving the layout content unchanged.

Source: Linters/SAST tools

Comment thread plans/open-wiki.md
wiki/ primary content, written by the agent and by the user
index.md · changelog.md · log.md
projects/*.md · people/*.md · topics/*.md · codewiki/*.md
.state/ snapshots and operation log; not content

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not classify .state/ as non-content.

.state/ contains snapshots of prior pages. Those snapshots can retain unredacted text after a redaction. Describe it as recovery history that may contain prior content, and retain the explicit default-ignore requirement.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/open-wiki.md` at line 86, Update the `.state/` entry in the
documentation to describe it as recovery history containing snapshots of prior
pages that may retain prior or unredacted content, rather than classifying it as
non-content. Preserve the explicit requirement that `.state/` is ignored by
default.

Comment thread plans/open-wiki.md Outdated

- [ ] 2.1 (Unit) Open or create a workspace: choose the folder and refuse one already occupied by something else
- [ ] 2.2 (Unit) Create, list and rename projects, each with its own `raw/`, `wiki/`, `.state/` and `CLAUDE.md`
- [ ] 2.1 (Unit) Open or create a project in a directory: scaffold `raw/`, `wiki/` and `.state/`, and refuse a directory already occupied by something else

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Allow ow to open an existing project directory.

“Refuse a directory already occupied by something else” conflicts with the stated workflow of running ow inside an existing repository. Limit this refusal to create mode. Open mode must validate and accept an existing project layout.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/open-wiki.md` at line 104, Update the project-directory workflow
described in item 2.1 so existing project directories are accepted in open mode,
with validation of the expected project layout. Restrict refusal of occupied
directories to create mode, while preserving scaffolding of raw/, wiki/, and
.state/ when creating a new project.

Comment thread plans/open-wiki.md Outdated

## 9 — The CLI, MCP and the agent's contract

- [ ] 9.1 (Unit) A project access module — read, search, validate, write — one implementation, imported by the application, the CLI and the MCP process

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Keep the write path out of the MCP process.

Task 9.1 defines one module containing read, search, validate, and write, then imports it into MCP. ADR 0013 and task 9.8 require the MCP entrypoint not to import the write path at all. Split the read-only core from the write-capable module.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/open-wiki.md` at line 197, Revise task 9.1 so the project access
functionality is split into a read-only core containing read, search, and
validate, and a separate write-capable module containing write. Ensure the MCP
process imports only the read-only core, while the application and CLI may use
the write-capable module.

Comment thread plans/open-wiki.md Outdated
- [ ] 9.10 (Unit) Announce the project in the server's name and description, so an agent with several configured says which base it answered from
- [ ] 9.11 (Unit) `ow search` and `ow graph`: the lexical and structural queries over the local project that `adr:0013-the-project-directory-is-the-unit` sends to the CLI rather than to MCP, printing JSON
- [ ] 9.12 (Unit) A validation error readable enough for the agent to fix it on its own and try again — the same text whether it came from the CLI, a hook or the editor
- [ ] 9.13 (TDD) Pay down cold start: bundle the CLI to a single file, and talk to the running application over a local socket when there is one — the socket carries read and validate and never write, and the standalone path produces the same answer

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Carry the local-socket security constraint into task 9.13.

ADR 0013 requires a restrictive named-pipe ACL where available and rejects unauthenticated local listeners. Add those transport and access-control requirements here. “Read and validate, never write” alone does not prevent the loopback exposure from returning.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/open-wiki.md` at line 209, Update task 9.13 in plans/open-wiki.md to
explicitly require a restrictive named-pipe ACL where supported and rejection of
unauthenticated local listeners, while preserving the existing local-socket
read/validate-only and standalone-equivalence requirements.

…k contract again

A validation pass over plans/open-wiki.md, then a review of the fixes.

The architecture hole was group 5: the preamble said every write goes
through the validated store, but nothing said which caller does what, so
the automatic fields, the log and the index had no executor on the path
the agent actually uses. The preamble now divides one module across three
callers — editor and CLI verb, the hook pair, the folder observer — and
9.5 builds both hooks rather than only PreToolUse.

Second correction to the same fact in two commits: a PreToolUse hook can
return updatedInput and rewrite the arguments before the tool runs. So the
store does not merely refuse on the direct path, it completes — the fields
filled on the agent's behalf are written into the input rather than
demanded back in an error. The first commit said the hook cannot see the
content; a draft of this one said it cannot change it. Both were reasoned
about rather than read, and the plan now says so where the claim lives.

Other holes closed: supersession was prose-only, so `ow graph superseded`
had nothing to walk (new 5.2, and the glossary entry it contradicted);
8.12 and 9.3 disagreed about whether changing the content language rewrites
a scaffolded file, and the first fix traded that contradiction for a hole
where nothing put the language in front of the agent at all; three tasks
scaffolded a project and produced different projects depending on the door;
nothing wrote the consulting .mcp.json, leaving the paste step the pivot
claimed to have removed (new 9.8); raw/_inbox sat inside the immutable
tree with no exemption; index.md, changelog.md and log.md were about to be
validated against the entity schema.

ADR 0009 stops citing a task number that had already rotted twice, 0014
says why 0010 is marked superseded rather than rejected and answers the
ordering question 0010 left open, and the Methods note stops being a
roll-call that was already missing six tasks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C9Vv5jJqcGxrStXhLwbf9b
@protonspy

Copy link
Copy Markdown
Owner Author

Second pass — validation of the plan, and the holes it found

Reviewed plans/open-wiki.md against the fifteen ADRs and the house rules, then reviewed the fixes. npx @protonspy/scc validate is at exit 0, 94 tasks, no duplicate numbers, and every cross-reference inside a task line resolves to a task whose content matches the claim made about it.

The architecture hole

Group 5's preamble said every write goes through the validated store, but nothing said which caller does what. On the path the agent actually uses, the automatic fields (5.5), the log and changelog (5.6) and the index (5.7) had no executor at all. The preamble now divides one module across three callers — editor and CLI verb, the hook pair, the folder observer — and 9.5 builds PostToolUse as well as PreToolUse, since the log describes a write that has already happened.

The hook contract, wrong a second time

The first commit recorded that a PreToolUse hook cannot see the content it is about to allow. A draft of this one recorded that it cannot change it. Both are false — it receives the complete tool_input and can return updatedInput, which replaces the arguments before the tool runs. So on the direct path the store does not merely refuse, it completes: the fields filled on the agent's behalf are written into the input rather than demanded back in an error message.

Both errors came from reasoning about the contract instead of reading it, so the plan and ADR 0013 now say so at the place the claim lives. What genuinely does not survive is coverage of writes made through the shell, which stays 9.5's problem.

Other holes closed

Supersession was prose-only ow graph superseded had nothing to walk. New task 5.2 records it as data; the glossary entry that contradicted it was rewritten.
8.12 vs 9.3 They disagreed on whether changing the content language rewrites a scaffolded file. The first fix traded that for a worse hole — nothing put the language in front of the agent at all. It now lives in the project settings and reaches the generated CLAUDE.md, which is what ADRs 0008 and 0013 already said.
Three scaffolders 2.1, 9.3 and 2.8 each built part of a project, so a project differed by which door it came through. 2.1 is now the one scaffolder and the others are what it calls.
Nobody wrote .mcp.json The consulting entry had a consumer and a prohibition but no author — leaving a hand-written stdio invocation, which is the paste step the pivot claimed to have removed. New task 9.8.
raw/_inbox/ Sat inside the immutable tree with no exemption from enumeration, citation or the uncited-source check.
index.md, changelog.md, log.md Were about to be validated against the entity-page schema.
Snapshot 2.3 bundled it with the atomic write, so it could not be called on the hook path, where the agent's tool does the writing.

Also: ADR 0009 stops citing a task number that had rotted twice; 0014 explains why 0010 is marked superseded rather than rejected and answers the ordering question 0010 left open (graph before search); the Methods note stops being a roll-call that was already missing six tasks.

Still open, unchanged

The write gate's composition (9.5), and what of raw/ and .state/ enters git. Embeddings are now closed — refused outright, recorded in 0013.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plans/open-wiki.md`:
- Line 211: Update task 8.12 in the project plan by changing “afterwards” to the
American English spelling “afterward”; leave the rest of the task text
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fe997656-446c-42a3-ad73-27fd11edb3b2

📥 Commits

Reviewing files that changed from the base of the PR and between f70e36b and e2e8787.

📒 Files selected for processing (8)
  • docs/adr/0009-distribution-through-github-releases.md
  • docs/adr/0013-the-project-directory-is-the-unit.md
  • docs/adr/0014-typescript-everywhere-except-audio-capture.md
  • docs/adr/0015-the-convention-ships-as-skills.md
  • docs/glossary.md
  • docs/wiki/changelog.md
  • docs/wiki/claude-code-plugins.md
  • plans/open-wiki.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • docs/adr/0015-the-convention-ships-as-skills.md
  • docs/glossary.md
  • docs/wiki/claude-code-plugins.md
  • docs/adr/0014-typescript-everywhere-except-audio-capture.md
  • docs/adr/0013-the-project-directory-is-the-unit.md
  • docs/wiki/changelog.md

Comment thread plans/open-wiki.md
- [ ] 9.17 (Unit) Write the agent-facing skill **from the tool list 9.7–9.10 actually shipped**, and settle in the same task whether it or the `CLAUDE.md` of 9.14 is the single home of the convention
- [ ] 8.10 (Unit) Watch the folder and reflect changes on screen live, whichever wrote them — the agent, a hook, or the user in another editor
- [ ] 8.11 (Unit) An operation history with undo, fed by 2.4, and honest about covering only what was observed
- [ ] 8.12 (Unit) Choose the content language at onboarding and change it afterwards — English by default, Brazilian Portuguese and Spanish alongside it — held in the project settings of 2.7 and reaching exactly two places: the transcription hint of 4.15, and the generated `CLAUDE.md` of 9.4, which is regenerated on change because it is generated and the skills are not

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the American English spelling.

Change afterwards to afterward in task 8.12.

🧰 Tools
🪛 LanguageTool

[locale-violation] ~211-~211: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ...nt language at onboarding and change it afterwards — English by default, Brazilian Portugu...

(AFTERWARDS_US)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/open-wiki.md` at line 211, Update task 8.12 in the project plan by
changing “afterwards” to the American English spelling “afterward”; leave the
rest of the task text unchanged.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant