@tryinget/pi-agent-vent 0.1.2 → 0.2.1
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 +10 -3
- package/docs/engineering.local.md +13 -0
- package/docs/project/2026-05-21-agent-vent-design.md +7 -5
- package/docs/project/2026-06-05-self-toolbox-agent-vent-diagnostic-boundary.md +69 -0
- package/docs/project/product-posture.md +2 -0
- package/docs/project/vision.md +4 -0
- package/extensions/agent-vent.ts +95 -13
- package/package.json +16 -7
- package/policy/engineering-lane.json +13 -1
- package/prompts/{implementation-planning.md → pi-agent-vent-implementation-planning.md} +3 -3
- package/prompts/{security-review.md → pi-agent-vent-security-review.md} +3 -3
- package/scripts/docs-list.sh +5 -0
- package/scripts/quality-gate.sh +5 -0
- package/scripts/release-artifact-check.mjs +35 -5
- package/scripts/release-check.sh +136 -55
- package/scripts/release-smoke-check.mjs +32 -1
- package/scripts/release-smoke.sh +17 -15
- package/scripts/validate-structure.mjs +8 -3
- package/scripts/validate-structure.sh +7 -2
- package/src/vent-store.js +85 -6
- package/tests/agent-vent-extension.test.js +190 -1
- package/tests/release-artifact-check.test.js +69 -2
- package/tests/release-smoke-check.test.js +25 -0
- package/tests/vent-store.test.js +43 -0
package/README.md
CHANGED
|
@@ -45,11 +45,12 @@ Then in Pi:
|
|
|
45
45
|
|
|
46
46
|
## Tool behavior
|
|
47
47
|
|
|
48
|
-
`agent_vent` supports
|
|
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.
|
|
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,
|
|
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,69 @@
|
|
|
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
|
+
- `self.diagnostic_candidate.v1` exposes separate `agentVentSuggestionAllowed` and `agentVentRecordAllowed` permissions. Plain `no agent_vent` / `no-agent_vent` constraints suppress activation, preview, and record guidance. Record-only `no agent_vent record` / `no-agent_vent-record` constraints preserve non-mutating preview guidance while marking durable recording forbidden.
|
|
52
|
+
- ASC category `context_alignment` is accepted by `agent_vent` as a compatibility alias and normalized to canonical category `other`; the alias does not add a new canonical category.
|
|
53
|
+
- The toolbox bundle currently exposes only its `default` diagnostic profile. Keep a call read-only by choosing `agent_vent` actions such as `preview`, `review`, or `stats`; do not invent `profile=read`.
|
|
54
|
+
- Generic low-signal summaries such as `done` are rejected for `record`; use `preview` to inspect issues and warnings before writing.
|
|
55
|
+
- Human/operator judgment still decides whether any recurrence should become an AK task, GitHub issue, incident review, evidence record, publication, or owner-surface handoff.
|
|
56
|
+
|
|
57
|
+
## Copy wording for boundaries
|
|
58
|
+
|
|
59
|
+
Recommended short wording:
|
|
60
|
+
|
|
61
|
+
> 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.
|
|
62
|
+
|
|
63
|
+
Use stronger wording when a durable local write happened:
|
|
64
|
+
|
|
65
|
+
> 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.
|
|
66
|
+
|
|
67
|
+
## Review and escalation posture
|
|
68
|
+
|
|
69
|
+
`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.
|
|
@@ -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.
|
package/docs/project/vision.md
CHANGED
|
@@ -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;
|
package/extensions/agent-vent.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
// ---
|
|
2
|
+
// summary: registers the agent_vent tool and command for local diagnostic review workflows
|
|
3
|
+
// read_when:
|
|
4
|
+
// - changing agent vent actions, command parsing, tool schemas, or authority boundaries
|
|
5
|
+
// ---
|
|
6
|
+
|
|
1
7
|
import path from "node:path";
|
|
2
|
-
import type { ExtensionAPI } from "@
|
|
8
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
9
|
import { Type } from "typebox";
|
|
4
10
|
import {
|
|
5
11
|
appendCurationEvent,
|
|
@@ -7,6 +13,7 @@ import {
|
|
|
7
13
|
appendVentRecord,
|
|
8
14
|
archiveRecurrenceGroup,
|
|
9
15
|
assertCanCurateRecurrence,
|
|
16
|
+
assessVentRecordQuality,
|
|
10
17
|
buildEscalationDraft,
|
|
11
18
|
buildFacetSummary,
|
|
12
19
|
buildLifecycleSnapshot,
|
|
@@ -49,6 +56,7 @@ import {
|
|
|
49
56
|
normalizeReviewState,
|
|
50
57
|
RETENTION_ACTIONS,
|
|
51
58
|
readRetentionEvents,
|
|
59
|
+
resolveCategoryFilter,
|
|
52
60
|
resolveRecurrenceGroup,
|
|
53
61
|
restoreRetentionBackup,
|
|
54
62
|
SEVERITIES,
|
|
@@ -59,6 +67,7 @@ import {
|
|
|
59
67
|
|
|
60
68
|
const ACTIONS = [
|
|
61
69
|
"record",
|
|
70
|
+
"preview",
|
|
62
71
|
"summary",
|
|
63
72
|
"list",
|
|
64
73
|
"path",
|
|
@@ -79,6 +88,20 @@ const REVIEW_STATES = Array.isArray(STORE_REVIEW_STATES)
|
|
|
79
88
|
? STORE_REVIEW_STATES
|
|
80
89
|
: FALLBACK_REVIEW_STATES;
|
|
81
90
|
const RETENTION_CANDIDATE_STATES = ["reviewed", "all", ...REVIEW_STATES] as const;
|
|
91
|
+
const CATEGORY_ALIAS_INPUTS = [
|
|
92
|
+
"workflow_friction",
|
|
93
|
+
"operator_friction",
|
|
94
|
+
"process_friction",
|
|
95
|
+
"missing_affordance",
|
|
96
|
+
"missing_feature",
|
|
97
|
+
"documentation_gap",
|
|
98
|
+
"docs_gap",
|
|
99
|
+
"context_window",
|
|
100
|
+
"context_friction",
|
|
101
|
+
"context_alignment",
|
|
102
|
+
"tooling_friction",
|
|
103
|
+
] as const;
|
|
104
|
+
const CATEGORY_INPUTS = [...CATEGORIES, ...CATEGORY_ALIAS_INPUTS] as const;
|
|
82
105
|
|
|
83
106
|
const AgentVentParams = Type.Object({
|
|
84
107
|
action: Type.Optional(
|
|
@@ -92,9 +115,10 @@ const AgentVentParams = Type.Object({
|
|
|
92
115
|
),
|
|
93
116
|
category: Type.Optional(
|
|
94
117
|
Type.Union(
|
|
95
|
-
|
|
118
|
+
CATEGORY_INPUTS.map((category) => Type.Literal(category)),
|
|
96
119
|
{
|
|
97
|
-
description:
|
|
120
|
+
description:
|
|
121
|
+
"Local category for the frustration pattern. Common aliases are accepted and normalized to canonical categories.",
|
|
98
122
|
},
|
|
99
123
|
),
|
|
100
124
|
),
|
|
@@ -235,11 +259,12 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
235
259
|
name: "agent_vent",
|
|
236
260
|
label: "Agent Vent",
|
|
237
261
|
description:
|
|
238
|
-
"Record, review, and inspect local agent frustration events so recurring bugs, workflow friction, and missing affordances become visible.",
|
|
262
|
+
"Record, preview, review, and inspect local agent frustration events so recurring bugs, workflow friction, and missing affordances become visible.",
|
|
239
263
|
promptSnippet:
|
|
240
|
-
"
|
|
264
|
+
"Preview or record minimized local frustration events and review recurring patterns without creating incidents, tasks, issues, evidence records, or telemetry.",
|
|
241
265
|
promptGuidelines: [
|
|
242
266
|
"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.",
|
|
267
|
+
"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.",
|
|
243
268
|
"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.",
|
|
244
269
|
"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.",
|
|
245
270
|
"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.",
|
|
@@ -253,7 +278,8 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
253
278
|
"When calling agent_vent, summarize minimally and never include secrets, credentials, private user payloads, or long raw logs.",
|
|
254
279
|
],
|
|
255
280
|
parameters: AgentVentParams,
|
|
256
|
-
async execute(_toolCallId, params,
|
|
281
|
+
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
282
|
+
throwIfCancelled(signal);
|
|
257
283
|
const storePath = defaultStorePath();
|
|
258
284
|
const reviewPath = defaultReviewPath();
|
|
259
285
|
const curationPath = defaultCurationPath();
|
|
@@ -275,13 +301,29 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
275
301
|
);
|
|
276
302
|
}
|
|
277
303
|
|
|
278
|
-
if (action === "record") {
|
|
304
|
+
if (action === "preview" || action === "record") {
|
|
279
305
|
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
280
306
|
const record = createVentRecord(params, {
|
|
281
307
|
cwd: ctx.cwd,
|
|
282
308
|
sessionFile: sessionFile ? path.basename(sessionFile) : undefined,
|
|
283
|
-
source: "agent_vent_tool",
|
|
309
|
+
source: action === "preview" ? "agent_vent_preview" : "agent_vent_tool",
|
|
284
310
|
});
|
|
311
|
+
const quality = assessVentRecordQuality(params, record);
|
|
312
|
+
if (action === "preview") {
|
|
313
|
+
return textResult(formatRecordPreview(record, quality), {
|
|
314
|
+
action,
|
|
315
|
+
storePath,
|
|
316
|
+
recordPreview: record,
|
|
317
|
+
quality,
|
|
318
|
+
wouldRecord: quality.recordable,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
if (!quality.recordable) {
|
|
322
|
+
throw new Error(
|
|
323
|
+
`agent_vent record rejected by anti-junk quality check: ${quality.issues.join("; ")}`,
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
throwIfCancelled(signal);
|
|
285
327
|
appendVentRecord(storePath, record);
|
|
286
328
|
const state = loadDiagnosticState({
|
|
287
329
|
storePath,
|
|
@@ -331,6 +373,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
331
373
|
});
|
|
332
374
|
}
|
|
333
375
|
|
|
376
|
+
throwIfCancelled(signal);
|
|
334
377
|
const state = loadDiagnosticState({
|
|
335
378
|
storePath,
|
|
336
379
|
reviewPath,
|
|
@@ -367,6 +410,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
367
410
|
};
|
|
368
411
|
assertCanCurateRecurrence(records, curationEvents, input);
|
|
369
412
|
const event = createCurationEvent(input, { source: "agent_vent_tool" });
|
|
413
|
+
throwIfCancelled(signal);
|
|
370
414
|
appendCurationEvent(curationPath, event);
|
|
371
415
|
const targetText = event.targetRecurrenceKey ? ` -> ${event.targetRecurrenceKey}` : "";
|
|
372
416
|
const text = [
|
|
@@ -400,6 +444,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
400
444
|
},
|
|
401
445
|
{ source: "agent_vent_tool" },
|
|
402
446
|
);
|
|
447
|
+
throwIfCancelled(signal);
|
|
403
448
|
appendReviewEvent(reviewPath, event);
|
|
404
449
|
const text = [
|
|
405
450
|
`Set local review state for ${event.recurrenceKey} to ${event.state}.`,
|
|
@@ -610,6 +655,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
610
655
|
});
|
|
611
656
|
}
|
|
612
657
|
if (retentionAction === "archive") {
|
|
658
|
+
throwIfCancelled(signal);
|
|
613
659
|
const result = archiveRecurrenceGroup({
|
|
614
660
|
storePath,
|
|
615
661
|
reviewPath,
|
|
@@ -632,6 +678,7 @@ export default function agentVentExtension(pi: ExtensionAPI) {
|
|
|
632
678
|
retention: result,
|
|
633
679
|
});
|
|
634
680
|
}
|
|
681
|
+
throwIfCancelled(signal);
|
|
635
682
|
const result = restoreRetentionBackup({
|
|
636
683
|
storePath,
|
|
637
684
|
retentionPath,
|
|
@@ -737,15 +784,31 @@ function registerAgentVentCommand(pi: ExtensionAPI, name: string, description: s
|
|
|
737
784
|
description,
|
|
738
785
|
handler: async (args, ctx) => {
|
|
739
786
|
const output = handleCommand(args);
|
|
740
|
-
if (ctx.hasUI) {
|
|
741
|
-
ctx.ui.notify(output, "info");
|
|
742
|
-
} else {
|
|
787
|
+
if (!ctx.hasUI) {
|
|
743
788
|
console.log(output);
|
|
789
|
+
} else if (isLongCommandOutput(output)) {
|
|
790
|
+
pi.sendMessage({
|
|
791
|
+
customType: "agent-vent-command",
|
|
792
|
+
content: output,
|
|
793
|
+
display: true,
|
|
794
|
+
details: { command: name },
|
|
795
|
+
});
|
|
796
|
+
ctx.ui.notify("agent_vent output added to the session transcript", "info");
|
|
797
|
+
} else {
|
|
798
|
+
ctx.ui.notify(output, "info");
|
|
744
799
|
}
|
|
745
800
|
},
|
|
746
801
|
});
|
|
747
802
|
}
|
|
748
803
|
|
|
804
|
+
function isLongCommandOutput(output: string): boolean {
|
|
805
|
+
return output.length > 500 || output.split("\n").length > 8;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function throwIfCancelled(signal: AbortSignal | undefined): void {
|
|
809
|
+
if (signal?.aborted) throw new Error("agent_vent cancelled");
|
|
810
|
+
}
|
|
811
|
+
|
|
749
812
|
function handleCommand(args: string) {
|
|
750
813
|
const tokens = splitCommandArgs(args);
|
|
751
814
|
const action = tokens[0] || "summary";
|
|
@@ -759,6 +822,7 @@ function handleCommand(args: string) {
|
|
|
759
822
|
return [
|
|
760
823
|
"agent_vent commands:",
|
|
761
824
|
" /agent_vent summary Show recurrence groups and candidate incidents.",
|
|
825
|
+
" LLM tool action=preview Preview a local diagnostic record and anti-junk quality check without writing the store.",
|
|
762
826
|
" /agent_vent list [limit] Show recent local vent records.",
|
|
763
827
|
" /agent_vent facets [limit] Show read-only local category/tag/tool/package facets.",
|
|
764
828
|
" /agent_vent review [state|all] [limit] [category=bug] [tag=reload] [tool=pi-reload] [package=tryinget-pi-agent-vent]",
|
|
@@ -1084,8 +1148,8 @@ function parseReviewListTokens(tokens: string[], options: { allowReviewedState?:
|
|
|
1084
1148
|
invalidFilters.push("category=");
|
|
1085
1149
|
continue;
|
|
1086
1150
|
}
|
|
1087
|
-
const
|
|
1088
|
-
if (
|
|
1151
|
+
const category = resolveCategoryFilter(value);
|
|
1152
|
+
if (category) filters.category = category;
|
|
1089
1153
|
else invalidFilters.push(`category=${value}`);
|
|
1090
1154
|
} else if (key === "tool") {
|
|
1091
1155
|
if (!value) {
|
|
@@ -1374,6 +1438,24 @@ function formatDiagnosticWarnings(state: Record<string, unknown>) {
|
|
|
1374
1438
|
: "";
|
|
1375
1439
|
}
|
|
1376
1440
|
|
|
1441
|
+
function formatRecordPreview(
|
|
1442
|
+
record: Record<string, unknown>,
|
|
1443
|
+
quality: { recordable?: boolean; issues?: string[]; warnings?: string[]; boundary?: string },
|
|
1444
|
+
) {
|
|
1445
|
+
const issues = quality.issues || [];
|
|
1446
|
+
const warnings = quality.warnings || [];
|
|
1447
|
+
return [
|
|
1448
|
+
`Agent vent preview: ${quality.recordable ? "recordable" : "not recordable"} (${record.severity || "medium"}/${record.category || "other"}) under ${record.recurrenceKey || "unknown"}.`,
|
|
1449
|
+
`Summary: ${record.summary || "(no summary)"}`,
|
|
1450
|
+
issues.length ? `Issues: ${issues.join("; ")}` : "Issues: none",
|
|
1451
|
+
warnings.length ? `Warnings: ${warnings.join("; ")}` : "Warnings: none",
|
|
1452
|
+
"No local diagnostic record was written. Use action=record only if this is a recurring or review-worthy diagnostic, not an ordinary progress update.",
|
|
1453
|
+
`Boundary: ${quality.boundary || "local diagnostic preview only"}`,
|
|
1454
|
+
].join("\n");
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
export const _test = { isLongCommandOutput, throwIfCancelled };
|
|
1458
|
+
|
|
1377
1459
|
function textResult(text: string, details: Record<string, unknown>) {
|
|
1378
1460
|
return {
|
|
1379
1461
|
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
|
|
3
|
+
"version": "0.2.1",
|
|
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.83.0",
|
|
91
|
+
"@earendil-works/pi-coding-agent": "0.83.0"
|
|
83
92
|
},
|
|
84
93
|
"overrides": {
|
|
85
94
|
"fast-xml-parser": "5.3.6"
|
|
86
95
|
},
|
|
87
96
|
"peerDependencies": {
|
|
88
|
-
"@
|
|
89
|
-
"@
|
|
97
|
+
"@earendil-works/pi-ai": "*",
|
|
98
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
90
99
|
"typebox": "*"
|
|
91
100
|
},
|
|
92
101
|
"dependencies": {
|
|
93
|
-
"typebox": "
|
|
102
|
+
"typebox": "1.3.7"
|
|
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: "
|
|
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
|
|
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: "
|
|
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
|
package/scripts/docs-list.sh
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# ---
|
|
3
|
+
# summary: locates and invokes documentation listing support for pi-agent-vent
|
|
4
|
+
# read_when:
|
|
5
|
+
# - enumerating package docs or overriding the docs-list implementation
|
|
6
|
+
# ---
|
|
2
7
|
set -euo pipefail
|
|
3
8
|
|
|
4
9
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
package/scripts/quality-gate.sh
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# ---
|
|
3
|
+
# summary: runs pi-agent-vent quality stages through the root gate or package fallback
|
|
4
|
+
# read_when:
|
|
5
|
+
# - checking lint, types, tests, or scaffold structure in varied checkout layouts
|
|
6
|
+
# ---
|
|
2
7
|
set -euo pipefail
|
|
3
8
|
|
|
4
9
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|