# Plan: Enhance `/init` to include build/debug/test/post-edit workflow in AGENTS.md

## Guiding principle

AGENTS.md and the prompts that generate it are consumed by AI agents. Every token matters. Imperative instructions, exact commands, zero prose filler.

## Goal

`/init` currently explores the codebase for cross-cutting conventions and writes them to `AGENTS.md`. It must also discover and emit:

1. How to build/install
2. How to test (all, single file, single case)
3. How to lint/format/type-check
4. What to run after every edit (the post-edit reflex)
5. How to debug (if discoverable)

## Current state

- Three-pass process in `agent.py` (lines 5491–5538):
  1. `INIT_PROMPT` (line 107) — scan for conventions
  2. `INIT_ENRICH_PROMPT` (line 118) — filter noise
  3. `INIT_WRITE_PROMPT` (line 127) — write to AGENTS.md
- Prompts focus exclusively on conventions. No mention of build/test/lint/post-edit.
- Existing `AGENTS.md` is 11 lines, conventions only.

## Changes

### 1. Rewrite `INIT_PROMPT` — explore conventions AND workflows

Two discovery axes:

**A) Workflows** — read build/CI files and extract exact commands:
- Install dependencies
- Build (if applicable)
- Run all tests / single file / single case
- Lint, format, type-check
- The canonical local validation sequence (see precedence rule below)
- Debug setup (launch configs, env vars, flags)

**Command-source precedence for "after every edit":**

The post-edit reflex is the canonical local validation sequence — whatever a developer runs locally before considering a change done. The prompt must instruct the agent to determine it using this priority:

1. A Makefile/justfile/package.json target that represents the full local validation pass (e.g., `make all`, `npm run validate`, `just check`). This may combine any subset of lint, format-check, type-check, and test. Accept whatever the target includes — do not second-guess which steps it covers.
2. If no single target exists, reconstruct the sequence from individual commands: chain all discoverable validation steps (lint, format-check, type-check, test) with `&&`.
3. CI config (`.github/workflows/`) is informational context for understanding the project but does NOT define the post-edit reflex — CI often runs a subset or superset of local validation.

The prompt must explicitly state: "CI may differ from local validation. Prefer local build-system targets over CI steps for the post-edit command. The post-edit command is whatever the project's build system defines as the full local validation pass — not just lint + test."

Files to probe: `Makefile`, `justfile`, `package.json` (scripts), `pyproject.toml` (`[tool.*]`), `tox.ini`, `.github/workflows/*.yml`, `Taskfile.yml`, `Cargo.toml`, `CMakeLists.txt`, `build.zig`.

**B) Conventions** — same as current: cross-cutting patterns an agent wouldn't know without reading source.

### 2. Rewrite `INIT_ENRICH_PROMPT` — never cut workflow items

Add a hard rule: "Never cut build, test, lint, format, type-check, debug, or post-edit commands. Always actionable for an agent."

Tighten the existing filter: replace vague language with "would an agent produce incorrect code or miss a required step without this?"

### 3. Rewrite `INIT_WRITE_PROMPT` — structured, budget-aware output

**Output structure:**

```
## Workflow

- install: `<command>`
- build: `<command>` (omit line if N/A)
- test all: `<command>`
- test file: `<command with placeholder>`
- test case: `<command with placeholder>`
- lint: `<command>`
- format: `<command>`
- typecheck: `<command>` (omit line if N/A)
- after every edit: `<command or sequence>`
- debug: `<notes>` (omit line if nothing discoverable)

## Conventions

- <terse convention bullets, 2 sentences max each>
```

**Budget constraint:**

The project-level AGENTS.md shares a 10,000-character budget (`MAX_INSTRUCTIONS_CHARS`) with user-level and global AGENTS.md files (loaded in `agent.py:1177–1252`). The prompt must:

- Set a target of **≤3,000 characters** for the generated AGENTS.md. This leaves room for user-level and global files.
- **Workflow section first, conventions second.** If space is tight, conventions get trimmed — workflow commands are always more actionable.
- State this explicitly: "Total output must not exceed 3000 characters. Workflow section takes priority. Cut convention bullets before workflow lines."

### 4. Implementation

**Files modified:**

- `swival/agent.py`:
  - Rewrite three string constants: `INIT_PROMPT` (~line 107), `INIT_ENRICH_PROMPT` (~line 118), `INIT_WRITE_PROMPT` (~line 127)
  - Add a new format string constant `INIT_RETRY_PROMPT` with a `{reason}` placeholder — the corrective prompt appended on validation failure
  - Modify the `/init` handler (~line 5491–5538) to add a post-write validation step after the third pass (see section 3, output-shape validation)
- `tests/test_repl.py` (or new `tests/test_init.py`) — update existing tests and add new ones (see section 5)

No new production dependencies.

**Control flow change:** The current `/init` is a fixed three-pass loop. The new version is three primary passes plus a conditional validation-and-retry step after the write pass. Specifically, after pass 3 completes:

1. Read AGENTS.md from `base_dir`. Validate using a two-part predicate: (a) the file exists AND contains a line matching the regex `^## Workflow\s*$` (anchored to line start, case-sensitive, no trailing content except optional whitespace), and (b) that line appears before any line matching `^## ` that is not `## Workflow` (i.e., Workflow is the first level-2 section). Both conditions must pass. This is the one canonical structure the prompts are told to produce.
2. If the predicate fails (any condition — file missing, heading absent, or heading not first), append a corrective retry prompt and re-run once (pass 4). The retry prompt is a format string `INIT_RETRY_PROMPT` with a `{reason}` placeholder, filled at runtime with a short description of the failure (e.g., `"AGENTS.md was not created"`, `"missing ## Workflow section"`, `"## Workflow is not the first section"`). The rest of the prompt is fixed: it instructs the model to rewrite the file with `## Workflow` as the first section followed by `## Conventions`. This is distinct from replaying `INIT_WRITE_PROMPT` — the model needs to know what specifically went wrong.
3. After the final write (pass 3 if valid, pass 4 if retried), check file size. If it exceeds 3,000 characters, emit `fmt.warning()`. Advisory only. This size check runs on whichever write produced the final file — it applies to both the initial write and the retry.
4. If the retry also produces a missing/malformed file, emit `fmt.warning()` and continue — `/init` does not fail. The agent did its best; the user can inspect and re-run.

All predicate failures — missing file, missing heading, heading not first — trigger one retry. The retry prompt is the same template (`INIT_RETRY_PROMPT`) with a failure-specific `{reason}`.

The prompts themselves must be written in agent-optimized style: imperative, terse, no filler.

### 5. Tests

**Existing tests require updates:**

`tests/test_repl.py:1271–1313` (`test_init_sends_prompt`, `test_init_ignores_args_with_warning`) mock `run_agent_loop`, use `base_dir=tmp_path`, never create an AGENTS.md file, and assert exactly 3 `run_agent_loop` calls. With the new readback step, a missing AGENTS.md after pass 3 triggers one retry (pass 4). These tests must be updated:

- `test_init_sends_prompt`: Have the fake `run_agent_loop` write a valid AGENTS.md with `## Workflow` on pass 3 so the retry doesn't fire. Assert 3 calls. This tests the happy path.
- `test_init_ignores_args_with_warning`: Same treatment.
- Add companion tests for the retry and warning paths (see items 6–11 below).

**New prompt-contract tests** (deterministic, no LLM):

1. **Workflow keywords in INIT_PROMPT:** Assert it contains `"Makefile"`, `"test"`, `"lint"`, `"after every edit"` (or equivalent). Catches accidental removal of workflow discovery instructions.

2. **CI precedence rule in INIT_PROMPT:** Assert it contains language about CI not defining the post-edit command (e.g., `"CI"` and `"local"`).

3. **Budget target in INIT_WRITE_PROMPT:** Assert it references a character limit (e.g., `"3000"`).

4. **Section ordering in INIT_WRITE_PROMPT:** Assert `"Workflow"` appears before `"Convention"` in the prompt text.

5. **Never-cut rule in INIT_ENRICH_PROMPT:** Assert it contains `"never cut"` or equivalent for workflow items.

**New readback/retry/warn tests** (deterministic, mock `run_agent_loop`):

The validation predicate used in all tests is the same one used in the implementation: file exists, contains a line matching `^## Workflow\s*$`, and that line appears before any other `^## ` heading. Tests should extract the predicate into a shared helper (e.g., `_valid_agents_md(path) -> bool`) used by both production code and tests — single source of truth.

6. **Valid file, no retry:** Pass 3's fake `run_agent_loop` writes an AGENTS.md with `## Workflow` as the first section. Assert `run_agent_loop` called exactly 3 times, no warning emitted.

6b. **Reason strings per failure mode (table-driven):** Three sub-cases, each writes a specific invalid AGENTS.md on pass 3 and a valid one on pass 4. Assert 4 calls in each, and assert the 4th prompt contains the expected reason string:
   - File not created → reason contains `"not created"`
   - File exists, no `## Workflow` → reason contains `"missing"`
   - File has `## Workflow` after `## Conventions` → reason contains `"not the first"`

7. **Missing heading, retry succeeds (end-to-end):** Pass 3 writes an AGENTS.md without `## Workflow`. Pass 4 (retry) writes a valid one. Assert `run_agent_loop` called 4 times. Assert the 4th prompt is `INIT_RETRY_PROMPT.format(reason=...)` (not a replay of `INIT_WRITE_PROMPT`). No warning.

8. **Missing heading, retry also fails:** Pass 3 and pass 4 both write AGENTS.md without `## Workflow`. Assert `run_agent_loop` called 4 times, `fmt.warning()` emitted about missing section.

9. **Missing file, retry succeeds:** Pass 3 does not create AGENTS.md. Pass 4 writes a valid one. Assert 4 calls, no warning.

10. **Budget warning on initial write:** Pass 3 writes a valid AGENTS.md (has `## Workflow`) that exceeds 3,000 characters. Assert 3 calls (no retry — heading present), `fmt.warning()` emitted about size.

11. **Budget warning after retry:** Pass 3 writes AGENTS.md without `## Workflow`. Pass 4 writes a valid but oversized (>3,000 chars) AGENTS.md. Assert 4 calls, `fmt.warning()` emitted about size (size check runs on the final file regardless of which pass produced it).

Accepted tradeoff: prompt-based enforcement of content quality is best-effort. The code catches structural failures (missing section, oversized file); it cannot guarantee the LLM produces correct commands.

### 6. Manual validation

- Run `/init` on the swival repo. Verify:
  - "after every edit" says `make all` (the canonical local validation target) — not just `pytest`, not just `make check`
  - Output is under 3,000 characters
  - Workflow section appears before conventions
- `make check` passes on modified files
- `make test` passes including new prompt-contract tests

### 7. Acceptance criteria

- [ ] Exact install/build commands
- [ ] Exact test commands (all, single file, single case)
- [ ] Exact lint/format/typecheck commands
- [ ] Mandatory "after every edit" — derived from canonical local validation, not CI
- [ ] Debug notes (if discoverable, else omitted)
- [ ] Conventions preserved
- [ ] Output ≤3,000 chars (advisory warning if exceeded), workflow section first
- [ ] Prompt-contract tests passing (items 1–5)
- [ ] Readback/retry/warn tests passing (items 6–11)
- [ ] Existing `/init` tests updated for new control flow
- [ ] No prose filler — every line actionable
