point the editor preview at the demo, and shorten the skill name

Four small things from one sitting, none of which would be reverted without the
others:

- .claude/launch.json describes the only dev server this repo has: make demo on
  localhost:8080. Deliberately not autoPort — examples/demo-site declares
  base: http://localhost:8080, so canonical, hreflang, OpenGraph and sitemap URLs
  are built from that port, and a reassigned one would make the absolute URLs on
  the page wrong while still rendering fine.
- The skill is .claude/skills/feature-loop/, without the khosra- prefix. ADR-0054
  records it, because ADR-0030 had named the prefixed form while settling the
  project name and decisions.md is append-only.
- Makefile .PHONY was missing quiet and surface, added two commits ago. A file of
  either name in the repo root would have silently shadowed the target.
- A latent row: the root listing's title reads "A Khosra Demo · A Khosra Demo",
  because base.html joins page title and site title unconditionally and at the
  root they are the same string. Found by looking at the served page — no test
  asserts a title. Theme layer, one if, and it waits for Phase G4.
This commit is contained in:
Claude Opus 5
2026-08-01 02:46:30 +06:00
committed by bdeshi
parent aad7d64270
commit 36194a16d8
7 changed files with 33 additions and 3 deletions
+11
View File
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "demo",
"runtimeExecutable": "make",
"runtimeArgs": ["demo"],
"port": 8080
}
]
}
+1 -1
View File
@@ -86,7 +86,7 @@ the test: `docs/architecture.md`.
## 4. The loop (every request, no exceptions)
`Clarify → Plan → Implement → Verify → Document → Commit → Report`.
Procedure: `.claude/skills/khosra-feature-loop/SKILL.md`. The three gates people skip:
Procedure: `.claude/skills/feature-loop/SKILL.md`. The three gates people skip:
**Clarify.** Only questions whose answer changes the code or the bytes on disk. Max three,
batched, up front, each with a **bold** default so silence answers. Never about naming, formatting,
+5 -1
View File
@@ -7,7 +7,8 @@ before code, docs that stay true.
constitution (always loaded). `docs/` is what the agent needs to build the
engine — anything in it may be pulled into context on demand. `ideas/` and `reference/` sit outside
`docs/` deliberately: storage, opened only when you name a file, swept by nothing.
`.claude/` holds the feature-loop skill and six commands. `scripts/` holds the gate.
`.claude/` holds the feature-loop skill (`skills/feature-loop/`), six commands, and `launch.json`.
`scripts/` holds the gate.
## How you use it
@@ -56,6 +57,9 @@ because a reference theme that grows taste stops being a reference (ADR-0026).
edit it and serve it with `make demo`. It stays true by two gates: a coverage test in `internal/web` serves it
through the real handler with one case per feature, and `verify.sh` runs `khosra check` over it. A feature added
without a case there is a feature the demo does not show, and the build says so (ADR-0051).
`.claude/launch.json` points the editor's preview at that same `make demo` on `localhost:8080`, so
"look at it" and "test it" are the one site. It is the only dev server this repo has: the engine serves
a site root and there is nothing else to run.
**The agent names the layer as well as the primitive.** Content on disk, engine, theme, browser — and it builds
at the outermost layer that can do the job (`CLAUDE.md` §2, `docs/architecture.md`). This exists because a whole
+1 -1
View File
@@ -5,7 +5,7 @@ SITE ?= $(KHOSRA_SITE)
ADDR ?= localhost:8080
BIN := ./khosra
.PHONY: help build run check new demo test verify fmt tidy clean
.PHONY: help build run check new demo test verify quiet surface fmt tidy clean
help: ## list targets
@grep -hE '^[a-z]+:.*##' $(MAKEFILE_LIST) | sed 's/:[^#]*## /|/' | column -t -s '|'
+14
View File
@@ -813,3 +813,17 @@ is discipline, and it says so instead of implying enforcement (rule 8).
Revisit if: the surface grows past a few hundred lines, in which case it is per-package files rather than
one; or `surface.md` churn starts drowning real diffs, which is the argument for generating it on demand
instead of tracking it.
## ADR-0054 — The feature-loop skill drops its `khosra-` prefix
Date: 2026-08-01 · Status: accepted (amends ADR-0030's skill-name clause only; the rest of that naming
decision stands)
Decision: the skill directory is `.claude/skills/feature-loop/`, not `khosra-feature-loop`.
Why: the human asked, and the prefix was redundant — every file in this repository is khosra's, so a
`khosra-` prefix inside it distinguishes nothing. ADR-0030 named the skill as part of settling the
project's name, which made sense while `atelier` was still being erased; it does not survive contact
with the fact that the skill is only ever loaded from this repo.
Consequence: cheap — a shorter name in the one place it is written (`CLAUDE.md` §4) and in the skill
listing. ADR-0030 keeps its original text because `decisions.md` is append-only, so a reader who lands
there sees the old name; this entry is the pointer that makes it resolvable.
Revisit if: the skill is ever published or shared outside this repo, where an unprefixed `feature-loop`
would collide with everyone else's.
+1
View File
@@ -106,6 +106,7 @@ with a stated reason. A list nothing drains is a graveyard of known defects.
| `date` stays in `Extra` after being lifted onto `Bundle.Date`, unlike `title`, `aliases`, `tags` and `order`, which are deleted | Spotted while adding `order`; the theme contract says `Extra` holds what the parser does not name, so one of the two is wrong. Harmless today — a template reading `.Extra.date` gets the raw YAML value | Whatever next reads `Extra` generically: feeds (queue 14) or `check` (17) |
| A gallery's images carry no `alt` | `width`/`height` now come from the original (ADR-0042), so only alt text is missing, and a filename does not supply one. An empty `alt` is honest for a picture the page has already introduced | Captions per gallery entry — a sidecar or a frontmatter list — if the reference theme ever needs them |
| Sequence resolution rescans the index on every bundle request — two passes over every key, each doing a `Lookup` | Measured at the same time as the pictures (ADR-0044): a whole page is ~63µs, so this is not what costs anything. Remembering it would be a cache with no measurement behind it | A page render exceeding a few milliseconds, which is also what would revive the parked cache model |
| The root listing's `<title>` repeats itself — "A Khosra Demo · A Khosra Demo" | Spotted 2026-08-01 by looking at the served page, not by any test: `base.html` joins page title and site title unconditionally, and at the root those are the same string. Cosmetic, and the fix is one `if` in a template — theme layer, not engine | The first time the reference theme is worked on (Phase G4 touches it), or sooner if a feed or OpenGraph title inherits the same doubling |
| The picture memo is never evicted — one entry per picture on the site, for the life of the process | Correct for one author's site, and the alternative is an eviction policy nothing needs. It is keyed on size and modification time, so it cannot go stale, only grow | A site root large enough that memory matters, or a long-running process where pictures churn |
## Open questions