@tryinget/pi-agent-vent 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,11 +45,12 @@ Then in Pi:
45
45
 
46
46
  ## Tool behavior
47
47
 
48
- `agent_vent` supports fourteen actions:
48
+ `agent_vent` supports fifteen actions:
49
49
 
50
50
  | Action | Purpose |
51
51
  |---|---|
52
- | `record` | Append a minimized vent record. Requires `summary`. |
52
+ | `record` | Append a minimized vent record. Requires `summary` and must pass the local anti-junk quality check. |
53
+ | `preview` | Build the sanitized would-be record and anti-junk quality result without writing the local store. |
53
54
  | `summary` | Show recurrence groups and advisory candidate incidents. |
54
55
  | `list` | Show recent local records. |
55
56
  | `path` | Show the store path and boundary contract. |
@@ -99,11 +100,14 @@ The runtime-facing name is intentionally singular: use `agent_vent` for the LLM
99
100
 
100
101
  `pi-agent-vent` is a companion to `pi-autonomous-session-control`, not part of it. ASC/`self` remains the execution and operational-mirror owner; this package owns only local vent diagnostics.
101
102
 
103
+ For the cross-package handoff between ASC `self` diagnostic candidates, toolbox activation, and `agent_vent` preview/record writes, see [Self, toolbox, and agent_vent diagnostic boundary](docs/project/2026-06-05-self-toolbox-agent-vent-diagnostic-boundary.md).
104
+
102
105
  When `pi-toolbox-discovery` is installed, it exposes the `agent_vent` bundle so agents can discover or activate the same-named `agent_vent` tool on demand:
103
106
 
104
107
  ```ts
105
108
  toolbox({ action: "search", query: "vent" })
106
109
  toolbox({ action: "activate", bundle: "agent_vent" })
110
+ agent_vent({ action: "preview", summary: "...", category: "workflow", tool: "..." })
107
111
  ```
108
112
 
109
113
  The owner extension must still be installed/reloaded so the `agent_vent` tool is registered before toolbox can activate it.
@@ -157,6 +161,7 @@ Product docs:
157
161
  - [Vision](docs/project/vision.md)
158
162
  - [Product posture](docs/project/product-posture.md)
159
163
  - [Agent vent design](docs/project/2026-05-21-agent-vent-design.md)
164
+ - [Self/toolbox/agent_vent diagnostic boundary](docs/project/2026-06-05-self-toolbox-agent-vent-diagnostic-boundary.md)
160
165
  - [Implementation plan](docs/project/2026-05-21-agent-vent-implementation-plan.md)
161
166
 
162
167
  ## Package checks
@@ -168,7 +173,9 @@ npm install
168
173
  npm run check
169
174
  ```
170
175
 
171
- For release confidence, `npm run release:check` packs the package, verifies packaged docs/scripts, runs the packaged fallback gate, installs the tarball into an isolated npm prefix for a no-auth shadow registered-tool `agent_vent path` smoke, then installs the tarball with isolated Pi settings and npm prefix/cache, validates that local `npm:<tarball>` is being used only as the install source, and smokes the installed artifact through local-path Pi package discovery with `/agent_vent path`. Use `npm run release:check:quick` for artifact-only checks when live Pi smoke is not available; quick checks still include the no-auth installed shadow registered-tool smoke. These smokes prove artifact/package-loading behavior only, not npm/GitHub publication or provenance.
176
+ For release confidence, `npm run release:check` packs the package, verifies packaged docs/scripts, runs the packaged fallback gate, installs the tarball into an isolated npm prefix for a no-auth shadow registered-tool `agent_vent path` smoke, then installs the tarball with isolated Pi settings and npm prefix/cache, validates that local `npm:<tarball>` is being used only as the install source, and smokes the installed artifact through local-path Pi package discovery with `/agent_vent path`. Use `npm run release:check:quick` for artifact-only checks when live Pi smoke is not available; quick checks still include the no-auth installed shadow registered-tool smoke.
177
+
178
+ Release probes pin `pi-ai` and `pi-coding-agent` to one exact version and fail before installation if that contract diverges from the selected/installed Pi host. Only the isolated artifact/probe installs set `min-release-age=0`, allowing a newly selected exact host contract to be tested while ordinary installs continue to obey the workstation supply-chain cutoff. These smokes prove artifact/package-loading behavior only, not npm/GitHub publication or provenance.
172
179
 
173
180
  Run from monorepo root through the canonical package gate:
174
181
 
@@ -55,3 +55,16 @@ Not selected by default:
55
55
  - Authority: candidate incidents are recommendations only; do not create or imply AK/GitHub/incident mutations.
56
56
  - Validation: `npm run check` from this package, or root `bash ./scripts/package-quality-gate.sh ci packages/pi-agent-vent`.
57
57
  - Optional companions are intentionally not adopted for v0.1: no `fast-check`, Cucumber, Nunjucks, or ts-quality rollout.
58
+
59
+ ## Repo loop validation
60
+
61
+ `@tryinget/pi-agent-vent` adopts `repo-loop-validation-v1` for package-local loop prompt dogfooding. The policy declaration is in `policy/engineering-lane.json`.
62
+
63
+ - `loop-doctor`: `npm run loop-doctor` (non-failing Node/npm/package/git diagnostics)
64
+ - `loop-verify-fast`: `npm run loop-verify-fast` (maps to `quality:pre-commit`)
65
+ - `loop-impact-plan`: `npm run loop-impact-plan` (coarse package impact note plus changed-file listing)
66
+ - `loop-impact-run`: `npm run loop-impact-run` (maps to `npm run check`)
67
+ - `loop-impact-wide`: `npm run loop-impact-wide` (explicit full package gate, also `npm run check`)
68
+ - `loop-landing-check`: `npm run loop-landing-check` (maps to `npm run check`)
69
+
70
+ These commands produce package-local evidence for orchestration prompts. They do not replace Pi runtime install/reload proof, release approval, or monorepo owner authority.
@@ -95,7 +95,8 @@ The tool prompt and runtime validation both bias toward minimal summaries:
95
95
 
96
96
  Actions:
97
97
 
98
- - `record` — append a vent record.
98
+ - `record` — append a vent record after the local anti-junk quality check accepts it.
99
+ - `preview` — build the sanitized would-be record and anti-junk quality result without writing the local store.
99
100
  - `summary` — summarize recurrence groups and candidate incidents.
100
101
  - `list` — show recent records.
101
102
  - `path` — show local store path and data contract.
@@ -112,7 +113,8 @@ Actions:
112
113
 
113
114
  Important behavior:
114
115
 
115
- - `record` requires `summary`.
116
+ - `record` requires `summary` and rejects low-signal generic payloads such as `done`.
117
+ - `preview` returns `recordPreview`, `quality`, and `wouldRecord` without appending JSONL; use it before `record` when the candidate came from `self`, another tool, or a generic/friction-heavy moment.
116
118
  - `severity` defaults to `medium`.
117
119
  - `category` defaults to `other`.
118
120
  - `recurrenceKey` may be supplied by the agent; otherwise it is derived from category + summary.
@@ -164,11 +166,11 @@ This heuristic intentionally errs toward surfacing review candidates, not assert
164
166
 
165
167
  ## Cross-package integration
166
168
 
167
- `pi-agent-vent` remains separate from `pi-autonomous-session-control` by design:
169
+ `pi-agent-vent` remains separate from `pi-autonomous-session-control` by design. The detailed handoff is documented in [Self, toolbox, and agent_vent diagnostic boundary](2026-06-05-self-toolbox-agent-vent-diagnostic-boundary.md):
168
170
 
169
- - ASC/`self` owns operational introspection, subagent/runtime control, and mirror-only handoff/progress summaries.
170
- - `pi-agent-vent` owns local diagnostic vent records, redaction, recurrence grouping, and advisory candidate-incident heuristics.
171
+ - ASC/`self` owns operational introspection, subagent/runtime control, mirror-only handoff/progress summaries, and typed `self.diagnostic_candidate.v1` suggestions.
171
172
  - `pi-toolbox-discovery` owns discovery/activation of the already-registered `agent_vent` tool through the same-named `agent_vent` bundle; `agent-vent` is not a runtime alias.
173
+ - `pi-agent-vent` owns local diagnostic vent records, preview quality checks, redaction, recurrence grouping, and advisory candidate-incident heuristics.
172
174
 
173
175
  This keeps vent persistence from becoming hidden ASC state while still making the capability discoverable during autonomous work.
174
176
 
@@ -0,0 +1,66 @@
1
+ ---
2
+ summary: "Boundary contract for self diagnostic candidates, toolbox activation, and agent_vent local diagnostic records."
3
+ read_when:
4
+ - "Changing ASC self diagnostic-review output."
5
+ - "Changing toolbox agent_vent bundle discovery or activation guidance."
6
+ - "Changing agent_vent preview/record behavior or diagnostic authority wording."
7
+ system4d:
8
+ container: "Cross-package diagnostic handoff boundary."
9
+ compass: "Make recurring friction visible without turning diagnostics into authority."
10
+ engine: "self mirrors candidate -> toolbox activates bundle -> agent_vent previews/records local diagnostics -> human decides owner escalation."
11
+ fog: "Diagnostic candidates and local records can be mistaken for tasks, evidence, incidents, telemetry, or ASC state."
12
+ ---
13
+
14
+ # Self, toolbox, and agent_vent diagnostic boundary
15
+
16
+ ## Purpose
17
+
18
+ This note documents the intended handoff between three Pi extension surfaces:
19
+
20
+ 1. `self` from `pi-autonomous-session-control` notices current-session friction and can return a typed `self.diagnostic_candidate.v1` payload.
21
+ 2. `toolbox` from `pi-toolbox-discovery` can discover or activate the already-registered `agent_vent` tool on demand.
22
+ 3. `agent_vent` from `pi-agent-vent` can preview or record minimized local diagnostic records in its append-only local store.
23
+
24
+ The chain is deliberately not an escalation pipeline. It is a low-cost local diagnostic path for repeated bugs, tool failures, workflow friction, context loss, missing affordances, and similar agent-experience problems.
25
+
26
+ ## Ownership contract
27
+
28
+ | Surface | Owns | Does not own |
29
+ |---|---|---|
30
+ | `self` | Moment-level mirror of the current session; candidate diagnostic payloads; suggested next local actions. | Durable vent records, recurrence truth, AK evidence/tasks, GitHub issues, incidents, telemetry, or owner routing. |
31
+ | `toolbox` | Bundle discovery, risk posture, and active-tool-set changes for already-registered tools. | Registering missing owner tools, validating vent quality, storing diagnostics, or deciding escalation. |
32
+ | `agent_vent` | Local JSONL diagnostic records, preview quality checks, redaction, recurrence grouping, review state, curation, draft-only text, export, and retention lifecycle. | AK evidence/tasks, GitHub issues, real incidents, external telemetry, ASC/self state, publication, or owner-system lifecycle. |
33
+
34
+ ## Safe handoff sequence
35
+
36
+ Use this sequence when a session notices recurring or high-friction behavior worth possible local memory:
37
+
38
+ ```ts
39
+ self({ query: "What friction just happened?" })
40
+ toolbox({ action: "activate", bundle: "agent_vent" })
41
+ agent_vent({ action: "preview", summary: "...", category: "...", tool: "...", packageName: "..." })
42
+ agent_vent({ action: "record", summary: "...", category: "...", tool: "...", packageName: "..." })
43
+ ```
44
+
45
+ Rules:
46
+
47
+ - `self` may prefill or suggest an `agent_vent` payload, but it must not write the record internally.
48
+ - `toolbox` activation only makes the `agent_vent` tool callable; it does not create or preview a diagnostic record.
49
+ - `agent_vent action=preview` sanitizes the would-be record and runs the anti-junk quality check without writing the store.
50
+ - `agent_vent action=record` writes only if the local quality check accepts the payload.
51
+ - Generic low-signal summaries such as `done` are rejected for `record`; use `preview` to inspect issues and warnings before writing.
52
+ - Human/operator judgment still decides whether any recurrence should become an AK task, GitHub issue, incident review, evidence record, publication, or owner-surface handoff.
53
+
54
+ ## Copy wording for boundaries
55
+
56
+ Recommended short wording:
57
+
58
+ > Diagnostic review is mirror/local only: `self` can propose a candidate, `toolbox` can activate the `agent_vent` capability, and `agent_vent` can preview or write local diagnostic memory. None of these actions create AK evidence/tasks, GitHub issues, incidents, external telemetry, publication, owner routing, or ASC/self state.
59
+
60
+ Use stronger wording when a durable local write happened:
61
+
62
+ > A local `agent_vent` record was written to the operator's Pi diagnostic store. This is recurrence memory for review, not canonical evidence, task truth, issue state, incident declaration, telemetry, publication, or owner-system mutation.
63
+
64
+ ## Review and escalation posture
65
+
66
+ `agent_vent` recurrence groups and candidate incidents mean “worth human review,” not “incident declared.” Draft outputs are paste-ready text only. Exports are diagnostic projections only. If a human decides a local recurrence deserves owner action, use the owning surface directly and record evidence there according to that owner’s rules.
@@ -51,7 +51,7 @@ When an agent keeps hitting the same bug, missing affordance, brittle workflow,
51
51
 
52
52
  - maturity: `local diagnostic alpha, review-and-retention safety hardened; privacy, review-command, outcome-follow-up, review-filter, review-compare, follow-up-scope, export-scope, export-follow-up, review-decision-legibility, destructive-selection, retention-history, public-contract parity, unpacked-artifact contract, installed-command smoke, installed shadow registered-tool smoke, and release-metadata alignment membranes verified`
53
53
  - current capability baseline: local append-only vent capture with optional local tool/package facets, recurrence grouping, local facet summary, local operator review queue with fail-closed-before-store-read command syntax and read-only category/tag/tool/package facet filters, read-only per-state review outcome follow-up buckets, read-only cross-state review comparison without archive/restore tokens, explicit derived local decision-posture projections, curation-aware recurrence resolution for review-state commands and record feedback, filter-preserving supported follow-up commands including record/state-scoped facet export, export-local-follow-up guidance without archive/restore tokens, read-only reviewed-group retention candidate planning without archive tokens, read-only retention receipt history with rollback-candidate restore command reconstruction, advisory human-review hints, quoted state-aware local next-action guidance that round-trips legacy recurrence keys, bounded representative-sample detail, review-state events, append-only recurrence curation projections with remove/undo events, diagnostic-state load membrane with privacy metadata recomputation, facet-aware draft-only owner-surface text generation, lifecycle stats/export projections, lock/hash-guarded confirmation-gated retention archive/restore with duplicate-id-safe record selection, local backup receipts, and rollback safeguards, advisory candidate-incident heuristic, redaction/minimization, `/agent_vent` inspection command, toolbox discovery, ASC/self companion routing, self-contained public-artifact validation for advertised package scripts/docs, no-auth installed-artifact shadow registered-tool `agent_vent path` release smoke with isolated npm prefix/cache and vent storage, installed-tarball local-path package-discovery `/agent_vent path` release smoke with isolated Pi settings, npm prefix/cache, and vent store, explicit local `npm:<tarball>` install-source validation, and package-local release metadata alignment checks for `repository.directory`, `x-pi-template.workspacePath`, and `x-pi-template.releaseComponent`
54
- - release posture: first published package release is `0.1.0` on npm with `latest` currently resolving to `0.1.0`; source/package version `0.1.1` is prepared to remove the `/agent-vent` command alias and keep runtime-facing naming singularly `agent_vent`; unpacked tarball contract has artifact-local `npm install && npm run check` proof, artifact-only quick release checks install the packed tarball into an isolated npm prefix and execute the installed artifact's registered `agent_vent` tool `action=path` through a shadow import against isolated vent storage without Pi auth, full release checks additionally validate local `npm:<tarball>` as the install source and smoke the installed packed artifact through local-path Pi package discovery by running `/agent_vent path` with isolated Pi settings, isolated npm prefix/cache, and isolated vent storage, and package-local structure validation fails closed on release metadata drift against `.copier-answers.yml`; post-publication registry smoke installed `@tryinget/pi-agent-vent@0.1.0` into an isolated npm prefix and verified the installed artifact and shadow registered-tool `path` behavior
54
+ - release posture: first published package release is `0.1.0` on npm; `0.1.1` removed the `/agent-vent` command alias and kept runtime-facing naming singularly `agent_vent`; source/package version `0.1.2` hardens extension load against stale review-state imports during reload; unpacked tarball contract has artifact-local `npm install && npm run check` proof, artifact-only quick release checks install the packed tarball into an isolated npm prefix and execute the installed artifact's registered `agent_vent` tool `action=path` through a shadow import against isolated vent storage without Pi auth, full release checks additionally validate local `npm:<tarball>` as the install source and smoke the installed packed artifact through local-path Pi package discovery by running `/agent_vent path` with isolated Pi settings, isolated npm prefix/cache, and isolated vent storage, and package-local structure validation fails closed on release metadata drift against `.copier-answers.yml`; post-publication registry smoke installed `@tryinget/pi-agent-vent@0.1.0` into an isolated npm prefix and verified the installed artifact and shadow registered-tool `path` behavior
55
55
  - current strategic line: harden the local review workflow before adding owner-surface escalation adapters
56
56
 
57
57
  ## Product success criteria
@@ -114,6 +114,8 @@ The highest-leverage product line is:
114
114
  local vent capture -> operator review queue -> draft-only owner routing -> human-approved escalation
115
115
  ```
116
116
 
117
+ For visible self-evolution work, keep `agent_vent` as recurrence memory and review queue only. The DRY routing map lives in the root `docs/project/visible-self-evolution-spine.md` spine; orchestrator may project verified evidence, while AK/society owner surfaces retain durable authority.
118
+
117
119
  Do not add automatic GitHub/AK/incident writers. The local facet summary, fail-closed facet-filtered local review queue, per-state review outcome follow-up, read-only cross-state review comparison, explicit local decision posture, filter-preserving supported follow-up commands, record/state-scoped facet export, export-local-follow-up guidance, read-only retention-candidate planning, read-only retention-history receipt projection, advisory human-review hints, quoted state-aware next-action guidance, bounded review-detail samples, curation-aware recurrence resolution, facet-aware draft-only routing, retention archive/restore, and privacy membrane now have package validation; remaining product depth should refine operator comprehension only where it does not broaden authority. Hard-delete beyond backup-backed archive is decided out of v0.1: permanent removal remains operator-owned filesystem/data-lifecycle control unless a future decision accepts a narrower purge design.
118
120
 
119
121
  Current proof: `npm run check` passes with 80 package tests plus release dry-run, packaged Markdown link checks, an unpacked-tarball `npm install && npm run check` contract smoke that runs the packaged fallback gate from inside the artifact, an artifact-only no-auth installed shadow registered-tool `agent_vent path` no-store-read smoke, and a full installed-tarball local-path package-discovery `/agent_vent path` smoke using isolated `PI_CODING_AGENT_DIR`, isolated npm prefix/cache, and `PI_AGENT_VENT_DIR`; docs strict check passes, `git diff --check` passes, and historical dogfood covered curation resolution, export posture, and live `pi install` reload behavior. Validation now covers quoted rollback commands, complete retention token inputs, stale-token/stale-restore failures, path-escape/symlink backup failures, receipt-failure rollback, retention-history restore-candidate reconstruction without active-store reads, export follow-up command quoting without archive/restore tokens or owner-routing claims, review decision-posture projection without resolution/assignment/evidence/incident claims, curation-aware recurrence resolution for review state and record feedback, stale lock cleanup, backup restore, duplicate-id-safe retention archive selection, retention-candidate planning without archive tokens, retention-candidate and compare tool-schema/command-contract parity, filter-preserving supported compare follow-ups, record/state-scoped facet export without owner-routing claims, mixed-group export non-broadening, empty export filters failing closed before store reads, tag/facet privacy metadata recomputation, hostile legacy JSONL privacy recomputation, fail-closed review/outcome/compare/export/retention-candidate/history syntax before store reads including empty filters, invalid review category/state handling, explicit per-state outcome/compare limits, quoted legacy recurrence-key command round trips, tool-only maintainer-note hints, reference-style packaged Markdown links, fail-closed `files[]` wildcard handling, public artifact script viability, release metadata alignment with `.copier-answers.yml`, local `npm:<tarball>` install-source validation, isolated installed-command smoke output, local-path package-discovery loading from the installed artifact, shadow registered-tool execution from the installed artifact, and registered-tool `path` no-store-read/no-store-write behavior with symlinked active stores.
@@ -44,6 +44,10 @@ agent notices recurring friction
44
44
  -> owner system receives a human-approved draft only when appropriate
45
45
  ```
46
46
 
47
+ For self-evolution loops, `agent_vent` is the recurrence-memory surface after ASC/self has produced a diagnostic candidate.
48
+ It is not the loop executor, evaluator, or escalation authority.
49
+ Use the root `docs/project/visible-self-evolution-spine.md` spine and the cross-package [self/toolbox/agent_vent diagnostic boundary](./2026-06-05-self-toolbox-agent-vent-diagnostic-boundary.md) for the DRY owner map.
50
+
47
51
  Near-term product work should make the review step better rather than broadening authority. Useful next surfaces include:
48
52
 
49
53
  - `/agent_vent review` for an operator-facing review queue;
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { Type } from "typebox";
4
4
  import {
5
5
  appendCurationEvent,
@@ -7,6 +7,7 @@ import {
7
7
  appendVentRecord,
8
8
  archiveRecurrenceGroup,
9
9
  assertCanCurateRecurrence,
10
+ assessVentRecordQuality,
10
11
  buildEscalationDraft,
11
12
  buildFacetSummary,
12
13
  buildLifecycleSnapshot,
@@ -48,17 +49,19 @@ import {
48
49
  normalizeRetentionAction,
49
50
  normalizeReviewState,
50
51
  RETENTION_ACTIONS,
51
- REVIEW_STATES,
52
52
  readRetentionEvents,
53
+ resolveCategoryFilter,
53
54
  resolveRecurrenceGroup,
54
55
  restoreRetentionBackup,
55
56
  SEVERITIES,
57
+ REVIEW_STATES as STORE_REVIEW_STATES,
56
58
  summarizeRecords,
57
59
  summarizeReviewQueue,
58
60
  } from "../src/vent-store.js";
59
61
 
60
62
  const ACTIONS = [
61
63
  "record",
64
+ "preview",
62
65
  "summary",
63
66
  "list",
64
67
  "path",
@@ -74,7 +77,24 @@ const ACTIONS = [
74
77
  "retention",
75
78
  ] as const;
76
79
  const EXPORT_FORMATS = ["markdown", "json"] as const;
80
+ const FALLBACK_REVIEW_STATES = ["new", "acknowledged", "dismissed", "escalation_drafted"] as const;
81
+ const REVIEW_STATES = Array.isArray(STORE_REVIEW_STATES)
82
+ ? STORE_REVIEW_STATES
83
+ : FALLBACK_REVIEW_STATES;
77
84
  const RETENTION_CANDIDATE_STATES = ["reviewed", "all", ...REVIEW_STATES] as const;
85
+ const CATEGORY_ALIAS_INPUTS = [
86
+ "workflow_friction",
87
+ "operator_friction",
88
+ "process_friction",
89
+ "missing_affordance",
90
+ "missing_feature",
91
+ "documentation_gap",
92
+ "docs_gap",
93
+ "context_window",
94
+ "context_friction",
95
+ "tooling_friction",
96
+ ] as const;
97
+ const CATEGORY_INPUTS = [...CATEGORIES, ...CATEGORY_ALIAS_INPUTS] as const;
78
98
 
79
99
  const AgentVentParams = Type.Object({
80
100
  action: Type.Optional(
@@ -88,9 +108,10 @@ const AgentVentParams = Type.Object({
88
108
  ),
89
109
  category: Type.Optional(
90
110
  Type.Union(
91
- CATEGORIES.map((category) => Type.Literal(category)),
111
+ CATEGORY_INPUTS.map((category) => Type.Literal(category)),
92
112
  {
93
- description: "Local category for the frustration pattern.",
113
+ description:
114
+ "Local category for the frustration pattern. Common aliases are accepted and normalized to canonical categories.",
94
115
  },
95
116
  ),
96
117
  ),
@@ -231,11 +252,12 @@ export default function agentVentExtension(pi: ExtensionAPI) {
231
252
  name: "agent_vent",
232
253
  label: "Agent Vent",
233
254
  description:
234
- "Record, review, and inspect local agent frustration events so recurring bugs, workflow friction, and missing affordances become visible.",
255
+ "Record, preview, review, and inspect local agent frustration events so recurring bugs, workflow friction, and missing affordances become visible.",
235
256
  promptSnippet:
236
- "Record minimized local frustration events and review recurring patterns without creating incidents, tasks, issues, evidence records, or telemetry.",
257
+ "Preview or record minimized local frustration events and review recurring patterns without creating incidents, tasks, issues, evidence records, or telemetry.",
237
258
  promptGuidelines: [
238
259
  "Use agent_vent when you encounter recurring agent frustration, long-lived bugs, repeated tool/runtime failures, context-loss patterns, or missing affordances worth later human review.",
260
+ "Use action=preview before action=record when the diagnostic may be generic, low-signal, or copied from another tool; previews run the anti-junk quality check without writing the local store.",
239
261
  "Use action=review to inspect the local recurrence review queue; include recurrenceKey to inspect bounded representative samples for one local group; optionally filter review by local category, tag, tool, or package facets; use action=set_review to mark a recurrence group as new, acknowledged, dismissed, or escalation_drafted.",
240
262
  "Use action=outcomes for read-only post-review follow-up across local review-state buckets; outcome guidance is local diagnostic UX only, not owner routing or external completion.",
241
263
  "Use action=compare for a read-only cross-state review comparison before export, retention planning, or draft-only handoff; comparison output emits no archive/restore tokens and mutates nothing.",
@@ -249,7 +271,8 @@ export default function agentVentExtension(pi: ExtensionAPI) {
249
271
  "When calling agent_vent, summarize minimally and never include secrets, credentials, private user payloads, or long raw logs.",
250
272
  ],
251
273
  parameters: AgentVentParams,
252
- async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
274
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
275
+ throwIfCancelled(signal);
253
276
  const storePath = defaultStorePath();
254
277
  const reviewPath = defaultReviewPath();
255
278
  const curationPath = defaultCurationPath();
@@ -271,13 +294,29 @@ export default function agentVentExtension(pi: ExtensionAPI) {
271
294
  );
272
295
  }
273
296
 
274
- if (action === "record") {
297
+ if (action === "preview" || action === "record") {
275
298
  const sessionFile = ctx.sessionManager.getSessionFile();
276
299
  const record = createVentRecord(params, {
277
300
  cwd: ctx.cwd,
278
301
  sessionFile: sessionFile ? path.basename(sessionFile) : undefined,
279
- source: "agent_vent_tool",
302
+ source: action === "preview" ? "agent_vent_preview" : "agent_vent_tool",
280
303
  });
304
+ const quality = assessVentRecordQuality(params, record);
305
+ if (action === "preview") {
306
+ return textResult(formatRecordPreview(record, quality), {
307
+ action,
308
+ storePath,
309
+ recordPreview: record,
310
+ quality,
311
+ wouldRecord: quality.recordable,
312
+ });
313
+ }
314
+ if (!quality.recordable) {
315
+ throw new Error(
316
+ `agent_vent record rejected by anti-junk quality check: ${quality.issues.join("; ")}`,
317
+ );
318
+ }
319
+ throwIfCancelled(signal);
281
320
  appendVentRecord(storePath, record);
282
321
  const state = loadDiagnosticState({
283
322
  storePath,
@@ -327,6 +366,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
327
366
  });
328
367
  }
329
368
 
369
+ throwIfCancelled(signal);
330
370
  const state = loadDiagnosticState({
331
371
  storePath,
332
372
  reviewPath,
@@ -363,6 +403,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
363
403
  };
364
404
  assertCanCurateRecurrence(records, curationEvents, input);
365
405
  const event = createCurationEvent(input, { source: "agent_vent_tool" });
406
+ throwIfCancelled(signal);
366
407
  appendCurationEvent(curationPath, event);
367
408
  const targetText = event.targetRecurrenceKey ? ` -> ${event.targetRecurrenceKey}` : "";
368
409
  const text = [
@@ -396,6 +437,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
396
437
  },
397
438
  { source: "agent_vent_tool" },
398
439
  );
440
+ throwIfCancelled(signal);
399
441
  appendReviewEvent(reviewPath, event);
400
442
  const text = [
401
443
  `Set local review state for ${event.recurrenceKey} to ${event.state}.`,
@@ -606,6 +648,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
606
648
  });
607
649
  }
608
650
  if (retentionAction === "archive") {
651
+ throwIfCancelled(signal);
609
652
  const result = archiveRecurrenceGroup({
610
653
  storePath,
611
654
  reviewPath,
@@ -628,6 +671,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
628
671
  retention: result,
629
672
  });
630
673
  }
674
+ throwIfCancelled(signal);
631
675
  const result = restoreRetentionBackup({
632
676
  storePath,
633
677
  retentionPath,
@@ -733,15 +777,31 @@ function registerAgentVentCommand(pi: ExtensionAPI, name: string, description: s
733
777
  description,
734
778
  handler: async (args, ctx) => {
735
779
  const output = handleCommand(args);
736
- if (ctx.hasUI) {
737
- ctx.ui.notify(output, "info");
738
- } else {
780
+ if (!ctx.hasUI) {
739
781
  console.log(output);
782
+ } else if (isLongCommandOutput(output)) {
783
+ pi.sendMessage({
784
+ customType: "agent-vent-command",
785
+ content: output,
786
+ display: true,
787
+ details: { command: name },
788
+ });
789
+ ctx.ui.notify("agent_vent output added to the session transcript", "info");
790
+ } else {
791
+ ctx.ui.notify(output, "info");
740
792
  }
741
793
  },
742
794
  });
743
795
  }
744
796
 
797
+ function isLongCommandOutput(output: string): boolean {
798
+ return output.length > 500 || output.split("\n").length > 8;
799
+ }
800
+
801
+ function throwIfCancelled(signal: AbortSignal | undefined): void {
802
+ if (signal?.aborted) throw new Error("agent_vent cancelled");
803
+ }
804
+
745
805
  function handleCommand(args: string) {
746
806
  const tokens = splitCommandArgs(args);
747
807
  const action = tokens[0] || "summary";
@@ -755,6 +815,7 @@ function handleCommand(args: string) {
755
815
  return [
756
816
  "agent_vent commands:",
757
817
  " /agent_vent summary Show recurrence groups and candidate incidents.",
818
+ " LLM tool action=preview Preview a local diagnostic record and anti-junk quality check without writing the store.",
758
819
  " /agent_vent list [limit] Show recent local vent records.",
759
820
  " /agent_vent facets [limit] Show read-only local category/tag/tool/package facets.",
760
821
  " /agent_vent review [state|all] [limit] [category=bug] [tag=reload] [tool=pi-reload] [package=tryinget-pi-agent-vent]",
@@ -1080,8 +1141,8 @@ function parseReviewListTokens(tokens: string[], options: { allowReviewedState?:
1080
1141
  invalidFilters.push("category=");
1081
1142
  continue;
1082
1143
  }
1083
- const normalizedCategory = value.toLowerCase().replaceAll("-", "_");
1084
- if (CATEGORIES.includes(normalizedCategory)) filters.category = normalizedCategory;
1144
+ const category = resolveCategoryFilter(value);
1145
+ if (category) filters.category = category;
1085
1146
  else invalidFilters.push(`category=${value}`);
1086
1147
  } else if (key === "tool") {
1087
1148
  if (!value) {
@@ -1370,6 +1431,24 @@ function formatDiagnosticWarnings(state: Record<string, unknown>) {
1370
1431
  : "";
1371
1432
  }
1372
1433
 
1434
+ function formatRecordPreview(
1435
+ record: Record<string, unknown>,
1436
+ quality: { recordable?: boolean; issues?: string[]; warnings?: string[]; boundary?: string },
1437
+ ) {
1438
+ const issues = quality.issues || [];
1439
+ const warnings = quality.warnings || [];
1440
+ return [
1441
+ `Agent vent preview: ${quality.recordable ? "recordable" : "not recordable"} (${record.severity || "medium"}/${record.category || "other"}) under ${record.recurrenceKey || "unknown"}.`,
1442
+ `Summary: ${record.summary || "(no summary)"}`,
1443
+ issues.length ? `Issues: ${issues.join("; ")}` : "Issues: none",
1444
+ warnings.length ? `Warnings: ${warnings.join("; ")}` : "Warnings: none",
1445
+ "No local diagnostic record was written. Use action=record only if this is a recurring or review-worthy diagnostic, not an ordinary progress update.",
1446
+ `Boundary: ${quality.boundary || "local diagnostic preview only"}`,
1447
+ ].join("\n");
1448
+ }
1449
+
1450
+ export const _test = { isLongCommandOutput, throwIfCancelled };
1451
+
1373
1452
  function textResult(text: string, details: Record<string, unknown>) {
1374
1453
  return {
1375
1454
  content: [{ type: "text" as const, text }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryinget/pi-agent-vent",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Local pi tool for agents to record recurring frustrations, bugs, and workflow friction without creating incidents or external telemetry",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -28,7 +28,7 @@
28
28
  "access": "public"
29
29
  },
30
30
  "engines": {
31
- "node": ">=22"
31
+ "node": ">=22.19.0"
32
32
  },
33
33
  "scripts": {
34
34
  "fix": "bash ./scripts/quality-gate.sh fix",
@@ -43,7 +43,13 @@
43
43
  "docs:list:workspace": "bash ./scripts/docs-list.sh --workspace --discover",
44
44
  "docs:list:json": "bash ./scripts/docs-list.sh --json",
45
45
  "release:check": "bash ./scripts/release-check.sh",
46
- "release:check:quick": "SKIP_PI_SMOKE=1 bash ./scripts/release-check.sh"
46
+ "release:check:quick": "SKIP_PI_SMOKE=1 bash ./scripts/release-check.sh",
47
+ "loop-doctor": "bash -lc 'node --version; npm --version; npm pkg get name version >/dev/null; git status --short -- . || true; exit 0'",
48
+ "loop-verify-fast": "npm run quality:pre-commit",
49
+ "loop-impact-plan": "bash -lc 'echo \"loop-impact-plan: package-local impact planner is coarse; run npm run loop-impact-run for the full package gate.\"; git status --short -- . || true'",
50
+ "loop-impact-run": "npm run check",
51
+ "loop-impact-wide": "npm run check",
52
+ "loop-landing-check": "npm run check"
47
53
  },
48
54
  "files": [
49
55
  "extensions/agent-vent.ts",
@@ -60,6 +66,7 @@
60
66
  "docs/project/product-posture.md",
61
67
  "docs/project/2026-05-21-agent-vent-design.md",
62
68
  "docs/project/2026-05-21-agent-vent-implementation-plan.md",
69
+ "docs/project/2026-06-05-self-toolbox-agent-vent-diagnostic-boundary.md",
63
70
  "docs/project/extension-sop.md",
64
71
  "docs/project/trusted-publishing.md",
65
72
  "docs/adr/2026-05-22-agent-vent-retention-delete-policy.md"
@@ -79,17 +86,19 @@
79
86
  "releaseConfigMode": "component"
80
87
  },
81
88
  "devDependencies": {
82
- "@biomejs/biome": "2.3.14"
89
+ "@biomejs/biome": "2.3.14",
90
+ "@earendil-works/pi-ai": "0.80.6",
91
+ "@earendil-works/pi-coding-agent": "0.80.6"
83
92
  },
84
93
  "overrides": {
85
94
  "fast-xml-parser": "5.3.6"
86
95
  },
87
96
  "peerDependencies": {
88
- "@mariozechner/pi-ai": "*",
89
- "@mariozechner/pi-coding-agent": "*",
97
+ "@earendil-works/pi-ai": "*",
98
+ "@earendil-works/pi-coding-agent": "*",
90
99
  "typebox": "*"
91
100
  },
92
101
  "dependencies": {
93
- "typebox": "^1.0.0"
102
+ "typebox": "*"
94
103
  }
95
104
  }
@@ -17,6 +17,18 @@
17
17
  "dependency-governance",
18
18
  "specification-and-dsls",
19
19
  "engineering-reasoning"
20
- ]
20
+ ],
21
+ "loop_validation": {
22
+ "version": "repo-loop-validation-v1",
23
+ "contract_doc": "docs/engineering.local.md#repo-loop-validation",
24
+ "commands": {
25
+ "loop-doctor": "npm run loop-doctor",
26
+ "loop-verify-fast": "npm run loop-verify-fast",
27
+ "loop-impact-plan": "npm run loop-impact-plan",
28
+ "loop-impact-run": "npm run loop-impact-run",
29
+ "loop-impact-wide": "npm run loop-impact-wide",
30
+ "loop-landing-check": "npm run loop-landing-check"
31
+ }
32
+ }
21
33
  }
22
34
  }
@@ -1,8 +1,8 @@
1
1
  ---
2
- summary: "Monorepo package implementation planning prompt template."
2
+ summary: "pi-agent-vent implementation planning prompt template."
3
3
  read_when:
4
4
  - "Using or updating the monorepo package implementation-planning prompt template."
5
- description: Draft an implementation plan for a requested change
5
+ description: Draft an implementation plan for a requested pi-agent-vent change
6
6
  system4d:
7
7
  container: "Prompt template for implementation planning."
8
8
  compass: "Turn requests into actionable, risk-aware plans."
@@ -10,7 +10,7 @@ system4d:
10
10
  fog: "Hidden constraints unless assumptions are surfaced."
11
11
  ---
12
12
 
13
- Create an implementation plan for this request: $@
13
+ Create a pi-agent-vent implementation plan for this request: $@
14
14
 
15
15
  Include:
16
16
  - Scope and non-goals
@@ -1,8 +1,8 @@
1
1
  ---
2
- summary: "Monorepo package security review prompt template."
2
+ summary: "pi-agent-vent security review prompt template."
3
3
  read_when:
4
4
  - "Using or updating the monorepo package security-review prompt template."
5
- description: Review a change for security risks and mitigations
5
+ description: Review a pi-agent-vent change for security risks and mitigations
6
6
  system4d:
7
7
  container: "Prompt template for security-focused review."
8
8
  compass: "Identify practical vulnerabilities before release."
@@ -10,7 +10,7 @@ system4d:
10
10
  fog: "Partial context can hide exploit paths."
11
11
  ---
12
12
 
13
- Review this change for security concerns: $@
13
+ Review this pi-agent-vent change for security concerns: $@
14
14
 
15
15
  Focus on:
16
16
  - Input validation and injection risk