113 Commits
Author SHA1 Message Date
Claude Opus 5andbdeshi f37e7b1308 harness: say which settings file the exemption means
The exemption is Claude Code's permission list, not "settings files". khosra will
have its own configuration and none of it is exempt: the engine's settings live in
the site root and the engine validates them, while scripts/budgets.env and
everything else under scripts/ and .claude/ stays gated. Verified by touching
budgets.env and watching the coupling gate fail.
2026-07-30 01:39:28 +06:00
Claude Opus 5andbdeshi d0197a41ed add a Makefile and build instructions
So the thing can be built and run without reading the harness. Eight targets,
each one go command or verify.sh; make help lists them. README gains the four
lines someone actually needs, and says a site root is a directory the binary is
pointed at rather than something in this repo.

make is recorded in toolchain.md as a convenience: the gate never invokes it, so
a machine without make loses nothing but typing.
2026-07-30 01:38:17 +06:00
Claude Opus 5andbdeshi e14171fa02 harness: fail an untidy go.mod
go get marks a module indirect until something imports it, and the allowlist
check only inspects direct requires — so an unapproved dependency could sit in
go.mod unnoticed. Demonstrated: adding github.com/google/uuid passed the
allowlist check and was caught only by this gate.
2026-07-30 01:36:34 +06:00
Claude Opus 5andbdeshi 519a41cf2f serve a bundle at its permalink
-site (or KHOSRA_SITE) opens the site root through content.OpenSite, so every
read keeps the os.Root guarantee. A path is a bundle key: /{section}/{slug}/
serves, the slashless form redirects permanently to it (ADR-0008), anything
unknown is 404. Render failure logs and returns a bare 500 rather than leaking a
template or filesystem detail.

internal/render holds goldmark plus the embedded reference theme (ADR-0026):
base.html with a redefinable "main" block, and one stylesheet inlined through
.Style. Serving it at an asset route would have been a second routing case for no
gain, and static serving belongs to a later entry.

Evidence beyond the tests: the binary against a real site root returns 200 with
<h1>About</h1> and the rendered body, 301 from /pages/about to /pages/about/, and
404 for /nope/. A Bengali variant is scanned but not yet reachable — that is the
next entry.

theme-contract.md gains a "Live today" section listing the six fields and two
named templates a theme may now rely on; the rest stays marked as shape.
2026-07-30 01:35:50 +06:00
Claude Opus 5andbdeshi 2466ce79c7 harness: permissions changes owe no HARNESS.md note
The coupling gate treated every path under .claude/ as mechanism, so editing the
pre-approved command list demanded an explanation of a machine that had not
changed. HARNESS.md already calls settings.json a convenience — if its schema
changed the harness would still work, you would just get more prompts — so the
gate now exempts that one file and nothing else.

Carries the settings.json edit that exposed it.
2026-07-30 01:35:14 +06:00
Claude Opus 5andbdeshi 242bd60d9c keep the build queue in an uncommitted .scratch/
The queue is a working plan, not a record: git log already carries what landed on
each step, so committing the plan duplicates it and invites the two to disagree.
.scratch/ is gitignored and skipped by the gate the way ideas/ and reference/ are,
so exploratory files there need not compile.

state.md keeps a conditional pointer rather than a path it cannot promise: if the
scratch file is absent, the log is the plan.
2026-07-30 01:30:48 +06:00
Claude Opus 5andbdeshi 192b0fb993 content-model: state the language-suffix shape and the collision rule
The parser treats two or three lowercase letters before .md as a language and
rejects a key claimed by two spellings of one variant. Both were implemented and
neither was in the doc that owns the disk contract.

Folded from a separate state commit:
state: point verified-against at the commit that introduced code
2026-07-30 01:30:46 +06:00
Claude Opus 5andbdeshi f1d31437be content: read a site root into bundles
Bundle loading with no HTTP: walk content/, split YAML frontmatter, derive an
NFC-normalised key and a language from the filename, and lift only title out of
frontmatter so every other key stays readable through Extra (ADR-0002).

Path safety is os.Root rather than a hand-rolled cleaner (ADR-0031). os.DirFS
documents that it does not prevent symlink escape; os.Root refuses any name
resolving outside the root, so the guard is a property of the type instead of a
check to remember at each call site. Test: a symlink to a file above the root
cannot be read. This clears the traversal item off the latent list.

A bundle that will not parse is logged and skipped, never fatal (ADR-0029), as
is a key claimed by two spellings of one variant (ADR-0021).

Bundle carries only Key, Lang, Path, Title, Body and Extra; Date, Slug, Draft
and Aliases arrive with the features that read them.
2026-07-30 01:30:12 +06:00
Claude Opus 5andbdeshi 781c756a0f harness: three gate fixes found by running against real code
The allowlist parser stripped only whole-line comments, so an entry carrying the
reason it exists — the format allowed-deps.txt documents — failed the gate and
would have blocked every dependency ever added.

The interface{}/any advisory printed a line number instead of a filename when
only one file matched, because grep -n omits the name for a single file, and it
matched the word "any" in prose comments.

"Nesting past 4" fired at four tabs, which a closure inside a function reaches
unaided.
2026-07-30 01:30:11 +06:00
Claude Opus 5andbdeshi 9d817dcadf rename the project to khosra, initialise the module
Naming is free before a module is published, a URL is shared, or a binary is
deployed; every day it waits costs more. Swept every form: module path, binary,
cmd/ directory, KHOSRA_SITE, the feature-loop skill directory, and the prose in
earlier ADRs — which describe this project under its old name, not a different
project. Recorded as ADR-0030.

go mod init lands here rather than with the first feature because the module
path is what the rename is about. x/text and yaml.v3 are required but not yet
imported, so both are indirect and no direct dependency is claimed yet.
2026-07-30 01:14:01 +06:00
Claude Opus 5andbdeshi 126fdbc861 harness: soften two gates that would have taught --no-verify
The test-coupling gate failed comment-only and gofmt-only .go diffs, which
ship no behaviour and owe no test. Bypassing it would have cost every gate at
once, so it now compares added and removed lines with comments, blanks and
whitespace runs stripped: equal sets mean nothing happened. A new .go file is
never exempt.

The exported-doc-comment check is now a warning. No gate can tell
"// Load loads." from a useful sentence, so as a hard failure its cheapest
satisfaction was exactly the noise conventions.md calls worse than nothing.
Package comments and ADR citations in code stay hard.

Also fills in state.md's verified-against line and drops a stray blank line
left in roadmap.md by an earlier gate test.
2026-07-30 01:09:22 +06:00
Claude Opus 5andbdeshi 99f8c730b0 harness: withdraw five pre-code ADRs to deferred ideas
Twenty-seven ADRs existed before a line of Go. Five specified the shape of
unbuilt mechanisms — cache validity, declared types, the settings cascade,
taxonomies, extras — which breaks the rule against abstraction before a
second concrete use, in prose where the counters cannot see it. They move to
ideas/deferred-decisions.md as recorded intent and return shaped by whatever
implements them.

Citations retargeted throughout; where one was decoration the rule now stands
on its own reasoning. Type declarations and the cascade drop to [spec] with
the MVP behaviour stated instead, so the first prompts have less to build.
conventions.md names http.ServeMux as the router, closing a hole that invited
hand-rolling a path splitter. The ADR gate now checks a number is registered
in the log rather than headed by an entry, so withdrawals resolve and invented
numbers still fail. Two architecture invariants corrected: identity no longer
implies a required language suffix, and the duplicated permalink clause is gone.
2026-07-30 01:01:38 +06:00
bdeshiandClaude Opus 5 02268f9121 init
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 00:34:18 +06:00