feat: restore TaskCreate captain-misuse enforcement via admiral session marker#119
Merged
Merged
Conversation
harrymunro
added a commit
that referenced
this pull request
May 8, 2026
Address PR #119 review feedback on cmd_session_check: - Mode gate now uses an explicit CAPTAIN_GATED_MODES allow-list (subagents, single-session). Previously any non-agent-team mode would reject on transcript mismatch, contradicting the docstring and pre-emptively gating future modes. - Empty admiral.session marker now fails open. Previously a partially written or interrupted marker would mismatch every payload and reject everything — including the admiral. - Share ADMIRAL_SESSION_MARKER constant via nelson_data_utils so hooks/ and skills/scripts/ reference one filename, not two. - Add regression tests for both fail-open paths and two unit tests for the preflight backfill path (previously untested). Tests: 64/64 hook tests, 280/280 lifecycle tests, references green.
…on marker PR #116 removed the PreToolUse:TaskCreate mode-check hook because it blanket-rejected the admiral's own Ctrl+T visibility tracking. This reinstates enforcement properly by discriminating admiral from captain via the hook payload's transcript_path (each subagent gets its own). - session-init (SessionStart): records admiral transcript_path to .nelson/admiral.session - session-check (PreToolUse:TaskCreate): rejects with wrong-ensign only when mode is subagents/single-session and the payload transcript_path does not match the recorded admiral marker - preflight: opportunistically backfills the marker if init ran after SessionStart fired - stand-down: best-effort marker cleanup - All paths fail-open on uncertainty (missing marker, empty transcript, no mission), so non-Nelson projects and edge cases are unaffected
Address PR #119 review feedback on cmd_session_check: - Mode gate now uses an explicit CAPTAIN_GATED_MODES allow-list (subagents, single-session). Previously any non-agent-team mode would reject on transcript mismatch, contradicting the docstring and pre-emptively gating future modes. - Empty admiral.session marker now fails open. Previously a partially written or interrupted marker would mismatch every payload and reject everything — including the admiral. - Share ADMIRAL_SESSION_MARKER constant via nelson_data_utils so hooks/ and skills/scripts/ reference one filename, not two. - Add regression tests for both fail-open paths and two unit tests for the preflight backfill path (previously untested). Tests: 64/64 hook tests, 280/280 lifecycle tests, references green.
8a03dd9 to
7a1117c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Restores the captain-
TaskCreateenforcement that PR #116 removed, this time without false-positive rejections of the admiral's own Ctrl+T visibility tracking. Discriminates admiral from captain subagents via the hook payload'stranscript_path(each subagent spawn gets a fresh transcript; admiral keeps its own).session-init(SessionStart): records admiraltranscript_pathto.nelson/admiral.session.session-check(PreToolUse onTaskCreate): rejects withwrong-ensignonly insubagents/single-sessionmode when the payloadtranscript_pathdoes not match the recorded admiral marker.preflight: opportunistically backfills the marker ifinitran after SessionStart fired (admiral always spawns Agents, so this is the safe fallback).stand-down: best-effort marker cleanup.transcript_path), so non-Nelson projects and edge cases stay untouched.Tracks
nelson-1o9.Test plan
pytest hooks/test_nelson_hooks.py -q→ 60/60 pass (was 48; +4TestSessionInit, +8TestSessionCheck).pytest skills/nelson/scripts -q→ 280/280 pass (was 278; +2 stand-down marker-cleanup tests).bash scripts/check-references.sh→ all cross-references valid.python3 hooks/nelson_hooks.py --help→ both new subcommands listed.session-init: writes marker when.nelson/exists, no-op when it doesn't.subagents-mode Nelson mission, spawn a captain viaAgent, log payloads from a throwawayPreToolUse:TaskCreatehook, confirm captaintranscript_pathdiffers from admiral. Plan called for this before committing — flagging for reviewer because it requires a real mission run.TaskCreateallowed withoutwrong-ensignfeedback; captainTaskCreaterejected;.nelson/admiral.sessionremoved at stand-down;SessionStartis a no-op in non-Nelson projects.Notes
.nelson/admiral.session, project-scoped (not mission-scoped). Stand-down resolves it viamission_dir.parent.parent.TaskCreaterow plus a newSessionStartrow.references/tool-mapping.mdorreferences/standing-orders/wrong-ensign.md— existing admiral-exception language remains accurate.