pi-crew 0.7.1 → 0.7.2

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.2] — Fix: Knowledge Injection into Workers + HITL for All Workflows (2026-06-15)
4
+
5
+ ### Bug Fixes
6
+
7
+ - **Knowledge injection into crew workers (O4)** — crew workers are spawned with `--no-extensions` and only load `prompt-runtime.ts`; they do **not** load the pi-crew extension. So the `before_agent_start` hook in `knowledge-injection.ts` never fired for workers — `.crew/knowledge.md` was invisible to every crew worker. **Fix**: inject `buildKnowledgeFragment(task.cwd)` directly into `renderTaskPrompt()` in `prompt-builder.ts` (where all worker context is assembled). The main session still gets knowledge via the hook; workers now get it via the prompt path.
8
+
9
+ **Live-verified**: all 3 workers (explorer, executor, verifier) in a fast-fix run confirmed seeing the knowledge section verbatim (`"Use TABS for indentation"`, `"Tests run via npm test"`).
10
+
11
+ - **Plan-level HITL for all workflows (T1.2)** — the post-batch approval re-check in the team-runner main loop only checked `hasPendingMutatingAdaptiveTask(tasks)` (adaptive/implementation workflows only). The boundary detector `hasPendingMutatingTaskAtBoundary(tasks)` was added to the initial build but **not** to the loop's re-check. So for non-adaptive workflows (`default`, `fast-fix`), the approval gate never fired after read-only tasks completed. **Fix**: add `hasPendingMutatingTaskAtBoundary(tasks)` to the loop's post-batch re-check (line 835), matching the initial-build logic.
12
+
13
+ **Verified** via 6 new unit tests + full flow trace. When `runtime.requirePlanApproval: true`, the run now blocks at the plan→execute boundary (`status: blocked`, "Plan approval required") until approved via `team api op=approve-plan`.
14
+
3
15
  ## [0.7.1] — Fix: Auto-Continue After Compaction (2026-06-15)
4
16
 
5
17
  ### Bug Fix
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-crew",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Pi extension for coordinated AI teams, workflows, worktrees, and async task orchestration",
5
5
  "author": "baphuongna",
6
6
  "license": "MIT",
package/src/errors.ts CHANGED
@@ -1,6 +1,24 @@
1
+ // pi-crew structured error module — taxonomy mapping E001–E006.
1
2
  /**
2
- * Error code taxonomy for pi-crew.
3
- * Maps to semantic categories matching fallow's E001-E004 pattern.
3
+ * @fileoverview Error types and structured error handling for pi-crew.
4
+ *
5
+ * This module defines pi-crew's error taxonomy, mapping to semantic categories
6
+ * matching fallow's E001-E004 pattern. It exports three main constructs:
7
+ *
8
+ * - {@link ErrorCode} — a `const` object and string-literal union type alias
9
+ * enumerating machine-readable error codes (E001–E006). Implemented as a
10
+ * `const` object rather than a TypeScript `enum` so that Node's
11
+ * `--experimental-strip-types` can load this module (enum syntax is not
12
+ * supported in strip-only mode).
13
+ *
14
+ * - {@link CrewError} — a structured `Error` subclass that carries an
15
+ * {@link ErrorCode}, an optional human-readable `help` hint, and an optional
16
+ * `context` string. Its `toString()` renders the display format:
17
+ * `error[E001]: Failed to read manifest.json: not found`.
18
+ *
19
+ * - {@link errors} — a factory object exposing convenience constructors
20
+ * (e.g. `errors.fileRead`, `errors.taskNotFound`) that build `CrewError`
21
+ * instances with sensible defaults and pre-attached context.
4
22
  */
5
23
  // Implemented as const object + type alias (not `enum`) so that Node's
6
24
  // `--experimental-strip-types` can load this module. TypeScript `enum`
@@ -5,6 +5,7 @@ import { buildMemoryBlock } from "../agent-memory.ts";
5
5
  import { permissionForRole } from "../role-permission.ts";
6
6
  import { renderTaskPacket, HANDOFF_TEMPLATE } from "../task-packet.ts";
7
7
  import { buildWorkspaceTree } from "../workspace-tree.ts";
8
+ import { buildKnowledgeFragment } from "../../extension/knowledge-injection.ts";
8
9
 
9
10
  /**
10
11
  * When loadMode is "lean", emit a tool guidance block that tells the worker
@@ -114,6 +115,11 @@ export async function renderTaskPrompt(manifest: TeamRunManifest, step: Workflow
114
115
  treeBlock,
115
116
  "",
116
117
  toolGuidanceBlock(agent),
118
+ "",
119
+ // O4: project knowledge (.crew/knowledge.md) — workers don't load the
120
+ // pi-crew extension (spawned with --no-extensions), so before_agent_start
121
+ // never fires for them. Inject here so every worker sees project knowledge.
122
+ buildKnowledgeFragment(task.cwd),
117
123
  ].filter(Boolean).join("\n");
118
124
 
119
125
  // Dynamic suffix: goal, step, skills, task packet, dependency context, memory — changes per task
@@ -394,7 +394,7 @@ function hasPendingMutatingAdaptiveTask(tasks: TeamTaskState[]): boolean {
394
394
  * Fires when there are pending mutating tasks whose prerequisites (read-only
395
395
  * tasks) have completed — i.e. the plan→execute boundary.
396
396
  */
397
- function hasPendingMutatingTaskAtBoundary(tasks: TeamTaskState[]): boolean {
397
+ export function hasPendingMutatingTaskAtBoundary(tasks: TeamTaskState[]): boolean {
398
398
  const hasCompletedReadOnly = tasks.some((t) => t.status === "completed" && !isMutatingTask(t));
399
399
  const hasPendingMutating = tasks.some((t) => t.status === "queued" && isMutatingTask(t));
400
400
  return hasCompletedReadOnly && hasPendingMutating;
@@ -832,7 +832,7 @@ tasks = mergeResult.resultTasks;
832
832
  if (injectedAfterBatch.injected) {
833
833
  manifest = requiresPlanApproval(workflow, input.runtimeConfig) ? ensurePlanApprovalRequested(manifest, tasks) : manifest;
834
834
  queueIndex = buildTaskGraphIndex(tasks);
835
- } else if (requiresPlanApproval(workflow, input.runtimeConfig) && hasPendingMutatingAdaptiveTask(tasks)) {
835
+ } else if (requiresPlanApproval(workflow, input.runtimeConfig) && (hasPendingMutatingAdaptiveTask(tasks) || hasPendingMutatingTaskAtBoundary(tasks))) {
836
836
  manifest = ensurePlanApprovalRequested(manifest, tasks);
837
837
  }
838
838
  if (manifest.planApproval?.status === "cancelled") {