# Plan: Heuristic Inbox CLI Graduation

## Overview

Graduate the agent-kit heuristic-system helper into a nils-cli primitive
named `heuristic-inbox`. nils-cli owns the deterministic surface (schema,
folder ops, redaction, lifecycle, archive, execution log). agent-kit keeps
the skill body and the judgment workflow. The graduation requires a
nils-cli minor release and an agent-kit PR that pins the new minimum and
removes the in-repo Python helper. Tier 2 (lifecycle compression) and the
folder migration must ship before this plan starts.

## Read First

- Primary source: `docs/plans/heuristic-inbox-cli-graduation/heuristic-inbox-cli-graduation-discussion-source.md`
- Source type: discussion-to-implementation-doc
- Open questions carried into execution: `--kind` vs subcommand namespace
  (default `--kind`); thin shim retention (default: keep one minor, then
  delete).
- Resolved post-execution (2026-05-19): the released CLI dropped `--kind` in
  favour of `ENTRY.md` / `RECORD.md` filename inference; the shim was deleted
  in the same PR rather than carried for one minor. See
  `heuristic-inbox-cli-graduation-execution-state.md` "Open Questions
  Resolved" for implementation evidence.

## Execution

- Execution state: `docs/plans/heuristic-inbox-cli-graduation/heuristic-inbox-cli-graduation-execution-state.md`

## Scope

- In scope (nils-cli, separate repo):
  - New `heuristic-inbox` primitive matching the agent-kit schema.
  - Execution-log capture pattern matching `skill-usage`.
  - Packaging, tests, semver minor bump, brew tap release.
- In scope (agent-kit):
  - `skills/workflows/heuristic-system/heuristic-error-inbox/SKILL.md`
  - `skills/workflows/heuristic-system/heuristic-error-inbox/scripts/heuristic-error-inbox.sh`
    (thin wrapper)
  - Deletion of `skills/workflows/heuristic-system/heuristic-error-inbox/bin/heuristic_error_inbox.py`
  - Deletion of `skills/workflows/heuristic-system/heuristic-error-inbox/tests/test_workflows_heuristic_system_heuristic_error_inbox.py`
  - Smoke test that confirms `heuristic-inbox` on PATH with required min
    version.
  - `DEVELOPMENT.md` minimum nils-cli version pin.
  - `docs/runbooks/skills/SKILL_USAGE_RECORDING_V1.md` references to the
    primitive (if any).
- Out of scope:
  - Schema changes beyond folder shape.
  - Lifecycle enum changes beyond Tier 2.
  - Policy or judgment inside the CLI.
  - Other agent-kit helpers migrating to nils-cli.

## Assumptions

1. `heuristic-case-folder-migration` has shipped. Folder shape and
   redaction rules are stable.
2. nils-cli release cadence allows a minor bump within the same delivery
   window.
3. The brew tap automation publishes the bottle within the project's normal
   release SLA.
4. No agent currently in flight depends on the legacy single-file shape.

## Sprint 1: Build And Release `heuristic-inbox` In nils-cli

**Goal**: Tag a nils-cli release containing the new primitive with full
parity to the agent-kit helper, plus execution-log capture.
**Demo/Validation**:

- Command(s) (nils-cli repo):
  - Repo-native test command (`cargo test` or `uv run pytest`, depending on
    the primitive language).
  - `heuristic-inbox --version` on the locally built binary.
- Verify:
  - All subcommands present.
  - Redaction module enforces the same rules as the agent-kit version.
  - Execution log writes under `agent-out project --topic heuristic-inbox`.

**PR grouping intent**: per-sprint
**Execution Profile**: serial

### Task 1.1: Port helper logic into nils-cli `heuristic-inbox`

- **Location**:
  - nils-cli: new primitive module (path determined by the nils-cli repo
    layout)
- **Description**: Port the helper code from agent-kit, preserving the
  folder schema, redaction module, and lifecycle enum exactly. Implement
  subcommands `new`, `list`, `verify`, `set-status`, `archive`,
  `ingest-evidence`.
- **Dependencies**:
  - none
- **Complexity**: 7
- **Acceptance criteria**:
  - All subcommands exist with help text mirroring the agent-kit shim.
  - Schema and redaction fixtures match the agent-kit copies bit-for-bit.
  - Exit code matrix matches the agent-kit semantics.
- **Validation**:
  - Repo-native nils-cli test suite.

### Task 1.2: Add execution-log capture matching `skill-usage`

- **Location**:
  - nils-cli `heuristic-inbox` primitive
- **Description**: Every write op (`new`, `set-status`, `archive`,
  `ingest-evidence`) writes `invocation.json` (command, args, exit code,
  repo context, timing, host-redacted paths) and per-op companion files
  (e.g., `before.json`, `after.json` where state changes) under
  `agent-out project --topic heuristic-inbox --mkdir`.
- **Dependencies**:
  - Task 1.1
- **Complexity**: 4
- **Acceptance criteria**:
  - Execution-log file shape matches the existing `skill-usage` pattern.
  - Logs are written even on failure (so the next agent can diagnose).
  - Paths in the log are redacted to `<workspace>` placeholders.
- **Validation**:
  - Repo-native tests covering write op + log content.

### Task 1.3: Cut the nils-cli release

- **Location**:
  - nils-cli release pipeline
- **Description**: Bump nils-cli to the next minor version. Publish the
  brew tap bottle. Record the new minimum in this plan's execution state
  so the agent-kit sprint can pin it.
- **Dependencies**:
  - Task 1.2
- **Complexity**: 3
- **Acceptance criteria**:
  - `brew upgrade nils-cli` installs the new minor.
  - `heuristic-inbox --version` reports the new semver.
- **Validation**:
  - Manual: `brew upgrade nils-cli && heuristic-inbox --version`.

## Sprint 2: Thin The agent-kit Skill And Remove The In-Repo Helper

**Goal**: Land the agent-kit consumer side: SKILL.md uses the brew-installed
CLI, the Python helper and its tests are removed, DEVELOPMENT.md pins the
new minimum, and the rest of the repo is updated.
**Demo/Validation**:

- Command(s):
  - `scripts/check.sh --tests -- -k "heuristic_system or heuristic_error_inbox"`
  - `scripts/check.sh --all`
- Verify:
  - Skill body delegates all deterministic ops.
  - Smoke test asserts `heuristic-inbox` is on PATH with the required
    minimum.
  - DEVELOPMENT.md prereq lists the new minimum.

**PR grouping intent**: per-sprint
**Execution Profile**: serial

### Task 2.1: Update SKILL.md to call `heuristic-inbox`

- **Location**:
  - `skills/workflows/heuristic-system/heuristic-error-inbox/SKILL.md`
  - `skills/workflows/heuristic-system/heuristic-error-inbox/scripts/heuristic-error-inbox.sh`
- **Description**: Rewrite the SKILL.md Command Surface section to call
  `heuristic-inbox` directly. Shrink the `.sh` shim to a thin wrapper that
  forwards args and resolves an optional `NILS_CLI_BIN` override.
- **Dependencies**:
  - Task 1.3
- **Complexity**: 3
- **Acceptance criteria**:
  - SKILL.md shows `heuristic-inbox <subcommand>` examples, not the old
    Python helper path.
  - The shim has no logic beyond forwarding args.
- **Validation**:
  - `scripts/check.sh --tests -- -k heuristic_system`

### Task 2.2: Remove the in-repo Python helper and tests

- **Location**:
  - `skills/workflows/heuristic-system/heuristic-error-inbox/bin/heuristic_error_inbox.py`
    (delete)
  - `skills/workflows/heuristic-system/heuristic-error-inbox/tests/test_workflows_heuristic_system_heuristic_error_inbox.py`
    (delete or replace with smoke)
- **Description**: Delete the Python helper and its tests. Add a small
  smoke that asserts `heuristic-inbox --version` reports at least the
  required minor.
- **Dependencies**:
  - Task 2.1
- **Complexity**: 3
- **Acceptance criteria**:
  - The deleted files no longer appear in the working tree.
  - The smoke runs in `scripts/check.sh --tests` and passes when the brew
    install is current.
  - `bash scripts/ci/stale-skill-scripts-audit.sh --check` passes.
- **Validation**:
  - `scripts/check.sh --tests -- -k heuristic_error_inbox`
  - `bash scripts/ci/stale-skill-scripts-audit.sh --check`

### Task 2.3: Pin the new nils-cli minimum and update references

- **Location**:
  - `DEVELOPMENT.md`
  - `docs/runbooks/skills/SKILL_USAGE_RECORDING_V1.md` (only if it names the
    old helper path)
  - `AGENTS.md` (only if any local override mentions the in-repo helper)
- **Description**: Update the prereq table in DEVELOPMENT.md to require
  `nils-cli >= <new minimum>`. Update any other reference that names the
  in-repo helper.
- **Dependencies**:
  - Task 2.2
- **Complexity**: 2
- **Acceptance criteria**:
  - DEVELOPMENT.md pins the new minimum.
  - No tracked file references the deleted Python helper path.
- **Validation**:
  - `rg "bin/heuristic_error_inbox.py" --files-with-matches` returns no
    tracked file.
  - `scripts/check.sh --docs`

## Sprint 3: Validate And Land

**Goal**: Confirm cross-repo behavior, audit for orphan references, and run
the full gate.
**Demo/Validation**:

- Command(s):
  - `plan-tooling validate --file docs/plans/heuristic-inbox-cli-graduation/heuristic-inbox-cli-graduation-plan.md`
  - `scripts/check.sh --all`
  - Manual: `heuristic-inbox new --from-skill-usage <record> --slug pilot`
    against a sandbox folder, then `verify` and `archive`. (Originally
    written as `--slug pilot --kind inbox`; the released CLI infers case kind
    from `ENTRY.md` / `RECORD.md` filenames instead.)
- Verify:
  - End-to-end inbox + operation-record flows succeed through the brew
    CLI.
  - Execution logs land in the expected `agent-out` topic.

**PR grouping intent**: per-sprint
**Execution Profile**: serial

### Task 3.1: Run cross-repo smoke and validation

- **Location**:
  - `docs/plans/heuristic-inbox-cli-graduation/heuristic-inbox-cli-graduation-execution-state.md`
- **Description**: Run a manual smoke: create an inbox case, ingest a
  redacted excerpt, archive it, verify; do the same for an operation
  record. The smoke writes to the `agent-out project --topic heuristic-inbox`
  run directory, which is intentionally not tracked; link the resulting
  run-directory path inside the execution state.
- **Dependencies**:
  - Task 2.3
- **Complexity**: 3
- **Acceptance criteria**:
  - Smoke succeeds with the brew-installed CLI.
  - Execution log directory contains `invocation.json` and state
    transitions.
- **Validation**:
  - Manual smoke recorded under execution state.

### Task 3.2: Run the full repo gate and prepare delivery

- **Location**:
  - `docs/plans/heuristic-inbox-cli-graduation/heuristic-inbox-cli-graduation-execution-state.md`
- **Description**: Run `scripts/check.sh --all`. Record results, link the
  nils-cli release, and confirm there is no remaining policy or judgment
  inside the CLI.
- **Dependencies**:
  - Task 3.1
- **Complexity**: 2
- **Acceptance criteria**:
  - `scripts/check.sh --all` passes.
  - Execution state lists the new nils-cli minor, the smoke evidence, and
    final outcomes.
- **Validation**:
  - `scripts/check.sh --all`

## Testing Strategy

- Unit: nils-cli primitive tests in the nils-cli repo cover subcommands,
  redaction module, lifecycle transitions, and execution log writes.
- Integration: agent-kit smoke confirms PATH + minimum version. Doc and
  markdown gates ensure SKILL.md and DEVELOPMENT.md stay consistent.
- E2E/manual: cross-repo smoke creating a case, ingesting evidence, and
  archiving via the brew-installed CLI.

## Risks & gotchas

- Cross-repo coordination: a bug in nils-cli requires a release before any
  consumer can pick it up. Keep an `NILS_CLI_BIN` override for local
  development.
- Schema drift between agent-kit (which still owns templates) and
  nils-cli (which enforces them) would break every case. Treat the
  agent-kit schema fixtures as the source of truth and have the nils-cli
  primitive consume them directly.
- Judgment creep into the CLI defeats the boundary. Reject any CLI feature
  request that asks "auto-promote when X" or "auto-archive when Y".
- The brew bottle lag means the agent-kit PR cannot land until the
  release is publicly available. Sequence the merges accordingly.
- Removing the in-repo helper while a parallel agent session still runs
  against the old shape could break that session. Communicate the cutover
  before merging Sprint 2.

## Rollback plan

- agent-kit side: revert the helper deletion, restore the SKILL.md
  command surface, and unpin the new nils-cli minimum.
- nils-cli side: yank the new minor from the brew tap if a regression is
  confirmed; downstream consumers stay on the previous version.
- Tier 2 and folder migration remain unaffected by rollback of this plan.
