docs: handoff-80 + docs direct-push carve-out (ADR-0059 Amendment 1)
Session handoff covering the clause-concept-hints feature (ADR-0058, #42) and the working-method establishment (ADR-0059, #41; fixes #43/#44). Records the docs direct-push carve-out: handoff/session docs and small docs amendments are owner-direct-pushed to main, because a docs-only PR posts no ci/gate run (paths-ignored) and stalls on the required check. Amends CLAUDE.md, ADR-0059 (Amendment 1), and its README index row.
This commit is contained in:
@@ -190,3 +190,26 @@ test the script but not run its pushing path.
|
||||
- **Automating PR creation/merge** — humans push and merge (D6).
|
||||
- **A CONTRIBUTING-side description of the reserve lock** — it's maintainer
|
||||
infrastructure, not contributor guidance (kept here instead).
|
||||
|
||||
## Amendment 1 (2026-06-25): docs direct-push carve-out
|
||||
|
||||
Extends the D5 owner-whitelist: **handoff / session docs (and small docs
|
||||
amendments like this one) are owner-direct-pushed to `main`, not PR'd.**
|
||||
|
||||
Discovered while preparing the first handoff under this flow: a **docs-only
|
||||
PR cannot merge** under the protection rules. `ci.yaml` `paths-ignore`s
|
||||
`docs/**` and `**/*.md`, so a docs-only change posts **no `ci / gate` run**;
|
||||
but D5 requires `ci / gate*` before merge — so the required check never
|
||||
arrives and the PR stalls on "expected/waiting". Rather than weaken the gate
|
||||
or add CI machinery, this trivial low-risk class (handoffs, session notes,
|
||||
small docs fixes) rides the existing owner-direct-push carve-out: the owner
|
||||
is already whitelisted, and a docs-only push to `main` is itself
|
||||
`paths-ignore`d, so it burns no CI.
|
||||
|
||||
Substantive changes — code, and the ADRs/docs that accompany code — still go
|
||||
through a PR as normal (their non-docs files trigger the gate). **If
|
||||
docs-via-PR is ever wanted** (e.g. a docs-only ADR through review), the clean
|
||||
fix is a "skipped → success" gate shim (a job that reports `ci / gate`
|
||||
success when the real gate is path-skipped) or dropping the docs
|
||||
`paths-ignore`; until then, direct-push is the sanctioned path for docs-only
|
||||
changes.
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,144 @@
|
||||
# Session handoff — 2026-06-25 (80)
|
||||
|
||||
A long session. It began as the next open-issue item — **#37, clause-concept
|
||||
hints** — but the act of cutting a branch for it surfaced that this
|
||||
now-public repo had **no written, trackable working method**. So the bulk of
|
||||
the session became establishing one (**ADR-0059**) and hardening it through
|
||||
real use, with two follow-up fixes the dogfooding turned up. Both arcs are
|
||||
fully merged; the tree is clean.
|
||||
|
||||
## §1. State
|
||||
|
||||
**Branch `main` at `78272e2`.** Everything below is merged; **no open PRs**;
|
||||
worktrees are just the primary (`main`) + the long-lived `website`. All
|
||||
feature/fix worktrees were cleaned up with `wt-rm`.
|
||||
|
||||
**Suite green at #37's merge:** **1831 lib + 8 e2e_pty + 503 it + 200 typing
|
||||
(2542 total), 0 failed, 1 ignored**; `fmt --check` + `clippy -D warnings`
|
||||
clean (via `nix develop -c`). The new workflow scripts carry their own
|
||||
local-`origin` harnesses: `test-adr-reserve.sh` **10/10**, `test-wt.sh`
|
||||
**16/16**, all `shellcheck`-clean.
|
||||
|
||||
**Issues:** closed this session — **#37** (done, ADR-0058) and **#38**
|
||||
(won't-do, see §4). Still open — **#40** (winget release notes, deferred to
|
||||
next release; see §4). (#36/#39 were closed in earlier sessions.)
|
||||
|
||||
## §2. What shipped — #37 clause-concept hints (ADR-0058, merged #42)
|
||||
|
||||
The deferred ADR-0053 extension: a tier-3 **`hint.concept.*`** layer shown by
|
||||
**F1** when the cursor sits **inside a recognized clause**, layered under the
|
||||
per-form `hint.cmd.*` block. Seven topics — referential actions, `1:n`/`m:n`
|
||||
cardinality, primary key, unique, check, foreign key.
|
||||
|
||||
- **Mechanism:** a new transparent `Node::Concept { topic, inner }` grammar
|
||||
wrapper records the clause's byte span into `WalkContext::concept_spans`
|
||||
(**append-only — survives the clause being fully matched**, unlike
|
||||
`pending_hint_mode` which clears on match and so only knows the slot
|
||||
boundary). `concept_topic_at_cursor` walks the full buffer and returns the
|
||||
**innermost** containing span. No use of the dormant `WalkBound::Position`.
|
||||
- **Two user forks:** detection = "anywhere inside the clause"; **all four
|
||||
clause families** in v1. **Mode-keyed examples** (`example.simple` /
|
||||
`example.advanced`) honour ADR-0053 D6 for topics reachable in both modes;
|
||||
`emit_tier3_block` picks by live mode.
|
||||
- **`/runda` caught two design gaps before any code** (clause map missed the
|
||||
simple-mode constraint suffix; single-`example` model collided with D6) —
|
||||
both fixed. **Comprehensiveness gate**: a recursive `Node::Concept` visitor
|
||||
cross-checks grammar wrappers ↔ `CONCEPT_TOPICS` ↔ catalogue blocks.
|
||||
- 21 new tests (14 resolver, 3 gates, 3 F1 integration, 1 snapshot).
|
||||
|
||||
## §3. The working method (ADR-0059, merged #41; fixes #43, #44)
|
||||
|
||||
The session's main artifact — the trackable flow for the public repo:
|
||||
|
||||
- **PRs onto a protected `main`** (always-green; one direct-push carve-out,
|
||||
§4), one logical change per branch, conventional prefixes, the `/runda`/DA
|
||||
review pasted into each PR. **Merge commits (`--no-ff`)**; never
|
||||
rebase/squash (append-only).
|
||||
- **One worktree per branch** (`<repo>-worktree-<segment>`) — never switch the
|
||||
primary checkout. `scripts/wt-new.sh <branch>` (off `origin/main`,
|
||||
`--no-track`) / `scripts/wt-rm.sh <branch>` (removes only the **named**
|
||||
worktree).
|
||||
- **Reserve-first ADR numbering** — `scripts/adr-reserve.sh <slug>`. The fix
|
||||
for the real collision problem: a contiguous integer needs an allocator and
|
||||
plain git branches have none, so **`main` is the registry and an atomic
|
||||
`git push` is the lock** (compare-and-swap, retried on contention),
|
||||
recorded in the append-only ledger **`docs/adr/RESERVATIONS.log`**. The
|
||||
number is **stable from creation** (safe in immutable commit messages +
|
||||
cross-refs). Supersedes ADR-0000's placeholder-until-merge default;
|
||||
subproject namespaces (`ADR-website/ci-NNN`) unchanged.
|
||||
- **Branch protection** (you applied in Gitea): require PR + the `ci / gate*`
|
||||
check + up-to-date-before-merge; **owner whitelisted for direct push** (the
|
||||
reservation ledger line, now also handoff/session docs — §4).
|
||||
- **Fixes found by dogfooding:**
|
||||
- **#43** — `wt-clean` (auto-sweep of all merged worktrees) → explicit
|
||||
**`wt-rm <branch>`**. The auto-sweep would have deleted long-lived
|
||||
branches (`website`, `ci`) since they're merged into `main` too. Also
|
||||
**`wt-new --no-track`**: branching off `origin/main` had set the new
|
||||
branch's upstream to `origin/main`, so a bare `git push` errored on a
|
||||
name-mismatch and suggested the dangerous `HEAD:main`.
|
||||
- **#44** — CI **dedupe**: `push: branches: [main]` (was `['**']`) so a
|
||||
push to a PR'd branch no longer runs the gate twice. On **Gitea** the
|
||||
`push` and `pull_request` runs were byte-identical — Gitea has **no
|
||||
merge-preview ref**; its `pull_request` checks out `refs/pull/N/head`, the
|
||||
same commit a branch push would (`docs.gitea.com/usage/actions/faq`).
|
||||
Keeping the gate on `pull_request` is forward-compatible: if Gitea ever
|
||||
adds the merge ref, the runs upgrade to testing the merged result for free.
|
||||
|
||||
## §4. Decisions
|
||||
|
||||
- **#38 closed — won't build** the pre-submit-diagnostic tier-3 route. The
|
||||
ADR-0053 D6 deferral reasons still hold: `Diagnostic` carries no class key
|
||||
(a class field would have to thread through every diagnostic-creation
|
||||
site — broad change) for marginal value (tier-2 already surfaces
|
||||
diagnostics live; many classes duplicate the runtime-error/clause-concept
|
||||
tiers). Reconsider only if a diagnostic class has genuinely unique teaching
|
||||
value. Rationale recorded on the issue.
|
||||
- **#40 deferred** (open): wire `CHANGELOG` into komac's winget
|
||||
`--release-notes-url`. Best coupled to the **next `v*` release + first real
|
||||
winget *update* test** — the initial winget PR to `microsoft/winget-pkgs`
|
||||
is still unconfirmed after several days, so end-to-end validation needs a
|
||||
confirmed package first.
|
||||
- **Docs direct-push carve-out** (this handoff is the first to use it):
|
||||
handoff / session docs (and the reservation ledger) are **owner
|
||||
direct-pushed to `main`**, not PR'd. See §5 for *why* a PR doesn't work.
|
||||
|
||||
## §5. Process lessons (now in ADR-0059 / CLAUDE.md)
|
||||
|
||||
- **Update a branch in ONE lane** — locally (`git fetch && git merge
|
||||
origin/main`), **not** the Gitea "Update branch" button when a conflict is
|
||||
possible. The button silently mis-resolved the README clash on #42
|
||||
(dropped the `0059` index row) and, combined with a local merge, diverged
|
||||
the PR branch; healed with an append-only merge (no force-push).
|
||||
- **Primary checkout rests on `main`; feature work in worktrees.** Mid-session
|
||||
the primary was stuck on `feat` (bootstrap artifact), which is what made
|
||||
worktree cleanup awkward — there was no `main` checkout holding the
|
||||
scripts. Resolved by switching the primary to `main` and moving `feat` to a
|
||||
worktree.
|
||||
- **Docs-only PRs are blocked by the required gate.** `paths-ignore`
|
||||
(`docs/**`, `**/*.md`) means a docs-only change posts **no `ci / gate`
|
||||
run**, and branch protection requires `ci / gate*` — so the required check
|
||||
never arrives and the PR is stuck "expected/waiting." That is the concrete
|
||||
reason handoff/session docs are direct-pushed (§4). If docs-via-PR is ever
|
||||
wanted, add a "skipped → success" gate shim (or drop the paths-ignore).
|
||||
- **Gitea CI specifics worth remembering:** no merge-preview ref (above); the
|
||||
reserve script's CAS via atomic push; `--no-track` on branch creation to
|
||||
avoid the inherited-`origin/main` upstream.
|
||||
|
||||
## §6. Next
|
||||
|
||||
- **Next session is free to pick a feature** — no specific item is queued;
|
||||
consult `docs/requirements.md` for the remaining backlog (e.g. **TT4 /
|
||||
Tier-4-in-CI** still not wired; **D3 packaging** — winget pending
|
||||
confirmation; the larger deferred UX items: tutorial system, session-log +
|
||||
markdown export V4, multi-line input I1, ER-diagram export V3).
|
||||
- **#40** when the next release happens (with the first winget update test).
|
||||
- **Use the new flow:** `wt-new` to start a branch, `adr-reserve` the moment
|
||||
an ADR is needed, PR onto `main`, `wt-rm` when done. Push/merge stay your
|
||||
steps; agents prepare but never push.
|
||||
|
||||
## §7. Process pins
|
||||
|
||||
- Commits user-confirmed, no AI attribution, append-only. **Push/merge are
|
||||
the user's steps.** This handoff + the §4 carve-out doc amendments are
|
||||
direct-pushed to `main` by the owner (docs-only, paths-ignored,
|
||||
owner-whitelisted).
|
||||
Reference in New Issue
Block a user