---
satisfies: [R12, R13, R14, R15, R16, R17]
---

## Description

Rollup. Smoke test for the flowctl plumbing (Task 2) — skills aren't unit-testable, so smoke covers the persistence layer only. Plus docs (CHANGELOG, README, CLAUDE.md, .flow/usage.md), website lifecycle bullet, codex mirror regen, and version bump 0.36.0 → 0.37.0.

**Size:** M
**Files:**
- `plugins/flow-next/scripts/audit_smoke_test.sh` (new — flowctl plumbing only)
- `CHANGELOG.md` (new `[flow-next 0.37.0]` entry above 0.36.0)
- `plugins/flow-next/README.md` (memory subcommand section + skill mention)
- `CLAUDE.md` (memory-system block + skill bullet)
- `.flow/usage.md` (memory commands list, if present)
- `~/work/mickel.tech/app/apps/flow-next/page.tsx` (memory feature card description)
- `.claude-plugin/marketplace.json`, `plugins/flow-next/.claude-plugin/plugin.json`, `plugins/flow-next/.codex-plugin/plugin.json` (versions — handled by `bump.sh`)
- `plugins/flow-next/codex/` (regenerated by `sync-codex.sh`)

## Approach

### Smoke test (`audit_smoke_test.sh`)

Mirror `prospect_smoke_test.sh:1-90` shape (helpers, header guard refusing to run from main repo, KEEP_TEST_DIR opt-out, cleanup trap, `pick_python` helper, `assert_rc` / `assert_grep` / `assert_grep_re` helpers).

Cases (covers Task 2 plumbing only — skills get verified by manual invocation, not smoke):

```
=== Setup ===
- Refuse to run from main repo
- mkdir TEST_DIR + cd
- git init + commit
- flowctl init + memory init
- Seed entries via flowctl memory add:
  - 2 active entries (bug/runtime-errors, knowledge/conventions)
  - Entry with module field, body, tags

=== Cases ===
Case 1: mark-stale roundtrip
  flowctl memory mark-stale <id> --reason "module renamed"
  → entry has status: stale, last_audited: <today>, audit_notes: "module renamed"
  → body unchanged (verify by diff)

Case 2: mark-stale with --audited-by
  flowctl memory mark-stale <id> --reason "X" --audited-by "/flow-next:audit"
  → audit_notes contains "X" + "(audited-by: /flow-next:audit)"

Case 3: mark-stale --json output shape
  flowctl memory mark-stale <id> --reason "X" --json
  → assert id, path, status="stale", last_audited, audit_notes all present
  <!-- Updated by plan-sync: fn-34.2 ships JSON shape {id, path, status, last_audited, audit_notes} (no `success` key) -->

Case 4: mark-stale missing --reason errors
  flowctl memory mark-stale <id>  (no --reason)
  → rc != 0, stderr mentions "required" or similar

Case 5: mark-stale idempotent
  mark-stale --reason "first"; mark-stale --reason "second"
  → second succeeds, audit_notes now "second", last_audited stamped twice

Case 6: mark-fresh roundtrip
  After Case 1's mark-stale, run mark-fresh <id>
  → status cleared, audit_notes empty/cleared, last_audited stamped

Case 7: mark-fresh on active entry no-op-ish
  mark-fresh on never-stale entry
  → rc=0, last_audited stamped, status still active

Case 8: search --status active default excludes stale
  Mark one entry stale, run flowctl memory search "<query in stale entry>"
  → stale entry NOT in results

Case 9: search --status stale includes only stale
  Same setup, flowctl memory search "<query>" --status stale
  → only stale entries returned

Case 10: search --status all includes both
  flowctl memory search "<query>" --status all
  → both active + stale returned

Case 11: list --status stale (existing fn-30 behavior, no regression)
  flowctl memory list --status stale
  → returns stale entries (verify fn-30 path still works)

Case 12: schema validation accepts new fields
  Manually write entry with last_audited + audit_notes in frontmatter
  flowctl memory read <id> → succeeds, frontmatter round-trips intact

Case 13: Ralph regression — mark-stale + mark-fresh + search work under FLOW_RALPH=1
  FLOW_RALPH=1 flowctl memory mark-stale <id> --reason "X" → rc=0
  FLOW_RALPH=1 flowctl memory search "<q>" --status all → rc=0
  (Pure plumbing, no Ralph gate. Skill is gated, plumbing is not.)
```

Target runtime: <30s end-to-end.

### `CHANGELOG.md` entry (insert above 0.36.0)

```markdown
## [flow-next 0.37.0] - 2026-04-XX

### Added
- `/flow-next:audit` — agent-native skill that walks `.flow/memory/`, reviews each entry against the current codebase, and decides per entry whether to Keep / Update / Consolidate / Replace / Delete. Interactive mode (default) asks via blocking-question tool; autofix mode (`mode:autofix` argument) applies unambiguous actions and marks ambiguous entries as stale. Adapted to the categorized memory schema shipped in 0.33.0.
- `flowctl memory mark-stale <id> --reason "..."` — sets `status: stale`, stamps `last_audited`, records `audit_notes`. Atomic via existing `write_memory_entry`. Body never modified.
- `flowctl memory mark-fresh <id>` — clears stale flag, stamps `last_audited`. Idempotent on already-active entries.
- `flowctl memory search` accepts `--status active|stale|all` (default `active`), mirroring `memory list`. Stale entries flagged by audit are excluded from default search results.

### Changed
- `MEMORY_OPTIONAL_FIELDS` extended with `last_audited`, `audit_notes`. `MEMORY_FIELD_ORDER` and `_MEMORY_QUOTED_STRING_FIELDS` updated. Validator unchanged (allowed-fields union picks up additions).

### Notes
- `/flow-next:audit` skips legacy flat-file memory entries (`pitfalls.md`, `conventions.md`, `decisions.md`) with a warning recommending `flowctl memory migrate` first.
- Subagent dispatch in the skill is documented for Claude Code (`Agent` + `Explore`), Codex (`spawn_agent` + `explorer`), and Droid; orchestrator falls back to main-thread investigation when subagent primitives are unavailable.
- The audit is fully agent-native — no codex/copilot subprocess dispatch, no Python audit engine. The host agent does the investigation directly using its existing Read/Grep/Glob tools.
```

### `plugins/flow-next/README.md` updates

Two locations:

1. **Skills table** (or skill-list section near the top) — add `/flow-next:audit` entry alongside existing skills (prospect, plan, work, interview, plan-review, impl-review, resolve-pr).

2. **Memory section** (`README.md:1437-1580`-ish) — under the existing memory subcommand examples, add:

```bash
# Mark an entry stale (used by /flow-next:audit, also callable directly)
flowctl memory mark-stale <id> --reason "module renamed in PR #123"
flowctl memory mark-stale <id> --reason "..." --audited-by "/flow-next:audit"
flowctl memory mark-stale <id> --reason "..." --json

# Clear stale flag
flowctl memory mark-fresh <id>

# Search now respects status (default: active)
flowctl memory search <query>                  # active only (default)
flowctl memory search <query> --status stale   # only stale entries
flowctl memory search <query> --status all     # active + stale
```

Plus a one-paragraph mention of the `/flow-next:audit` skill above the subcommand list.

### `CLAUDE.md` memory-system block (lines 62-77)

Add after the `discoverability-patch` bullet:

```
- Audit (skill): `/flow-next:audit [mode:autofix] [scope hint]` — agent-native skill that reviews memory entries against current code; decides Keep/Update/Consolidate/Replace/Delete per entry. Interactive (asks via blocking-question tool) or autofix (applies unambiguous, marks ambiguous as stale). Skips legacy flat files (run `memory migrate` first).
- Mark stale: `flowctl memory mark-stale <id> --reason "..." [--audited-by "..."]` — sets status: stale, stamps last_audited, records audit_notes. Used by /flow-next:audit, also callable directly.
- Mark fresh: `flowctl memory mark-fresh <id>` — clears stale flag.
- Status filter (existing fn-30 expanded to search): `flowctl memory search <q> --status active|stale|all` (default active). Stale entries excluded from default search results.
```

### `.flow/usage.md`

If memory commands listed: append the three new ones. If not, no change needed.

### `~/work/mickel.tech/app/apps/flow-next/page.tsx`

Locate the memory feature card description (~line 537). Append:

```
... `/flow-next:audit` reviews entries against current code; the agent decides Keep / Update / Consolidate / Replace / Delete per entry. Autofix mode applies unambiguous changes and marks ambiguous as stale. Never deletes silently.
```

Match existing card tone (terse, verb-led).

### `scripts/sync-codex.sh` regen

```bash
./scripts/sync-codex.sh
```

This regenerates `plugins/flow-next/codex/` to mirror the new skill (`flow-next-audit/`) and slash command (`audit.md`). The sync script is idempotent — safe to re-run if anything is already in place.

Verify post-sync:
- `plugins/flow-next/codex/skills/flow-next-audit/` exists with the three skill files
- `plugins/flow-next/codex/prompts/flow-next-audit.md` (or wherever Codex puts slash commands) exists
- No diff in unrelated files

### `scripts/bump.sh`

```bash
./scripts/bump.sh minor flow-next
```

Updates 3 manifests to 0.37.0. Verify:
- `.claude-plugin/marketplace.json` flow-next plugin version → 0.37.0
- `plugins/flow-next/.claude-plugin/plugin.json` version → 0.37.0
- `plugins/flow-next/.codex-plugin/plugin.json` version → 0.37.0

`jq . <each>` parses cleanly.

### Final commit + tag (post-merge, manual)

Per `CLAUDE.md` release checklist:

```bash
git commit -am "feat(flow-next): /flow-next:audit skill + memory mark-stale/mark-fresh + search --status — 0.37.0"
git push
git tag flow-next-v0.37.0 && git push origin flow-next-v0.37.0
```

Tag triggers release workflow + Discord. Don't tag without pushing.

Mickel.tech commit lands separately in that repo, terse conventional-commit style.

## Investigation targets

**Required:**
- `plugins/flow-next/scripts/prospect_smoke_test.sh` — smoke shape to mirror
- `plugins/flow-next/scripts/smoke_test.sh:427-...` — memory-section conventions
- `CHANGELOG.md:1-50` — recent entry shape (`[flow-next 0.36.0]`, `[flow-next 0.35.0]`)
- `plugins/flow-next/README.md` — memory section + skill list
- `CLAUDE.md:62-77` — memory-system block
- `~/work/mickel.tech/app/apps/flow-next/page.tsx:534-538` — memory card
- `scripts/bump.sh` — version-bump script (read for confidence; do NOT edit manifests by hand)
- `scripts/sync-codex.sh` — codex mirror regen

**Optional:**
- Recent fn-33 PR diff for shape of website + docs commit pattern
- `.flow/usage.md` — memory commands listing (verify presence)

## Key context

- Skills aren't unit-testable. Smoke covers Task 2 plumbing only. The skill (Task 1) is verified by manual invocation in a real session — that verification happens out-of-band (during this PR's review or post-merge).
- `bump.sh` handles 3 manifests atomically — don't edit them manually.
- `sync-codex.sh` is idempotent. Re-running is safe.
- Tag triggers GitHub Actions release + Discord. Don't tag locally without pushing.
- Mickel.tech is a separate repo. Commit there independently, follow that repo's commit conventions.
- Verify CHANGELOG date placeholder (`<date>`) gets replaced with actual release date before commit.
- Smoke target runtime: <30s. This is plumbing tests, not full skill workflow.

## Acceptance

- [ ] `audit_smoke_test.sh` exists, executable, set-euo-pipefail, refuses to run from main repo, has KEEP_TEST_DIR opt-out, cleanup trap. (R12)
- [ ] All 13 cases in audit_smoke_test.sh pass end-to-end. (R12, R13)
- [ ] Smoke runtime <30s on a typical dev machine.
- [ ] Existing smoke tests (`smoke_test.sh`, `prospect_smoke_test.sh`, `ralph_smoke_test.sh`) all still pass — no regressions. (R12)
- [ ] `CHANGELOG.md` has `[flow-next 0.37.0]` entry above 0.36.0 with Added/Changed/Notes sections covering: skill, mark-stale, mark-fresh, search --status, schema extension, legacy-skip, agent-native architecture note. (R14)
- [ ] `plugins/flow-next/README.md` skill list includes `/flow-next:audit`; memory section includes mark-stale + mark-fresh + search --status examples. (R14)
- [ ] `CLAUDE.md` memory-system block has audit + mark-stale + mark-fresh + search --status bullets. (R14)
- [ ] `.flow/usage.md` updated if it lists memory commands; otherwise no change. (R14)
- [ ] `~/work/mickel.tech/app/apps/flow-next/page.tsx` memory feature card description appended with one-line audit lifecycle. (R15)
- [ ] `scripts/sync-codex.sh` regenerated; `plugins/flow-next/codex/skills/flow-next-audit/` exists with three skill files. (R16)
- [ ] All three manifests (`marketplace.json`, `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`) show version 0.37.0; `jq` parses cleanly on each. (R17)
- [ ] All checks ready for manual `git tag flow-next-v0.37.0 && git push origin flow-next-v0.37.0` after PR merge.


## Done summary
Shipped fn-34 rollup: audit_smoke_test.sh (13 cases / 41 assertions covering mark-stale + mark-fresh + search --status plumbing) plus CHANGELOG/README/CLAUDE.md/.flow/usage.md docs and version bump 0.36.0 → 0.37.0 (manifests + codex mirror regenerated). Patched smoke_test.sh memory search assertion to match fn-34.2's new --status active default. All four smoke suites + unit tests green.
## Evidence
- Commits: f0cda1eb807378c29e92aa5309fb8d0b4620ba49
- Tests: plugins/flow-next/scripts/audit_smoke_test.sh (13 cases / 41 assertions), plugins/flow-next/scripts/smoke_test.sh (126 assertions), plugins/flow-next/scripts/prospect_smoke_test.sh (94 assertions), plugins/flow-next/scripts/ralph_smoke_test.sh (15 assertions), python3 -m unittest discover -s plugins/flow-next/tests (331/331 green)
- PRs: