pi-crew 0.5.19 → 0.5.20

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,38 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.20] — Verification Sweep: 7 Fixes (2026-06-03)
4
+
5
+ ### Highlights
6
+ - **Correctness bug fixed**: `enforceLabelCap` could silently evict actively-used metric entries
7
+ - `Date` removed from forbidden globals (was blocking legitimate workflow scripts)
8
+ - `scheduledJobs` properly typed in `CrewSettings` interface
9
+ - 3 new tests for metric MRU eviction behavior
10
+
11
+ ### Fixes
12
+
13
+ #### Correctness
14
+ - `Counter.inc()` and `Gauge.set()` now delete-then-set to move keys to MRU position
15
+ - Previously, `enforceLabelCap` could evict an entry that was just updated
16
+
17
+ #### Consistency
18
+ - Removed `Date` from `FORBIDDEN_GLOBALS` in `DynamicScriptRunner`
19
+ - `Date` is not dangerous — was causing false positives for `myDate`, `updateDate`, etc.
20
+ - `DynamicScriptRunner` and `WorkflowSandbox` now consistent
21
+
22
+ #### Type Safety
23
+ - Added `scheduledJobs?: unknown[]` to `CrewSettings` interface
24
+ - Removed `as any` cast in `register.ts` (now uses `as ScheduledJob`)
25
+
26
+ #### Code Quality
27
+ - Removed dead `reason` variable in `settings-store.ts`
28
+ - Added trailing newline to `event-bus.ts` (POSIX compliance)
29
+ - Added 3 tests for Counter/Gauge MRU eviction behavior
30
+
31
+ ### Stats
32
+ - Test suite: 2658+ pass + 1 skip, 0 fail
33
+ - TypeScript: 0 errors
34
+ - Security: All 7 SEC-* issues confirmed still fixed
35
+
3
36
  ## [0.5.19] — Final Sweep: 8 MEDIUM/LOW Fixes + 2 Test Fixes (2026-06-03)
4
37
 
5
38
  ### Highlights
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-crew",
3
- "version": "0.5.19",
3
+ "version": "0.5.20",
4
4
  "description": "Pi extension for coordinated AI teams, workflows, worktrees, and async task orchestration",
5
5
  "author": "baphuongna",
6
6
  "license": "MIT",
@@ -18,6 +18,7 @@ import {
18
18
  } from "./async-notifier.ts";
19
19
  import { registerAutonomousPolicy } from "./autonomous-policy.ts";
20
20
  import { registerCleanupHandler } from "./crew-cleanup.ts";
21
+ import type { ScheduledJob } from "../runtime/scheduler.ts";
21
22
  import { clearHooks } from "../hooks/registry.ts";
22
23
  import { notifyActiveRuns } from "./session-summary.ts";
23
24
 
@@ -1339,10 +1340,10 @@ export function registerPiTeams(pi: ExtensionAPI): void {
1339
1340
  // Uses a global symbol so the module doesn't need a direct circular import.
1340
1341
  (globalThis as Record<symbol | string, unknown>)[Symbol.for("pi-crew:scheduler")] = crewScheduler;
1341
1342
  // Load scheduled jobs from settings if present
1342
- if (Array.isArray((crewSettings as any).scheduledJobs)) {
1343
- for (const job of (crewSettings as any).scheduledJobs) {
1343
+ if (Array.isArray(crewSettings.scheduledJobs)) {
1344
+ for (const job of crewSettings.scheduledJobs) {
1344
1345
  try {
1345
- crewScheduler.add(job);
1346
+ crewScheduler.add(job as ScheduledJob);
1346
1347
  } catch {
1347
1348
  /* skip invalid */
1348
1349
  }
@@ -79,4 +79,4 @@ class EventBus {
79
79
  * This bus is retained for future observability/SIEM integration.
80
80
  * See also: progress-tracker.ts which emits agent:progress events.
81
81
  */
82
- export const crewEventBus = EventBus.getInstance();
82
+ export const crewEventBus = EventBus.getInstance();
@@ -79,6 +79,9 @@ export class Counter extends Metric {
79
79
  if (!Number.isFinite(delta) || delta < 0) return;
80
80
  const key = labelKey(labels);
81
81
  const current = this.values.get(key) ?? { labels: normalizeLabels(labels), value: 0 };
82
+ // Delete before set to move key to end of insertion order (MRU).
83
+ // Without this, enforceLabelCap could evict an actively-used entry.
84
+ this.values.delete(key);
82
85
  this.values.set(key, { labels: current.labels, value: current.value + delta });
83
86
  enforceLabelCap(this.values, this.name);
84
87
  }
@@ -97,7 +100,10 @@ export class Gauge extends Metric {
97
100
 
98
101
  set(labels: MetricLabels = {}, value: number): void {
99
102
  if (!Number.isFinite(value)) return;
100
- this.values.set(labelKey(labels), { labels: normalizeLabels(labels), value });
103
+ const key = labelKey(labels);
104
+ // Delete before set to move key to end of insertion order (MRU).
105
+ this.values.delete(key);
106
+ this.values.set(key, { labels: normalizeLabels(labels), value });
101
107
  enforceLabelCap(this.values, this.name);
102
108
  }
103
109
 
@@ -7,7 +7,6 @@ import { WorkflowSandbox, type SandboxOptions } from "./sandbox.ts";
7
7
  * These are checked during AST validation before execution.
8
8
  */
9
9
  export const FORBIDDEN_GLOBALS = [
10
- "Date",
11
10
  "Math.random",
12
11
  "require",
13
12
  "import",
@@ -11,6 +11,8 @@ export interface CrewSettings {
11
11
  defaultJoinMode?: JoinMode;
12
12
  schedulingEnabled?: boolean;
13
13
  notifierIntervalMs?: number;
14
+ /** Scheduled jobs loaded from settings — opaque, passed to crewScheduler */
15
+ scheduledJobs?: unknown[];
14
16
  }
15
17
 
16
18
  const MAX_CONCURRENT_CEILING = 1024;
@@ -71,7 +73,6 @@ function readSettingsFile(filePath: string): CrewSettings {
71
73
  try {
72
74
  return sanitizeSettings(JSON.parse(fs.readFileSync(filePath, "utf-8")));
73
75
  } catch (err) {
74
- const reason = err instanceof Error ? err.message : String(err);
75
76
  logInternalError("settings-store.read", err, `Ignoring malformed settings at ${filePath}`);
76
77
  return {};
77
78
  }