I1984 — Knowledge candidates never leave untracked files on a trunk that only pull requests change
Decide and implement where knowledge candidates are written so that deriving them at an episode boundary on the trunk never leaves the trunk's working tree dirty.
DONE wave 0 · p1 · deep-work profile · parallel safe
Objective
Decide and implement where knowledge candidates are written so that deriving them at an episode boundary on the trunk never leaves the trunk's working tree dirty.
Why
OSCILLA main carries untracked .ai/repo/knowledge/candidates/ (a README and 7 records). It can never commit them, because its main changes only through pull requests. Every checkpoint since records working_tree dirty, clean-tree release gates refuse, and the advisory rule candidates-reviewed asks for the very commit the process forbids.
Current state
Slice 1 of the ADR 0091 amendment (2026-10-15): on the trunk (mj_on_trunk, lib/common.sh) session close and recovery (lib/session.sh, lib/recover.sh) and knowledge derive (lib/knowledge.sh) write to .ai/local/state/outbox/{sessions,candidates}/, and context and doctor name a non-empty outbox; case 3060. Slice 2: a session close off the trunk (mj_session_outbox_drain, lib/session.sh) moves the outbox into the tracked sections unchanged and exactly once, and leaves a file that is not a record in the outbox with a line on stderr; case 3063. Slice 3: docs/KNOWLEDGE.md, the candidates-reviewed rule text (share/standard/majordomus/rules, vendored) and the sessions README (tracked and skeleton) say where a trunk episode's records wait, when a branch carries them, what context and doctor say meanwhile, and what happens to a file in the outbox that is not a record.
Desired state
Candidates derived on the trunk are staged under .ai/local, or derivation is skipped there, until a branch promotes them. The decision is recorded against ADR 0091.
Scope
- lib/knowledge.sh
- lib/capture.sh
- share/standard/majordomus/rules
- docs/KNOWLEDGE.md
- .ai/repo/adrs
- test/cases
Dependencies
None. This issue is a root of the graph.
What waits on this
Acceptance criteria
- Closing an episode on the trunk leaves `git status --porcelain` empty
- Candidates derived on a branch are still offered for review and promotion as today
Validation
- bin/majordomus plan validate
- MJ_TEST_JOBS=4 bash test/run.sh <the case this issue adds>
Evidence required
- trunk_stays_clean_case
- decision_recorded
Evidence
| covers | type | command | result | at commit |
|---|---|---|---|---|
| decision_recorded | artifact | decided 2026-10-15: trunk episodes stage records in .ai/local/state/outbox, the next branch episode moves them into the tracked sections; ADR 0091 amendment names three slices | c0e3585 | |
| trunk_stays_clean_case | test | MJ_TEST_JOBS=4 bash test/run.sh 3060_trunk_stays_clean | 1 passed, 0 failed (red on a53f08f11b: the close left .ai/repo/sessions/ and .ai/repo/knowledge/candidates/ untracked on main) | a53f08f |
Timeline
- started
- 2026-10-15T11:20:46Z
- verified
- —
- completed
- 2026-10-15T11:21:05Z
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I1984.yaml. Read it back with majordomus plan show I1984.