@xzzpig/pi-openspec-x 0.2.0 → 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/CHANGELOG.md +7 -0
- package/dist/public.d.ts +48 -0
- package/package.json +7 -3
- package/src/child-report-reader.ts +16 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
- Support Pi 1.2+ custom-message wakeups in child report handlers. A wakeup
|
|
6
|
+
retains the current user-dispatch attempt without allowing an unverified
|
|
7
|
+
message to authorize a report; a new user dispatch creates a fresh attempt.
|
|
8
|
+
- Include the extension's generated public type declaration in the package.
|
|
9
|
+
|
|
3
10
|
## 0.2.0
|
|
4
11
|
|
|
5
12
|
Child report tools are now scoped to the subagents that own them, and the
|
package/dist/public.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* pi-openspec-x extension entry point.
|
|
5
|
+
*
|
|
6
|
+
* pi-sandbox is probed lazily through a dynamic import (dependencies.ts): on
|
|
7
|
+
* success the three opsx sandbox profiles (D4: opsx-planner / opsx-agent /
|
|
8
|
+
* opsx-reviewer) are registered into pi-sandbox's runtime registry — in-memory
|
|
9
|
+
* for the session lifetime, never written to a user's sandbox.json, a
|
|
10
|
+
* user-defined same-name profile always keeping priority. On failure the
|
|
11
|
+
* reason is recorded as dependency state and the extension continues: the
|
|
12
|
+
* official-track skills and every other capability keep working, and a later
|
|
13
|
+
* request for a restricted mode is refused with a typed
|
|
14
|
+
* OpsxDependencyMissingError (fail-closed) instead of the extension (or the
|
|
15
|
+
* official track) dying at load time.
|
|
16
|
+
*
|
|
17
|
+
* Registers the resources_discover handler, which:
|
|
18
|
+
* - generates (and caches, keyed by CLI version) the official-track
|
|
19
|
+
* openspec-* skills under `<agentDir>/cache/pi-openspec-x/skills/` and
|
|
20
|
+
* exposes the directory to pi via `skillPaths`;
|
|
21
|
+
* - warns once per project when static `<cwd>/.pi/skills/openspec-*`
|
|
22
|
+
* directories collide with the generated skills.
|
|
23
|
+
*
|
|
24
|
+
* Registers the session_start handler that clears a stale `active_agent`
|
|
25
|
+
* identity left in the session file by an earlier session (pi-agent-role's
|
|
26
|
+
* semantics; see mode.ts).
|
|
27
|
+
*
|
|
28
|
+
* Registers the three child reporting tools (report_gap_analysis,
|
|
29
|
+
* report_plan_review, report_work) through the role-specific child-only
|
|
30
|
+
* extensions declared in agents.ts (design D1): each tool is registered into
|
|
31
|
+
* its own subagent's process and never into the main session, so the parent's
|
|
32
|
+
* tool declaration and prompt rules stay free of them.
|
|
33
|
+
*
|
|
34
|
+
* pi-subagents is probed the same lazy way: on success the four opsx
|
|
35
|
+
* subagents (opsx-gap-analysis / opsx-plan-review / opsx-worker / opsx-reviewer) are
|
|
36
|
+
* registered into pi-subagents' runtime registry via the owner's event bus
|
|
37
|
+
* (D3). A missing pi-subagents costs only the enhanced flow's subagents —
|
|
38
|
+
* the official track and direct main-session implementation are unaffected.
|
|
39
|
+
* Because the owner listener only exists once pi-subagents has loaded (load
|
|
40
|
+
* order between extensions is not guaranteed), a failed init-time attempt is
|
|
41
|
+
* retried on session_start.
|
|
42
|
+
*
|
|
43
|
+
* Missing openspec CLI: no skills are registered and no error escapes — a
|
|
44
|
+
* one-time notice is sent instead.
|
|
45
|
+
*/
|
|
46
|
+
declare function piOpenspecX(pi: ExtensionAPI): Promise<void>;
|
|
47
|
+
|
|
48
|
+
export { piOpenspecX as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xzzpig/pi-openspec-x",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "OpenSpec workflow for the pi coding agent: spec-driven planning and implementation via dedicated subagents, sandboxed /opsx:plan and /opsx:implement commands.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"index.ts",
|
|
27
27
|
"src",
|
|
28
|
+
"dist",
|
|
28
29
|
"README.md",
|
|
29
30
|
"CHANGELOG.md",
|
|
30
31
|
"LICENSE",
|
|
@@ -43,13 +44,16 @@
|
|
|
43
44
|
"@xzzpig/pi-subagents": "*"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
|
-
"@earendil-works/pi-coding-agent": "1.
|
|
47
|
+
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
47
48
|
"@types/node": "24.12.4",
|
|
49
|
+
"rollup": "^4.62.2",
|
|
50
|
+
"rollup-plugin-dts": "^6.4.1",
|
|
48
51
|
"typescript": "5.9.3",
|
|
49
52
|
"vitest": "4.1.8"
|
|
50
53
|
},
|
|
51
54
|
"scripts": {
|
|
52
55
|
"test": "vitest run",
|
|
53
|
-
"typecheck": "tsc --noEmit"
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"build:types": "rollup -c rollup.dts.config.mjs"
|
|
54
58
|
}
|
|
55
59
|
}
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
* ingestion; it never adds a model-fillable parameter, and the parent
|
|
13
13
|
* re-validates `report` against the original tool schema.
|
|
14
14
|
*
|
|
15
|
-
* The attempt is the anti-forgery anchor:
|
|
16
|
-
* random `attemptId` plus the SHA-256 of
|
|
17
|
-
* `pi-openspec-x/child-report-attempt:v1` session entry.
|
|
18
|
-
* attributable to the
|
|
19
|
-
* reuses the same session file cannot smuggle an earlier
|
|
20
|
-
* current dispatch.
|
|
15
|
+
* The attempt is the anti-forgery anchor: for each user dispatch,
|
|
16
|
+
* `before_agent_start` records a fresh random `attemptId` plus the SHA-256 of
|
|
17
|
+
* the actual prompt in a `pi-openspec-x/child-report-attempt:v1` session entry.
|
|
18
|
+
* A report is attributable only to the dispatch whose attempt it names, so a
|
|
19
|
+
* resumed child that reuses the same session file cannot smuggle an earlier
|
|
20
|
+
* run's report into the current dispatch.
|
|
21
21
|
*
|
|
22
22
|
* Deliberately NOT here: any reading of pi-subagents' private `AsyncStatus`
|
|
23
23
|
* or lifecycle constants (design D3). This module declares the minimal v3
|
|
@@ -164,9 +164,9 @@ export function beginChildReportAttempt(
|
|
|
164
164
|
/** Human-readable refusal text for a report that cannot be attributed. */
|
|
165
165
|
export function attemptUnavailableMessage(agent: string): string {
|
|
166
166
|
return (
|
|
167
|
-
`Report rejected: no child report attempt is recorded for ${agent} in this
|
|
167
|
+
`Report rejected: no child report attempt is recorded for ${agent} in this dispatch. ` +
|
|
168
168
|
`The parent cannot attribute this report to a verified run, so it would be ignored; ` +
|
|
169
|
-
`the attempt entry is written by this extension at the start of
|
|
169
|
+
`the attempt entry is written by this extension at the start of each user dispatch.`
|
|
170
170
|
);
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -175,7 +175,7 @@ export function attemptUnavailableMessage(agent: string): string {
|
|
|
175
175
|
*
|
|
176
176
|
* The wrapped tool keeps the original name, schema, confirmation text and
|
|
177
177
|
* `sequential` execution mode; only `details` changes into the envelope. When
|
|
178
|
-
* the current
|
|
178
|
+
* the current dispatch has no persisted attempt, the call fails explicitly instead
|
|
179
179
|
* of returning a report the parent would have to discard.
|
|
180
180
|
*/
|
|
181
181
|
export function registerChildReportTool(
|
|
@@ -185,6 +185,13 @@ export function registerChildReportTool(
|
|
|
185
185
|
let current: ChildReportAttemptOutcome | undefined;
|
|
186
186
|
|
|
187
187
|
pi.on("before_agent_start", (event: BeforeAgentStartEvent, ctx) => {
|
|
188
|
+
// Pi 1.2+ also fires this hook when a custom message wakes the same child.
|
|
189
|
+
// It is not a new user dispatch: keep its existing attempt, or continue to
|
|
190
|
+
// reject reports if no dispatch has been recorded. Pi 1.1 never fired this
|
|
191
|
+
// hook for such a wake and has no messageType field.
|
|
192
|
+
if ("messageType" in event && event.messageType === "custom") return;
|
|
193
|
+
current = undefined;
|
|
194
|
+
if (!("prompt" in event) || typeof event.prompt !== "string") return;
|
|
188
195
|
current = beginChildReportAttempt(pi, ctx, {
|
|
189
196
|
agent: options.agent,
|
|
190
197
|
prompt: event.prompt,
|