Skip to content

Add insights plugin for private local task reports (0.1.0) - #62

Merged
gering merged 4 commits into
mainfrom
task/add-plugin-insights-report
Sep 18, 2026
Merged

gering merged 4 commits into
mainfrom
task/add-plugin-insights-report

Conversation

@gering

@gering gering commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Summary

New standalone insights plugin (0.1.0). /insights:report [free text] records a private, local report on the work so far: mid-task, blocked, finished, or with no task at all. The goal is process and plugin learning, not worker ranking.

  • Schema insights.report/v1. report_trigger and task_status are separate fields. The project is identified by its canonical main checkout, so worktrees group together while same-named repos stay distinct (a labelled directory fallback covers non-git projects). Each report carries a standalone work summary, the reporter's and other participants' models, runtime and effort, and the skills that actually ran with their execution-time plugin versions. Every unknown value is explicit ({value: null, reason}). The retrospective covers outcome, domain vs. tooling difficulty, what worked, friction (causes stay hypotheses), interventions, and model-authored suggestions. Plugin-specific details (swarm, work-system, pr-flow, knowledge-system) are included only when that plugin was used.
  • scripts/insights.py (Python stdlib) is the single write, read, and list path for this producer and for later ones. Reports go to ~/.gering-plugins/insights/reports/ (outside ~/.claude, so they survive plugin uninstalls and non-Claude workers can reach them later):
    • private permissions; existing store directories are refused if not private, never chmod'ed
    • atomic link() publication that never overwrites; an identical retry returns unchanged, a collision exits 3
    • malformed stored files are reported honestly; reads are bounded
    • credentials are redacted, URLs sanitized, control and bidi characters rejected
    • skeleton produces a complete draft that fails validation until filled in
  • Docs: docs/REPORT-CONTRACT.md (schema, provenance rules, producer contract) and docs/RETROSPECTIVE.md (adaptive, evidence-only prompts). Registered in the marketplace, the README files, CHANGELOG and CLAUDE.md. A knowledge entry records the design decisions.
  • Scope: manual reports only. The worker/Manager handoff producers are the separate follow-up task integrate-insights-handoffs. This PR adds no hooks, always-loaded rules, ratings or analytics.

Verification

  • python3 plugins/insights/scripts/test_insights.py: 23/23 hermetic tests pass. HOME, XDG and the store point to a sandbox, and the tests never touch the real store. Coverage:

    • schema, partial and unknown metadata
    • same-repo worktrees vs. unrelated same-named repos; no-task and non-git reports
    • participant/model changes and version provenance
    • concurrent writers; retry vs. collision; corrupt, oversize, FIFO and symlinked store files
    • failed writes never reported as success
    • redaction edge cases; skeleton behavior
  • Three historical incident fixtures validate (partial swarm voice loss, repeat question vs. new approval, dispatch timeout with a worker that kept running). They are labelled as history, not as current bug status.

  • Mutation check: making the collision check fail-open, or replacing link with os.replace, makes 2 and 3 tests fail respectively.

  • python3 scripts/check-structure.py: OK (0 errors; the only warning is the existing pr-flow open description length).

  • Demonstration in an isolated store (INSIGHTS_STORE_DIR), following the documented helper path:

    • a mid-task snapshot of this very lane, written from the worktree; the project resolves to the main checkout
    • a no-task report from a non-git directory (ref_source=cwd)
    • a follow-up report linked to the first, written via skeleton → draft file → write

    All three were read back and listed; the files are 0600 in a 0700 directory.

  • Not verified: the actual installed /insights:report slash command. The plugin isn't installed in this session's plugin cache; the skill flow was exercised by hand through the same helper calls.

Review

Two local /swarm:review --fix rounds (Claude, codex and grok; Kimi not opted in). The mandate budget of 2 is now used up.

  • Round 1: full delta, excluding the fixture JSON to stay under the prompt size where grok previously lost clusters. 15 findings: 12 agreed, 2 partial, 1 rejected. Fixed, among others:
    • a shell-heredoc injection in the skill; drafts are now passed as files
    • a crash on malformed URL ports
    • chmod of a user-supplied override directory
    • token query parameters left in free text
    • IDs that accepted a trailing newline
    • loose Fact variants
    • an unbounded read path
    • a new skeleton subcommand
  • Round 2: scoped to the fix delta. 14 findings: 11 agreed, 2 partial, 1 rejected. Fixed:
    • redaction breaking project.key for sk-… paths; now fixpoint redaction that skips identifier fields
    • the bare private-key header regex eating the rest of the text
    • a FIFO or growing-file race in the reader
    • skeleton project and task fallback
    • draft cleanup order and doc wording
  • Rejected both times: batching the git forks in context/skeleton. The cost is milliseconds on a manual command, so clarity wins.
  • The round-2 fixes are covered by new regression tests but were not re-reviewed, because the review budget is exhausted.

🤖 Generated with Claude Code

https://claude.ai/code/session_0156cvkkQ57b813ESqkKmmiX

gering and others added 4 commits September 17, 2026 12:25
- /insights:report [free text] records a mid-task, blocked, finished or
  task-less report: verbatim user feedback or an agent snapshot
- insights.report/v1 schema: trigger vs task status, main-checkout project
  identity, standalone work summary, reporter/participant models and
  evidenced plugin versions, explicit unknowns with reasons
- insights.py: single validate/write/read/list path; private XDG store,
  atomic no-overwrite publication, idempotent retries, loud collisions,
  honest malformed-file reporting, URL sanitizing, credential rejection
- Hermetic tests plus three historical incident fixtures; contract and
  retrospective docs; marketplace, README, CHANGELOG, CLAUDE.md entries

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0156cvkkQ57b813ESqkKmmiX
- Pass drafts as files written by the host tool; never a shell heredoc
  (a terminator line in user feedback would execute as shell commands)
- Redact credential shapes, incl. token query params, instead of
  rejecting them, so verbatim feedback stays storable; report count
- Refuse symlinked, foreign or group/other-readable store dirs instead
  of chmod'ing an existing override directory
- Parse URLs without .port/.hostname (no crash on bad ports, keep IPv6)
- fullmatch IDs/timestamps, whole seconds only, exclusive Fact variants,
  reject bidi controls and Unicode line separators
- One size-capped load path for read/list; positive --limit only
- Add `skeleton`: complete draft with observed values that fails
  validation until filled

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0156cvkkQ57b813ESqkKmmiX
- Redact to a fixpoint, keep trailing punctuation, redact a bare key
  header only, and exempt helper-derived identifiers (an sk- repo path
  broke project.key); redact before URL sanitizing so counts are honest
- Parse URLs with an anchored regex instead of urlsplit
- Read stored reports through one bounded fd: regular files only, no
  symlinks, no FIFO hangs; also for ID-collision comparison
- skeleton embeds the resolved project and falls back to the task/
  branch name; skill removes the draft right after write
- Knowledge entry for the insights store decisions

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0156cvkkQ57b813ESqkKmmiX
Outside ~/.claude so reports survive plugin uninstalls and stay reachable
for non-Claude producers; drops the XDG resolution and the path-level v1
(the schema version lives in each report).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0156cvkkQ57b813ESqkKmmiX
@gering
gering force-pushed the task/add-plugin-insights-report branch from 804c661 to 043e297 Compare September 17, 2026 10:29
@gering
gering merged commit 2667b93 into main Sep 18, 2026
1 check failed
@gering
gering deleted the task/add-plugin-insights-report branch September 20, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant