Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
dfe1494
Repo true-up: Features own their state, augment official Features, ho…
nabil-becker Oct 15, 2026
fe09068
Devhost: this repo's devcontainer runs on its own Features by local path
nabil-becker Oct 15, 2026
1e0f7c6
devhost Feature: the way of working as a Feature, and this repo boots…
nabil-becker Oct 15, 2026
20b091f
Backlog: TD-12, dsc's dependence on the GitHub API makes CI flaky
nabil-becker Oct 15, 2026
eab81d5
fix: make the pre-commit hook executable
Oct 16, 2026
a5f5238
fix(devhost): non-identifying engineer handle; ignore and guard .env …
Oct 16, 2026
9122bd9
chore: commit the devcontainer lock file
Oct 16, 2026
7a7f65b
chore: test preflight for a missing Docker daemon; document the host-…
Oct 16, 2026
f27f32d
feat(devhost): descriptive slug ids for backlog items
Oct 16, 2026
e4149b9
docs: devhost parts of README, CONTRIBUTING, Taskfile and lint
Oct 16, 2026
b8e475c
docs: the records of 2026-10-16 (ledger, backlog, lexicon, ADRs 0001-…
Oct 16, 2026
a0f06c9
docs: the backs' last records before the devhost rebuild
Oct 16, 2026
d9ba484
docs: first ledger review (2026-10-16)
Oct 16, 2026
4301e14
chore: night shift 2026-10-16 plan; the backlog restored after a secr…
Oct 16, 2026
a2ea661
docs: one checklist for adding a Feature (new-feature-checklist)
Oct 16, 2026
f8a7a2d
docs(proposals): King Arthur theme (write-king-arthur-proposal)
Oct 16, 2026
f8ca5c6
docs(proposals): a journalist back (write-journalist-proposal)
Oct 16, 2026
10c64cb
docs(proposals): personalization (write-personalization-proposal)
Oct 16, 2026
717ee84
docs: night shift 2026-10-16 report; the records of the night
Oct 16, 2026
329808e
docs: the Arthurian layer in the lexicon; the theme proposal accepted
Oct 16, 2026
a425ba9
docs(journal): the bard's first piece, 2026-10-16 (hand-run trial)
Oct 16, 2026
862b78f
docs: the backs' records of the bard trial (ADR 0004, ledger, backlog)
Oct 16, 2026
ceba8fd
docs: the journal stays in plain words; no committed output speaks in…
Oct 16, 2026
676948d
docs: night shift 2026-10-16 reviewed, all items kept
Oct 16, 2026
0a8475b
docs: backlog PR items name #12 and #13; the C4 model decision taken
Oct 16, 2026
b77dea3
docs: the backs' records: ADR 0005 (the ontology), lexicon terms, Fea…
Oct 16, 2026
e97c219
docs: the purpose: Features first, and this repo as the third iterati…
Oct 16, 2026
0fca437
docs: backlog splits Feature principles from agent principles (featur…
Oct 16, 2026
79f6f5e
docs(proposals): Feature principles and agent principles drafts (feat…
Oct 16, 2026
b7f7016
docs(records): iteration package proposal, AP-14 ladder, ADRs 0006 an…
Oct 16, 2026
4c79f39
docs(records): the iteration package proposal is accepted, ADR 0008 (…
Oct 16, 2026
8c255f9
docs(model): canonical ontology, Arthurian theme labels and C4 views …
Oct 16, 2026
537bcc8
docs(model): ids for the ontology and the C4 view (ontology-guard)
Oct 16, 2026
a5be9c3
docs(model): the C4 context view puts the Features at the centre (reo…
Oct 16, 2026
8a10409
docs(ledger): correct the dashboard fix entry's friction
Oct 17, 2026
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
50 changes: 50 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"permissions": {
"allow": [
"Bash(task *)",
"PowerShell(task *)",
"Bash(git status*)",
"Bash(git log*)",
"Bash(git diff*)",
"Bash(git show*)",
"Bash(git branch*)",
"Bash(git rev-parse*)",
"Bash(git ls-files*)",
"Bash(devhost-briefing*)",
"Bash(devhost-costs*)",
"Bash(devhost-report*)",
"Bash(devhost-verify*)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)"
]
},
"hooks": {
"SessionStart": [
{
"hooks": [
{"type": "command", "command": "devhost-briefing", "timeout": 30}
]
}
],
"Stop": [
{
"hooks": [
{"type": "command", "command": "devhost-run-job scribe", "async": true, "timeout": 600},
{"type": "command", "command": "devhost-run-job librarian", "async": true, "timeout": 600},
{"type": "command", "command": "devhost-run-job secretary", "async": true, "timeout": 600},
{"type": "command", "command": "devhost-run-job tester", "async": true, "timeout": 600}
]
}
],
"SubagentStop": [
{
"hooks": [
{"type": "command", "command": "devhost-run-job scribe", "async": true, "timeout": 600},
{"type": "command", "command": "devhost-run-job librarian", "async": true, "timeout": 600}
]
}
]
}
}
59 changes: 59 additions & 0 deletions .claude/skills/close-session/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
name: close-session
description: The end-of-session checklist for this repository. Use it before ending any working session, before opening a pull request, and whenever the user says they are done, wrapping up, or asks to commit or push. It makes sure the records carry the session's work (the ledger entries checked, the backlog current), the guards pass, and the work is on a branch, reported in the hand-off shape.
---

# Close a session

A session that changed code or documents is not finished until the next session, on any
engineer's machine, can pick up from the repository alone. This is the order to do it in.

## Steps

1. **Account for the work in the records.** Every unit of work has a ledger entry; every open
item is in `TODO.md` with an owner and a date; every settled term is in `LEXICON.md`; every
decision that needed more than a line has an ADR (`/new-adr`). Inside the devhost the backs
did most of this after each turn: read what they added (the quiet notices name it) and add or
reword by hand only what they missed or got wrong. On a workstation there are no backs: write
the entry, the items and the terms yourself, in the same shapes (`docs/ledger/README.md`,
`TODO.md`'s header).

2. **Check the scribe's ledger entries; never edit one.** Each entry against what happened: every
unit of work has one, including each con's job; the friction is complete and tagged; the
Operator's decisions are theirs; no real data, credentials or forbidden words; the Measures
line carries numbers. A wrong entry is corrected by a new entry with a `Corrects:` line.

3. **Run the guards and the checks.**

```sh
task devhost:verify # or: devhost-verify
task check # the repository's own suite, if it has one
```

A finding is fixed, not skipped. `git commit --no-verify` only on the Operator's say-so, with
the reason in the commit message and in the ledger entry.

4. **Scan the diff for boundaries.** The diff against the base branch must contain no
credentials, no identifiers, no real data, no name from the redact list.

5. **Commit on a topic branch.** Never on the base branch directly. Conventional Commit messages
naming the backlog ids; the agent's co-author trailer when the agent wrote the commit, at its `@noreply.invalid` address (ADR 0002). Commit
and push only when the user asked for it. If they did not, stop here and report what is ready.

6. **Open the pull request** when asked, with the template filled in and the checks stated as run.

7. **Report, in the hand-off shape**, so that what the session lacked travels with what it made:

```
Outcome: two to five lines: what changed, which ids were added or changed
Outputs: the branch, the pull request, the files written
Friction: what the session lacked or what went wrong, tagged
For the repository: [tooling] ..., [docs] ..., [skill] ..., [process] ...
Decisions needed: what is now the Operator's, and what the next session should start with
```

## Why

The next session reads the repository, not this conversation. If a decision, an item or a term
lives only here, it is gone. The checklist is short because every step has already bitten
someone.
57 changes: 57 additions & 0 deletions .claude/skills/ledger-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
name: ledger-review
description: Review the ledger (docs/ledger/YYYY-MM.md, written by the scribe back) every five or so entries, reading the month's agent-cost report first, and turn what the entries recorded (friction, learnings, measures, questions) into one concrete change per group - a TODO.md item, a decision for the Operator, a change made now with its test, or no action with a reason - starting by checking whether the last review's friction came back. Use it when the briefing says a review is due, or when the Operator asks what keeps going wrong, what the agents cost, or whether a model is the right size.
---

# Review the ledger

The ledger is only worth keeping if it is read. A review is where its entries become changes:
one per group, small, with a test where it is tooling. Every five or so entries, a review; each
review starts by checking whether last time's friction came back, because an agreed fix can go
unapplied; and it starts from the numbers, so the models can be right-sized.

## Steps

0. **Read the cost report first.** `task devhost:report` (or `devhost-report`) rebuilds
`docs/ledger/costs-YYYY-MM-<engineer>.md` for this machine; read the other engineers' beside
it. Its "What to look for" list turns cost into friction: a con type on a large model at a
low cost per run, inter cost per session rising, a back's cost per change rising, many
"nothing" runs, guard undos, ledger corrections, frequent stakes, errors
(`devhost-report --log`). Backs are improved through this loop like any skill: their briefs,
thresholds and models.

1. **Find the entries to review.** The last `## Review YYYY-MM-DD` section in the monthly files
closes the previous review; the entries after it are the input (the briefing counts them).
Skip an entry that a later entry `Corrects:`; read the correcting one instead. Fewer than four
entries: say so and stop, unless the Operator asked anyway.

2. **Check recurrence first.** For each change the previous review promised (its actions, and the
`TODO.md` items it added), check that it was applied: the item ticked, the test that exists,
the skill that changed, the model that moved. A promised change that was never made is
reopened in this review before anything new is considered.

3. **Group what the entries say.** Read every entry's *Friction*, *Learned*, *Measures*, *For the
repository* and *Decisions needed*, and the cost report's findings. Group by cause, not by
wording: a document that drifts, a task that is missing, a skill that is silent on a case, a
question that keeps being asked, a cost that keeps being paid, a model oversized for its work.
Measures are read as a trend.

4. **One action per group.** Exactly one of: a `TODO.md` item with owner, date and the friction it
should make go away; a decision for the Operator under "Decisions for the Operator" in
`TODO.md`, with a recommendation; a change made now in this branch, with the test that would
have caught it when it is tooling (a model moved for a job is a change too); or no action,
with the reason written down. Prefer the smallest change that removes the cause.

5. **Append the review section.** Put the proposed actions to the Operator in a few lines; on
agreement, append to the current monthly file a `## Review YYYY-MM-DD` section: the entries
reviewed (first and last date and title), the cost report's headline numbers, each group with
its action and id, what the review itself lacked, and what is deferred. The review is never
edited afterwards; the next one starts from it.

6. **Close.** `task devhost:verify`, then `/close-session` as usual. The pull request's
description is the review section, expanded.

## Why

A log nobody reviews is a cost without a return. The review is short because every entry already
says what it lacked; the work is to decide once per cause, and to keep a promise once made.
45 changes: 45 additions & 0 deletions .claude/skills/new-adr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
name: new-adr
description: Write an architecture decision record for this repository. Use it when a decision needs more reasoning than a backlog item or a ledger line holds, when two or more options were seriously weighed, when a choice constrains how people work (branching, tooling, review) or how the system is shaped (a boundary, a protocol, a store), or when the user asks for an ADR, a decision record, or to "write up why we chose X". Not for choices a single line states completely.
---

# Write an ADR

An ADR is the long form for the few decisions that need it. [docs/adr/README.md](../../../docs/adr/README.md)
holds the format, numbering and lifecycle.

## Steps

1. **Confirm it deserves one.** If the decision, its source and its consequence fit in a backlog
item or a ledger line, write that and stop. The test: will someone ask "why" in a year, and
would the line answer them?

2. **Create the file** from the template with the next number:

```sh
task devhost:adr -- Short title of the decision # or: devhost-adr Short title of the decision
```

This writes `docs/adr/NNNN-short-title-of-the-decision.md` and adds the index row to the ADR
README.

3. **Fill the sections in order.** Keep the headings exactly; `devhost-verify` checks them.
- *Context*: the situation and the forces, each with its source (a note, a document, a
measurement, with the date).
- *Decision*: full sentences, present tense, specific enough to check the repository against.
- *Options considered*: the chosen one first with why it wins, then each losing option with why
it lost. An option nobody would have chosen is padding; leave it out.
- *Consequences*: easier, harder, and what must now be done, with backlog items if any. Name
the open questions it leaves.

4. **Status.** `proposed` until the Operator confirms (then `accepted`) or rejects (`rejected`). A
change to an accepted ADR is a new ADR that supersedes it; the old text is not edited beyond
its status line.

5. **Close out.** `task devhost:verify`, then as in `/close-session`.

## Why

The backlog is for finding decisions; the ADR is for trusting them later. Writing the losing
options down is what stops the same debate from recurring when the person who remembers it is
unavailable.
90 changes: 90 additions & 0 deletions .claude/skills/night-shift/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
name: night-shift
description: "Close up for the day and work an agreed list from TODO.md alone overnight, in the session the Operator leaves open, then walk them through it in the morning. Use it when the Operator says they are leaving - 'night shift', 'closing up', 'I'm heading out, need anything?', 'ending my day', 'work through these while I'm away', 'run the list overnight' - and when they come back and ask 'morning report', 'what happened overnight', 'what did you get done'. The main session only; never a separately launched background agent."
---

# Night shift

The Operator leaves; the main session keeps working, in the same session, on a list they
agreed, under stricter rules than the day; they review it in the morning. The night's work is a
branch the Operator keeps or reverts commit by commit, and nothing leaves the devhost.

It runs in this session, in auto mode: the terminal stays open and the workstation awake. No
separate unattended agent is launched. Cons (subagents briefed for one job) may be used inside
the session, within the cap, in a worktree when they change shared tooling.

## 1. Closing up (with the Operator, a few minutes)

1. **Need anything?** First list what you need from them before they go: the open decisions
that block an item you could otherwise do tonight, each with your recommendation, and anything
only they can do (a login; switching on auto mode; a file only they may write).
2. **Propose tonight's list** from `TODO.md`: only items that need no decision from the Operator,
are bounded, can be undone, and can be proven by a test, a simulation or the checks. One line
each: what "done" will mean, and what it will not touch. Leave out anything under "Decisions
for the Operator", anything outward-facing (deploys, mail, services), and changes to
permissions or hooks.
3. **Agree it.** The Operator strikes, adds, reorders. Default cap **$10** at list price for the
night (they may change it); default stop time **07:00** local. An item they did not agree is
not worked, however easy it looks.
4. **Write the plan** into `docs/night-shift/YYYY-MM-DD.md` (the shape in
`docs/night-shift/README.md`): the items in order with their done-checks, the cap, the stop
time and the start time in UTC. Cut the night's branch from the branch the day ended on:
`git switch -c chore/night-shift-YYYY-MM-DD`, and commit the plan as its first commit, so the
whole night can be undone.
5. **Pre-flight check**, before they go; say any failure at once:
- the session is in auto mode; if not, ask them to switch, since one permission prompt stalls
the night;
- `devhost-verify` and the repository's checks pass, so a failure overnight is tonight's;
- nothing uncommitted besides the backs' latest writes;
- `devhost-costs` noted in the plan as the starting figure;
- they know to leave the terminal open and the workstation awake (sleep pauses the container).
6. Say "Night shift started" in one line, and begin.

## 2. The night rules

- **One item at a time, in plan order.** Build it the way the day would, with the test that
proves it; run the checks; commit that item alone, with a Conventional Commit naming its id.
If the check fails and a short fix does not make it pass, revert the item (`git checkout -- .`
before the commit, `git revert` after) and mark it `undone`. Never carry a failure into the
next item.
- **Never decide for the Operator.** A question, a real choice between alternatives, or anything
`TODO.md` gives to the Operator: write it under Questions in the report with your
recommendation, and skip or finish the item under a stated assumption only if the assumption is
cheap to reverse.
- **Nothing leaves the devhost.** No push, no pull request, no deploy, no mail, no webhook beyond
the fakes, no artifacts, links or messages to any service beyond the model itself.
- **Nothing irreversible.** No history rewrites, no deleting files the night did not create, no
changes to `.claude/settings.json`, hooks or permissions, no `--no-verify`.
- **No new skills, no new directions.** A skill, a decision or a new direction that seems needed
goes in the report as a proposal.
- **Keep to the cap.** Run `devhost-costs --since <start time>` after each item. If the next
item would likely pass the cap, stop there. Stop at the stop time too.
- **Write the report as you go**, after each item, not at the end, so a stop at any point leaves
a true record. The backs keep working after each turn, as in the day; read their changes
before each commit.
- When the list is done, or a rule stops you, finish the report, commit it, and stop. Do not
start work that is not on the plan.

## 3. The plan and report file

`docs/night-shift/YYYY-MM-DD.md`, one file, committed on the night's branch, in the shape
`docs/night-shift/README.md` gives. The scribe writes the night's ledger entries as usual; the
report is the walk-through, the ledger the record.

## 4. Morning

The briefing shows a night-shift report without a "Reviewed" line. When the Operator says
"morning report" (or asks what happened):

1. Walk through it: one line per item, then the questions and proposals.
2. For each item they keep or reject: revert the rejected ones on the branch (`git revert
<commit>`, so the history says what was tried), and say what is back as it was.
3. Add `Reviewed by the Operator <date>.` as the report's third line and commit it.
4. Then the branch goes the normal way: `/close-session`, a pull request when they ask.

## Why

Unattended work is only safe when the rules are stricter than the day's: an agreed list, one
reversible commit per item with the checks green, nothing sent, nothing decided, a cap measured
from the session's own transcripts, and a report written as it goes. The branch is the sandbox
and the morning review is a set of commits the Operator keeps or reverts one by one.
24 changes: 24 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"features": {
"ghcr.io/devcontainers-extra/features/shellcheck:1": {
"version": "1.1.0",
"resolved": "ghcr.io/devcontainers-extra/features/shellcheck@sha256:8e6d050e4ead6a0350dbe4c70611e351f32cb61a8cc5cb2b39da0cf29ff3bed5",
"integrity": "sha256:8e6d050e4ead6a0350dbe4c70611e351f32cb61a8cc5cb2b39da0cf29ff3bed5"
},
"ghcr.io/devcontainers-extra/features/yamllint:2": {
"version": "2.0.18",
"resolved": "ghcr.io/devcontainers-extra/features/yamllint@sha256:c3ed260f8e4f026d2ae93ae61581d9a8c28d64950a4e801ac33b968566e6c16e",
"integrity": "sha256:c3ed260f8e4f026d2ae93ae61581d9a8c28d64950a4e801ac33b968566e6c16e"
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "2.17.0",
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c",
"integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c"
},
"ghcr.io/devcontainers/features/powershell:1": {
"version": "1.5.1",
"resolved": "ghcr.io/devcontainers/features/powershell@sha256:df7baa89598c93bfd15808641d9ec9eb03e0ccdf52e5de4cbbce9ab2d9755d18",
"integrity": "sha256:df7baa89598c93bfd15808641d9ec9eb03e0ccdf52e5de4cbbce9ab2d9755d18"
}
}
}
Loading
Loading