Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
118 changes: 118 additions & 0 deletions .claude/skills/_ctx-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
name: _ctx-pr
description: "Scaffold a pull-request body from the current branch's commits, Spec: trailers, and closed TASKS into gitignored inbox/ for the human to paste. Use when preparing or opening a PR for a ctx branch. Never pushes and never creates the PR."
---

Draft a ready-to-paste PR body from what the branch actually
contains — its commits, the specs those commits cite, and the
TASKS it closed. Write it to `inbox/` (gitignored) for the human
to review and paste into the PR. **This skill never runs
`git push`, `gh pr create`, or any remote operation.** It only
writes a local file; the human opens the PR.

## When to Use

- Preparing or opening a PR for a feature/fix branch
- The user says "draft a PR", "write the PR body", "/_ctx-pr"
- Wrapping a branch and you want the narrative assembled from
the real commits rather than hand-written

## When NOT to Use

- Work was committed straight to `main` (no branch to describe —
`<base>..HEAD` is empty; say so and stop)
- The user wants the PR actually pushed/created — that is the
human's job; this skill drafts text only
- Mid-branch, before the commits are final

## Before Running

1. Confirm the branch and base. Base is `main` unless the user
names another. Current branch: `git rev-parse --abbrev-ref HEAD`.
2. Confirm there are commits to describe:
`git rev-list --count <base>..HEAD`. If `0`, tell the user the
branch has no commits over `<base>` and stop — do not fabricate
a PR body.

## Gather (all derived — no guessing)

Run these and read the output; do not summarize from memory:

- **Commits, oldest first**, with full bodies:
`git log --reverse --format='%H%n%s%n%b%n==END==' <base>..HEAD`
- **Specs cited** — the `Spec:` trailer of each commit, deduped in
first-seen order:
`git log --reverse --format='%(trailers:key=Spec,valueonly)' <base>..HEAD | sed '/^$/d' | sort -u`
Every commit should have one (CONSTITUTION); if any lacks one
(blank trailer output for that commit), note the gap rather than
inventing a spec.
- **Closed tasks** — what this branch flipped `[ ]`→`[x]`:
`git diff <base>..HEAD -- .context/TASKS.md` and read the added
`- [x]` / `DONE` lines.
- **Verification** — pull any lint/test/audit or end-to-end drive
notes out of the commit bodies; do not claim checks that the
commits don't evidence.

## Write the PR body

Write to `inbox/pr-<branch-slug>-<UTCstamp>.md` where `<UTCstamp>`
is `date -u +%Y%m%dT%H%M%SZ`. Use this shape:

```markdown
# <imperative title synthesized from the commits, <= ~70 chars>

## Summary

<2-4 sentences: what the branch does and why. Ground it in the
commit subjects/bodies, not aspiration.>

## Changes

- <grouped bullet, by commit or theme> — serves `specs/<name>.md`
- <...>

## Specs

- `specs/<name>.md` — <one-line what it designs>
- <deduped, first-seen order>

## Closed tasks

- <TASKS item marked done on this branch>
- <...> (omit the section if none)

## Verification

- <lint/test/audit result, end-to-end drive — only what the
commits actually evidence>
```

## Hard constraints — self-check before finishing

Re-read the drafted file and confirm ALL of these. If any fails,
fix the file before reporting done:

- [ ] No `Co-Authored-By:` anywhere in the body
- [ ] No agent/tool sign-off and no "Generated with…" / "🤖"
footer (CONSTITUTION "Process Invariants" — same rule
`ctx-commit` enforces, applied to the PR narrative)
- [ ] Every `Changes` bullet ties to a spec listed in `Specs`
- [ ] `Closed tasks` entries actually appear as `[x]`/`DONE` in
the branch's TASKS diff (no aspirational closes)
- [ ] `Verification` claims are backed by the commit bodies
- [ ] The file is under `inbox/` (gitignored) — never committed,
never a tracked path
- [ ] No `git push` / `gh pr create` was run

## After Writing

Tell the user the file path and that it is theirs to paste — you
did not push or open anything. Offer to adjust tone or length.

## Usage Examples

```text
/_ctx-pr
/_ctx-pr (base develop)
/_ctx-pr (after finishing the ceremony-nudge branch)
```
40 changes: 40 additions & 0 deletions .context/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,46 @@ For significant decisions:

-->

## [2026-07-15-000000] Live ceremony credit reuses the daily throttle marker, suppressing the day's other ceremony nudge

**Status**: Accepted

**Context**: The `check-ceremony` hook nudges the operator to open
sessions with `/ctx-remember` and close them with `/ctx-wrap-up`. It was
journal-driven only, so it self-nudged on the very prompt that ran a
ceremony and kept nudging until the session was journal-imported. The
fix (specs/ceremony-nudge-live-session.md) parses the live prompt and,
when it is a ceremony command, credits it immediately. The question was
*how* to record that live credit.

**Alternatives Considered**:
- Reuse the existing per-day throttle marker (`ceremony-reminded`):
touching it on a live ceremony credits the session and settles the
ceremony question for the day. Pros: zero new state; one guard;
matches the check's existing once-per-day cadence. Cons: crediting a
live `/ctx-remember` also suppresses a would-be `/ctx-wrap-up` nudge
for the rest of that day (and vice-versa).
- Per-ceremony live markers (separate remember/wrap-up credit): Pros:
the other ceremony can still nudge the same day. Cons: new state files,
a second throttle axis, and more moving parts for a coarse daily nudge.

**Decision**: Reuse the single daily throttle marker. On a live ceremony
prompt, `check-ceremony` touches `ceremony-reminded` and returns without
nudging.

**Rationale**: The check is a deliberately coarse daily cadence, not a
per-ceremony ledger. An operator actively running one ceremony does not
need to be nagged about the other on that same prompt, and the marker's
"settled for today" semantics already express exactly that. The extra
state a per-ceremony scheme buys is not worth it for a once-a-day hint.

**Consequence**: Running either ceremony live suppresses both ceremony
nudges for the rest of that day. This is intended; the trade-off is
documented in the spec's Trade-off section. If a per-ceremony cadence is
ever wanted, this is the decision to revisit.

**Related**: See spec specs/ceremony-nudge-live-session.md.

## [2026-07-04-152957] Statusline informs, never gates

**Status**: Accepted
Expand Down
20 changes: 20 additions & 0 deletions .context/LEARNINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,26 @@ DO NOT UPDATE FOR:
-->


---

## [2026-07-15-141749] Carving one feature out of a working tree that also holds an unrelated in-progress feature needs hunk-level staging + an isolation-gate

**Context**: The tree mixed a computed-index feature, a stale local copy of a contributor's hub PR (#134), and a gosec-hardening effort — interleaved even within shared files (commands.yaml, errors.yaml, .context/*). Needed to commit ONE of them cleanly. Interactive 'git add -p' isn't available headless.

**Lesson**: Whole-file 'git add' bundles the other feature; naive per-file staging silently drops shared-file edits and forgets coupled files. The reliable method: (1) safety-checkpoint the whole tree to a throwaway branch first; (2) stage pure-mine files + apply only your hunks to mixed files via 'git diff HEAD -- f | filter-hunks | git apply --cached'; (3) ISOLATION-GATE: 'git stash --keep-index -u' then run full build+lint+test on the staged-only tree.

**Application**: Always run the isolation-gate before committing a carve — it caught 5 unstaged files (orphaned DescKeys would've broken the build alone) and a half-done env.go fix that a whole-tree build masked. A green full-tree build does NOT prove the carved subset is self-consistent; only building the stashed-down index does.

---

## [2026-07-15-141726] gosec G101 has two independent triggers: identifier-keyword match and value-entropy

**Context**: Removed the blanket G101 path-exclusion for internal/config/embed/text/; gosec then flagged 3 lines. Two were identifier matches (DescKeyErrHubGenerateToken, ...AdminTokenRequired — 'token' substring in the name), but the third flagged only sourcemap.write-row out of 8 identical *WriteRow consts.

**Lesson**: G101 matches on (a) the variable/const IDENTIFIER containing a credential keyword (token/pass/pwd/secret/cred/apiKey — case-insensitive substring), AND (b) a Shannon-entropy heuristic on the string VALUE. The single sourcemap hit was entropy, not name — which is why 7 sibling *WriteRow consts weren't flagged.

**Application**: Fix each trigger at the source, never with #nosec or a path exclusion: for a name-match, rename the identifier off the keyword (keep the value/i18n-key/env-var intact so linkage/behavior are unchanged); for an entropy hit, change the value (e.g. write-row->append-row). Confirm empirically: renaming the identifier while keeping the value clears a name-match, proving it wasn't value-based.

---

## [2026-07-06-214523] git filter-branch leaves the originals in refs/original and the reflog
Expand Down
54 changes: 48 additions & 6 deletions .context/TASKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2509,7 +2509,16 @@ DR-kb session a5736210 closeouts under
directly update the docs whenever it makes sense.
- [ ] Human: Do a documentation audit for AI-generated artifacts. #important
#not-urgent
- [ ] Human: test `ctx init` on a fresh ubuntu install.
- [x] Human: test `ctx init` on a fresh ubuntu install.
DONE 2026-07-15 (session 87e465a0). This machine is bare-metal fresh
Ubuntu; ctx 0.8.1 installed at /usr/local/bin/ctx. Smoke-tested in a
throwaway temp git repo: `ctx init` created all 9 canonical files +
steering + kb scaffold + templates, wired .claude/settings.local.json
(plugin enabled, statusline), CLAUDE.md, Makefile, and 9 .gitignore
entries; detected the Claude plugin (0.8.1, hot-reload). Follow-on
`ctx status` (9 files, 22 invariants), `ctx agent` (packet rendered,
unfilled steering tombstones correctly skipped), and `ctx drift`
(11 checks PASSED, no drift) all clean. Temp repo removed.
- [ ] Human: These shall be done before a release cut. Especially when the
amount of code generated is around hundreds of thousands of lines of code,
we need to sit down and spend as much time as needed. For two reasons:
Expand Down Expand Up @@ -2620,19 +2629,52 @@ shipped.

- [x] [Epic A] ctx index: rename internal/index→internal/heading + generic ATX heading matcher (T01-T04). Plan: specs/plans/computed-index-projection.md #session:75be038e #branch:main #commit:f382bee7 #added:2026-07-14-054851

- [ ] ctx-remember nudge live-credit: the check-ceremony nudge is journal-driven (ScanJournalsForCeremonies over recent IMPORTED journals), so it can't credit the current live session's /ctx-remember and misfires until the session is imported. Have the /ctx-remember skill (or ctx) touch the ceremony throttle/marker when it runs live, so the signal reflects the current session instead of waiting for journal import. See internal/cli/system/cmd/checkceremony/run.go (remindedFile/ThrottleID) #session:75be038e #branch:main #commit:f382bee7 #added:2026-07-13-220031

- [ ] ctx-remember nudge self-suppress: the check-ceremony hook fires the 'try starting with /ctx-remember' relay even on the prompt that IS /ctx-remember, because entity.HookInput doesn't parse the UserPromptSubmit 'prompt' field (only session_id + tool_input.command). Add Prompt to HookInput and skip the ceremony nudge when the prompt starts with /ctx-remember or /ctx:ctx-remember. See internal/cli/system/cmd/checkceremony/run.go + internal/entity/hook.go #session:75be038e #branch:main #commit:f382bee7 #added:2026-07-13-220031
- [x] ctx-remember nudge live-credit: the check-ceremony nudge is journal-driven (ScanJournalsForCeremonies over recent IMPORTED journals), so it can't credit the current live session's /ctx-remember and misfires until the session is imported. Have the /ctx-remember skill (or ctx) touch the ceremony throttle/marker when it runs live, so the signal reflects the current session instead of waiting for journal import. See internal/cli/system/cmd/checkceremony/run.go (remindedFile/ThrottleID) #session:75be038e #branch:main #commit:f382bee7 #added:2026-07-13-220031
DONE 2026-07-15 (session 87e465a0). Fixed in ctx itself (not the skill):
checkceremony.Run now parses the live prompt and, when it IS a ceremony
command, touches the daily marker (credits the live session) — no more
journal-import lag. Unified with the self-suppress fix below via
ceremony.InvokedByPrompt. Verified end-to-end against the built binary.
Spec: specs/ceremony-nudge-live-session.md.

- [x] ctx-remember nudge self-suppress: the check-ceremony hook fires the 'try starting with /ctx-remember' relay even on the prompt that IS /ctx-remember, because entity.HookInput doesn't parse the UserPromptSubmit 'prompt' field (only session_id + tool_input.command). Add Prompt to HookInput and skip the ceremony nudge when the prompt starts with /ctx-remember or /ctx:ctx-remember. See internal/cli/system/cmd/checkceremony/run.go + internal/entity/hook.go #session:75be038e #branch:main #commit:f382bee7 #added:2026-07-13-220031
DONE 2026-07-15 (session 87e465a0). Added Prompt (json:"prompt") to
entity.HookInput; checkceremony.Run now returns without nudging when the
live prompt is a ceremony command (ceremony.InvokedByPrompt matches the
first token against the bare /ctx-remember|/ctx-wrap-up and plugin
/ctx:ctx-remember|/ctx:ctx-wrap-up forms — first-token equality, so
/ctx-remembering and prose mentions don't match). Verified end-to-end:
bare + plugin forms suppress, normal prompt still nudges. Tests:
ceremony_test.go (12 cases) + checkceremony/run_test.go. Spec:
specs/ceremony-nudge-live-session.md.

- [ ] ctx list/search: richer query surface over knowledge files (filtering, full-text) layered on top of the thin `ctx index` heading-projector — successor to the queued 'CLI-projected list/search' idea; index ships first as the projection primitive #session:75be038e #branch:main #commit:f382bee7 #added:2026-07-13-215523

- [ ] Re-sign the release tags (v0.1.0 through v0.8.0 and latest): the 2026-07-06 DCO history rewrite stripped their GPG signatures when the tagged commits changed SHA. #session:2cff382a #branch:fix/jumbo-diff-review-fixes #commit:945850af #added:2026-07-06-214523

- [ ] Create a /ctx-pr skill: scaffold a PR body from the branch's commits, Spec: trailers, and closed TASKS, written to inbox/ (gitignored) for the user to paste. MUST enforce the no-agent-signoff convention: no 'Co-Authored-By' and no 'Generated with ...' footer, per CONSTITUTION Process Invariants. #session:2cff382a #branch:fix/jumbo-diff-review-fixes #commit:945850af #added:2026-07-06-213149
- [x] Create a /ctx-pr skill: scaffold a PR body from the branch's commits, Spec: trailers, and closed TASKS, written to inbox/ (gitignored) for the user to paste. MUST enforce the no-agent-signoff convention: no 'Co-Authored-By' and no 'Generated with ...' footer, per CONSTITUTION Process Invariants. #session:2cff382a #branch:fix/jumbo-diff-review-fixes #commit:945850af #added:2026-07-06-213149
DONE 2026-07-15 (session 87e465a0). Shipped as REPO-INTERNAL _ctx-pr
(.claude/skills/_ctx-pr/SKILL.md, `_` prefix = not bundled in the plugin;
chosen over a shipped ctx-pr because it hard-enforces ctx's own CONSTITUTION
conventions + writes to the ctx-repo inbox/). Derives the body from
git log <base>..HEAD (subjects/bodies/Spec: trailers), the deduped specs,
and the [ ]→[x] TASKS diff; writes inbox/pr-<branch>-<UTCstamp>.md. Hard
constraints in a self-check block: no Co-Authored-By / agent sign-off /
"Generated with…" footer, no git push / gh pr create, empty base..HEAD
refuses to fabricate. Spec: specs/ctx-pr-skill.md.

- [ ] New orchestrator skill /ctx-architecture-deep-dive: wrap the three-pass architecture arc (/ctx-architecture principal → /ctx-architecture-enrich → /ctx-architecture-failure-analysis) plus the synthesis step (milestone-readiness note → /ctx-task-out --milestone <next>) into one parameterized skill with machine-checkable preconditions (code-intel MCP actually serving the repo, index fresh vs HEAD, synced tree, fresh session). Prior art: zhc/os docs/runbooks/architecture-deep-dive.md — a runbook whose pasted prompt rotted within ONE milestone (needed a 'Historical' banner because it hard-codes milestone facts like 'M0b is untasked'); a skill that derives milestone state from specs/plans/ at runtime doesn't rot. The site recipe architecture-deep-dive documents the arc as prose — this skill would be its ceremony (see the 'unceremonied pipeline step' learning). os prototypes a project-local version first and folds lessons back here. #priority:medium #session:6c276362 #branch:main #commit:a0e5cbf9 #added:2026-07-04-210547

- [ ] Skill assets hard-code `npx gitnexus analyze` as the stale-index remedy, but on hosts where GitNexus runs via Docker (tree-sitter@0.21.1 native addon vs Node 24 ABI — no arm64 prebuilt) that command is a silent no-op; os/GITNEXUS.md documents this and both os and ctx expose `make gitnexus-index` → hack|scripts/gitnexus-index.sh instead. Fix the suggestion to be project-aware: point at the repo-local indexing entry point (a `gitnexus-index` make target, an indexing script, or the repo's GITNEXUS.md instructions) and fall back to `npx gitnexus analyze` only when nothing repo-local exists. Sites: internal/assets/claude/skills/ctx-remember/SKILL.md:156, internal/assets/integrations/copilot-cli/skills/ctx-remember/SKILL.md:155, internal/assets/claude/skills/ctx-architecture-enrich/SKILL.md:34+112+130. Found live: /ctx-remember in the os project emitted the broken npx suggestion while the working `make gitnexus-index` existed one directory over. #priority:medium #session:6c276362 #branch:main #commit:a0e5cbf9 #added:2026-07-04-205437
- [x] Skill assets hard-code `npx gitnexus analyze` as the stale-index remedy, but on hosts where GitNexus runs via Docker (tree-sitter@0.21.1 native addon vs Node 24 ABI — no arm64 prebuilt) that command is a silent no-op; os/GITNEXUS.md documents this and both os and ctx expose `make gitnexus-index` → hack|scripts/gitnexus-index.sh instead. Fix the suggestion to be project-aware: point at the repo-local indexing entry point (a `gitnexus-index` make target, an indexing script, or the repo's GITNEXUS.md instructions) and fall back to `npx gitnexus analyze` only when nothing repo-local exists. Sites: internal/assets/claude/skills/ctx-remember/SKILL.md:156, internal/assets/integrations/copilot-cli/skills/ctx-remember/SKILL.md:155, internal/assets/claude/skills/ctx-architecture-enrich/SKILL.md:34+112+130. Found live: /ctx-remember in the os project emitted the broken npx suggestion while the working `make gitnexus-index` existed one directory over. #priority:medium #session:6c276362 #branch:main #commit:a0e5cbf9 #added:2026-07-04-205437
DONE 2026-07-15 (session 87e465a0). Reworded all four sites (ctx-remember
companion-check suggestion; enrich precondition, no-MCP block, and >5-commit
hard-stop) to prefer the repo's own indexing entry point (make gitnexus-index
target / script / GITNEXUS.md) and fall back to bare `gitnexus analyze` only
when none exists — kept generic since these ship to arbitrary projects. (npx
itself was already gone via the 2026-07-06 de-npx pass; this is the
project-aware follow-up.) Copilot ctx-remember copy regenerated via
sync-copilot-skills; check-copilot-skills green. Spec:
specs/gitnexus-project-aware-reindex.md.

- [x] Drop the persisted INDEX blocks from DECISIONS.md/LEARNINGS.md;
project the index on demand via new CLI verbs instead. The headings
Expand Down
Loading
Loading