Batch-review your Chief of Staff agent's pending proposals, STATE.md flags, and new silent duty failures — deterministic re-verification via per-proposal recheck recipes, one HTML digest, one decision pass (approve/reject for changes, accept-to-backlog/dismiss for ideas, defer for either), and one commit per decision. Use when the user says "review persona flags", "close persona flags", "review pending proposals", "what's pending my approval", or "/agenticos:persona-flag-closer".
Installs into .claude/skills of the current project.
Are you the author of Persona Flag Closer?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/zzoretich-persona-flag-closer-agenticos-workbench)
---
name: persona-flag-closer
description: Batch-review your Chief of Staff agent's pending proposals, STATE.md flags, and new silent duty failures — deterministic re-verification via per-proposal recheck recipes, one HTML digest, one decision pass (approve/reject for changes, accept-to-backlog/dismiss for ideas, defer for either), and one commit per decision. Use when the user says "review persona flags", "close persona flags", "review pending proposals", "what's pending my approval", or "/agenticos:persona-flag-closer".
---
# Persona Flag Closer
Close the loop on the agent's findings: everything pending the user's judgment, reviewed in ONE pass. Deterministic Node does collection and re-verification (zero tokens); the conversation is spent only on decisions.
Paths: `SKILL_DIR = ${CLAUDE_PLUGIN_ROOT}/skills/persona-flag-closer`. The vault is the `vault` value in `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/agenticos.json`; the scripts read it themselves (`--root <vault>` overrides). Proposals live in `<vault>/persona/proposals/*.md` (README.md is not a proposal); flags are the `- [ ]` lines under `## Flags` in `<vault>/persona/STATE.md`; silent failures come from `<vault>/persona/journal/logs/duty-*-error.log` (or `PERSONA_LOG_DIR`). Review state lives in `<vault>/persona/flag-closer/`. The outcome ledger is `LEDGER = <vault>/brain/scripts/persona/ledger.js` (appends to `<vault>/persona/ledger.jsonl`, which IS tracked — include it in the commit). The idea backlog is `BACKLOG = <vault>/brain/scripts/persona/backlog.js` (appends to `<vault>/persona/backlog.md`, also tracked). The recipe runner is `RECHECK = <vault>/brain/scripts/persona/recheck.js` (the tick runs its `record` verb daily; this review runs it without recording). If `node` is not on PATH, use the `node` path recorded in `agenticos.json`.
## Workflow
1. **Collect (deterministic, run ONCE per review):**
`node "<vault>/brain/scripts/persona/proposal-html.js"` first — it renders each pending proposal's HTML page into `<vault>/brain/_index/proposals/` (gitignored) and fixes its "Open the proposal in browser" line, so a proposal decided now still has a page in the Proposals tab's Backlog and History.
`node "$SKILL_DIR/scripts/collect.js" --update-state > /tmp/pfc-collect.json`
`--update-state` consumes error-log offsets and records the pending-set hash.
2. **Re-verify (deterministic):**
`node "$RECHECK" /tmp/pfc-collect.json > /tmp/pfc-review.json`
Verdicts: STILL-VALID (recipe exit 0 — finding still present) · STALE (nonzero — likely already fixed) · RECIPE-ERROR (recipe broken) · NO-RECIPE (legacy proposal — human judgment). Do NOT pass `--record` here: the confirmation counters (`<vault>/persona/flag-closer/confirmations.json`) are the tick's — its precheck records one pass per local day, so an interactive review never inflates the auto-apply ladder.
3. **Empty case:** if `proposals`, `flags`, and `logFindings` are all empty in `/tmp/pfc-review.json`, say "Nothing pending — no proposals, no flags, no new failures." and STOP.
4. **Render the digest:**
`TODAY=$(date +%F); node "$SKILL_DIR/scripts/render-digest.js" /tmp/pfc-review.json > "<vault>/persona/flag-closer/digest-$TODAY.html"`
Show the user the path (or publish it with the Artifact tool when that tool is available — title "Persona Flag Review", favicon "🚩"; keep the same title on every publish). The digest and the state files under `<vault>/persona/flag-closer/` are gitignored — never `git add` them.
5. **One batch decision pass** — group items 4 per AskUserQuestion call until all are covered; header = slug truncated to 12 chars; question text = kind (`self` | `vault` | `workflow` | `product`; default self), target (plus `surface` on a product proposal), filed date + age, verdict, premise summary (n VERIFIED / m ASSUMED), and a one-line gist of the What. The verbs depend on the kind — each proposal carries them as `verbs` from `collect.js`: a `self` or `vault` proposal is a change the agent applies (Approve / Reject); a `workflow` or `product` proposal is an idea for the user (Accept / Dismiss). For an idea, STILL-VALID means "the situation that prompted it still holds", not "apply it".
- Proposal `self` | `vault`, STILL-VALID or NO-RECIPE → options: **Approve** ("apply exactly as written now") / **Reject** ("delete + record feedback memory") / **Defer** ("leave for next review").
- Proposal `workflow` | `product`, STILL-VALID or NO-RECIPE → options: **Accept** ("keep it — append to persona/backlog.md") / **Dismiss** ("delete + ledger it so it is not filed again") / **Defer**.
- Proposal, STALE (any kind) → options: **Close (stale)** ("finding no longer present — delete file") / **Keep open** / **Defer**.
- Proposal, RECIPE-ERROR → options: **Fix recipe** / **Defer**. NEVER apply a RECIPE-ERROR item. When the item carries `refused`, the recipe never ran: it is outside the read-only grammar (`persona/proposals/README.md`) — say which part in the question.
- Flag → options: **Close flag** ("remove the line from STATE.md") / **Keep** / **File proposal** ("draft a proposals/ entry for the underlying fix").
Log findings are informational — digest only, no question.
6. **Execute each decision — one commit per item that touches tracked files** (only when `<vault>` is a git repository; otherwise apply the file changes and report them). `persona/STATE.md`, `persona/journal/`, `persona/answers.json`, `persona/autoapply.json`, `persona/DISABLED` and `persona/flag-closer/` are ignored by the vault's `.gitignore`: never `git add` them, and never run a pathspec-less `git commit` (it would sweep up whatever the user had staged). Duties and `/propose` never commit what they file, so a proposal file may be untracked: check with `git -C <vault> ls-files --error-unmatch persona/proposals/<file>` first. When that fails, delete the file with `rm` instead of `git rm`, and drop `persona/proposals/<file>` from the commit's pathspec (a lane left with nothing tracked to commit — Fix recipe on an untracked file — edits and does not commit):
- **Approve:** read the proposal; apply its **What** EXACTLY as written (the user's option selection IS the approval for guarded targets — apply nothing beyond the written change). Verify through the gate, never with `sh -c`: `node "$LEDGER" run-recipe '<recheck>'` must print `gone` (finding gone). On `present`, STOP on this item, report it, do not commit; on `error` or `refused: …`, STOP and report the broken recipe. On success, ledger it — `node "$LEDGER" append approved <slug> --kind <kind> --by user --target "<target>" --recheck '<recheck>'`, adding `--class <autoapply_class>` when the proposal declares one (the recipe is what the watchdog re-runs for a week to mark it `verified` or `regressed`; the class is how the ledger's per-class track record accrues) — then `git -C <vault> add <changed paths> persona/ledger.jsonl && git -C <vault> rm -q persona/proposals/<file> && git -C <vault> commit -m "persona: apply approved proposal <slug>" -- <changed paths> persona/ledger.jsonl persona/proposals/<file>`. A changed path on the never-`git add` list above (an `autoapply-<class>` proposal edits `persona/autoapply.json`) is applied and verified like any other but left unstaged: the commit then names only `persona/ledger.jsonl` and the proposal file.
- **Reject:** record the reasoning as a feedback memory (one file in `<vault>/brain/memory/feedback/` + its one-line entry under `## Feedback (how to work)` in `<vault>/MEMORY.md`), ledger it — `node "$LEDGER" append rejected <slug> --kind <kind> --by user --target "<target>" --note "<one-line reason>"` (plus `--class <autoapply_class>` when declared) — then `git -C <vault> add <feedback file> <vault>/MEMORY.md persona/ledger.jsonl && git -C <vault> rm -q persona/proposals/<file>` and commit `git -C <vault> commit -m "chore: reject proposal <slug> — feedback recorded" -- <feedback file> <vault>/MEMORY.md persona/ledger.jsonl persona/proposals/<file>`.
- **Accept** (`workflow` | `product` only): `node "$BACKLOG" append persona/proposals/<file> --by user` (it appends the proposal's What and Why as a `## <filed> · <kind> · <slug>` section and refuses a `self`/`vault` file or a duplicate slug — on a refusal STOP on this item and report it), ledger it — `node "$LEDGER" append accepted <slug> --kind <kind> --by user --target "<target>"` — then `git -C <vault> add persona/backlog.md persona/ledger.jsonl && git -C <vault> rm -q persona/proposals/<file> && git -C <vault> commit -m "persona: accept proposal <slug> to the backlog" -- persona/backlog.md persona/ledger.jsonl persona/proposals/<file>`. Nothing is applied; a product entry names its surface so a later feature run can start from it.
- **Dismiss** (`workflow` | `product` only): ledger it with the reason — `node "$LEDGER" append dismissed <slug> --kind <kind> --by user --target "<target>" --note "<one-line reason>"` — then `git -C <vault> add persona/ledger.jsonl && git -C <vault> rm -q persona/proposals/<file> && git -C <vault> commit -m "chore: dismiss proposal <slug>" -- persona/ledger.jsonl persona/proposals/<file>`. No feedback memory: the reflect duties read `dismissed` from the ledger summary and do not re-file it.
- **Close (stale):** ledger it — `node "$LEDGER" append stale-dropped <slug> --kind <kind> --by user --target "<target>"` (plus `--class <autoapply_class>` when declared) — then `git -C <vault> add persona/ledger.jsonl && git -C <vault> rm -q persona/proposals/<file>`; commit `git -C <vault> commit -m "chore: close stale proposal <slug>" -- persona/ledger.jsonl persona/proposals/<file>`.
- **Close flag:** edit `<vault>/persona/STATE.md` — delete that ONE `- [ ]` line, nothing else. Do not commit: the vault ignores `persona/STATE.md` (and `persona/journal/`), so there is nothing to stage — report the edit in the wrap-up instead. The user commits duty state by hand if they want it tracked.
- **Fix recipe:** edit only the `recheck:` frontmatter line so it re-runs the original check inside the read-only grammar (`node "$LEDGER" run-recipe '<new recipe>'` must not print `refused`); commit `git -C <vault> commit -m "fix: repair recheck recipe for <slug>" -- persona/proposals/<file>`. Do not touch the proposal's What.
- **Defer / Keep:** touch nothing.
7. **Auto-apply lane (earned, dormant until a class is whitelisted):** an item with `autoApply.eligible: true` — its `autoapply_class` is listed in `<vault>/persona/autoapply.json`, its verdict is STILL-VALID and the tick has recorded 2+ consecutive daily confirmations — is applied without a question, each as its own revertible commit, and only when its What applies cleanly and touches no path on step 6's never-`git add` list (otherwise skip it, add nothing, commit nothing, and report it in step 8). Apply the What EXACTLY as written; run `node "$LEDGER" run-recipe '<recheck>'` and require `gone` — on anything else STOP on this item, report it, do not commit. Then ledger it — `node "$LEDGER" append auto-applied <slug> --kind <kind> --class <autoapply_class> --by flag-closer --target "<target>" --recheck '<recheck>'` (the watchdog verifies an auto-applied change exactly like an approval) — and `git -C <vault> add <changed paths> persona/ledger.jsonl && git -C <vault> rm -q persona/proposals/<file> && git -C <vault> commit -m "persona: auto-apply <slug> (class <autoapply_class>)" -- <changed paths> persona/ledger.jsonl persona/proposals/<file>` (the `git add` matches the Approve lane: without it a newly created path is refused by the pathspec). The shipped whitelist is EMPTY, so this lane does nothing until the user approves an `autoapply-<class>` proposal, which the reflect duties file only once a class has `persona.autoapply.minVerified` (3) verified approvals, no regression and no rejection in `ledger.js summary`.
8. **Wrap up:** report one line per decision taken (an Accept names the backlog section, an auto-apply names its class and commit), the digest path, the remaining pending count, and the last line of `node "$LEDGER" summary` (approval rate, open, unverified).
## Guardrails
- Never edit `persona/duties/`, `brain/scripts/persona/`, `persona/IDENTITY.md`, the duty schedules, hooks, or Claude Code settings except as the exact What of an approved proposal in step 6.
- If a proposal's What no longer applies cleanly to the current file state, treat it as STALE regardless of verdict: report, offer Close or Defer — never improvise a variant.