Skip to content

Trail-code learnings, session handoffs, owner-only guard for agent context - #231

Merged
kjmikkel merged 5 commits into
mainfrom
feat/230-trail-workflow
Oct 20, 2026
Merged

kjmikkel merged 5 commits into
mainfrom
feat/230-trail-workflow

Conversation

@kjmikkel

Copy link
Copy Markdown
Owner

Closes #230

Adopts the agent workflow from kjmikkel/Dracula-Night-by-Night (#163, #165 there).

Trail-code — trail init --no-agents --no-global: .trail/hook.cjs (SessionStart shim; hands over to trail if installed, otherwise shows Claude the learnings), .trail/README.md, .trail/.gitignore, and the hook entry in .claude/settings.json. First learning included.

Plan / execute / handoff — new CLAUDE.md section: plan on the strongest model, implement with Sonnet subagents (already set up in .claude/agents/), and end each planned session with docs updated, trail note, and a continuation prompt appended to the plan under ## Handoff — <date>.

Safeguards (Trail injects .trail/learnings into context; hook.cjs imports from node_modules//dist/claude/ and runs npm via cmd.exe):

  • guard / trail-owner-only on pull_request_target — base-branch workflow and script, PR code never checked out. Fails when a non-owner touches .trail, .claude (incl. the tracked agents/skills), CLAUDE.md, CLAUDE.local.md, AGENTS.md, .mcp.json, node_modules, dist/claude, or a root PATHEXT executable; symlink-, case-, trailing-dot/space-, 8.3- and Unicode-look-alike-aware; fails closed on API errors and the 3,000-file cap.
  • .github/CODEOWNERS lists the same paths.
  • .github/scripts/trail-guard.test.sh: 43 cases, all passing locally.

Also: .claude/settings.local.json is no longer tracked — it's per-machine (and trail init writes its statusline there). Note it remains in git history. graft/ (stale cache from trail's old name) is ignored.

Because the guard runs from main, it won't run on this PR; mark guard / trail-owner-only required after merge.

🤖 Generated with Claude Code

kjmikkel and others added 4 commits October 17, 2026 16:10
…gent context (#230)

- trail init --no-agents --no-global: .trail/ (hook shim, README, .gitignore)
  and the shared SessionStart hook in .claude/settings.json.
- CLAUDE.md: plan/execute split, end-of-session handoff (docs, trail note,
  continuation prompt appended to the plan), and the agent-context rule.
- guard / trail-owner-only (pull_request_target) + CODEOWNERS, ported from
  Dracula-Night-by-Night: only the owner may touch .trail, .claude, CLAUDE.md,
  AGENTS.md, .mcp.json, node_modules, dist/claude or root PATHEXT executables.
  43 test cases in .github/scripts/trail-guard.test.sh.
- Stop tracking .claude/settings.local.json (per-machine; trail init writes
  its statusline there) and ignore the stale graft/ cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two gaps in .trail/hook.cjs's trust boundary, found by security review:
- hook.cjs resolves @trailhq/trail-code from the repo root, so a root
  package.json with that name self-references and its "exports" can point
  the hook at hooks.js in any unguarded directory (reproduced).
- hook.cjs runs `npm root -g` via cmd.exe, which searches the current
  directory first; that is wherever the session started, so a planted
  npm.cmd in a subdirectory ran. Executables are now owner-only at any depth.

Fixed in the guard rather than hook.cjs because `trail init` regenerates the
hook. CODEOWNERS and CLAUDE.md updated to match; 48 guard tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- .cpl is in PATHEXT on some machines (this one included), so cmd.exe would
  run a planted npm.cpl like npm.cmd.
- A submodule's files never appear in the PR's changed-file list, so a
  submodule could carry anything the guard blocks. .gitmodules is now
  owner-only at any depth.

54 guard tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… copy (#230)

PATHEXT differs per machine (Python adds .py/.pyw), so a fixed extension list
can't be complete. The names hook.cjs actually runs are now owner-only with
any extension. 58 guard tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kjmikkel
kjmikkel force-pushed the feat/230-trail-workflow branch from f1573ee to e6df894 Compare October 17, 2026 14:38
A committed .pyc carried a local path; it was purged from history along with
.claude/settings.local.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kjmikkel
kjmikkel merged commit 5471aad into main Oct 20, 2026
10 checks passed
@kjmikkel
kjmikkel deleted the feat/230-trail-workflow branch October 20, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Set up Trail-code shared learnings, session handoffs, and an owner-only guard for agent-context paths

1 participant