pi-crew 0.9.56 → 0.9.57
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/AGENTS.md +1 -1
- package/CHANGELOG.md +29 -0
- package/README.md +53 -5
- package/dist/index.mjs +5350 -4350
- package/docs/README.md +54 -0
- package/package.json +12 -12
- package/skills/real-test-pi-crew/SKILL.md +93 -3
- package/src/agents/discover-agents.ts +68 -10
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +2 -1
- package/src/config/types.ts +12 -0
- package/src/extension/action-suggestions.ts +16 -63
- package/src/extension/async-notifier.ts +3 -3
- package/src/extension/command-completions.ts +2 -2
- package/src/extension/crew-cleanup.ts +3 -3
- package/src/extension/crew-vibes/footer.ts +4 -2
- package/src/extension/cross-extension-rpc.ts +10 -5
- package/src/extension/knowledge-injection.ts +57 -10
- package/src/extension/register.ts +2 -2
- package/src/extension/registration/artifact-cleanup.ts +41 -3
- package/src/extension/registration/commands.ts +4 -4
- package/src/extension/registration/context-builder.ts +10 -10
- package/src/extension/registration/crash-recovery-cache.ts +3 -3
- package/src/extension/registration/foreground-run-controller.ts +1 -1
- package/src/extension/registration/lazy-configurers.ts +2 -2
- package/src/extension/registration/lifecycle-handlers.ts +12 -12
- package/src/extension/registration/lifecycle.ts +2 -2
- package/src/extension/registration/observability.ts +2 -2
- package/src/extension/registration/registration-types.ts +3 -3
- package/src/extension/registration/runtime-cleanup.ts +1 -1
- package/src/extension/registration/subagent-helpers.ts +2 -2
- package/src/extension/registration/subagent-manager-setup.ts +2 -2
- package/src/extension/registration/subagent-tools.ts +21 -16
- package/src/extension/registration/team-tool.ts +108 -17
- package/src/extension/registration/viewers.ts +3 -4
- package/src/extension/registration/wire-cross-extension.ts +7 -7
- package/src/extension/rpc-hmac.ts +3 -2
- package/src/extension/run-bundle-schema.ts +13 -4
- package/src/extension/run-export.ts +2 -2
- package/src/extension/run-index.ts +2 -3
- package/src/extension/run-maintenance.ts +57 -1
- package/src/extension/team-manager-command.ts +3 -1
- package/src/extension/team-tool/anchor.ts +8 -2
- package/src/extension/team-tool/api.ts +117 -39
- package/src/extension/team-tool/cancel.ts +23 -8
- package/src/extension/team-tool/chain-executor.ts +1 -1
- package/src/extension/team-tool/dispatch/automate.ts +17 -2
- package/src/extension/team-tool/dispatch/control.ts +17 -2
- package/src/extension/team-tool/dispatch/manage.ts +34 -2
- package/src/extension/team-tool/dispatch/run.ts +17 -2
- package/src/extension/team-tool/dispatch/status.ts +37 -5
- package/src/extension/team-tool/doctor.ts +2 -2
- package/src/extension/team-tool/explain.ts +1 -1
- package/src/extension/team-tool/goal-wrap.ts +5 -5
- package/src/extension/team-tool/goal.ts +30 -9
- package/src/extension/team-tool/handle-schedule.ts +37 -19
- package/src/extension/team-tool/inspect.ts +21 -5
- package/src/extension/team-tool/lifecycle-actions.ts +53 -10
- package/src/extension/team-tool/parallel-dispatch.ts +14 -5
- package/src/extension/team-tool/param-error.ts +24 -0
- package/src/extension/team-tool/respond.ts +20 -6
- package/src/extension/team-tool/run.ts +27 -17
- package/src/extension/team-tool/status.ts +11 -5
- package/src/extension/team-tool.ts +26 -19
- package/src/hooks/registry.ts +1 -1
- package/src/i18n.ts +22 -0
- package/src/observability/event-bus.ts +1 -1
- package/src/prompt/prompt-runtime.ts +2 -2
- package/src/runtime/README.md +35 -0
- package/src/runtime/agent-control.ts +1 -1
- package/src/runtime/anchor-manager.ts +0 -2
- package/src/runtime/async-runner.ts +1 -1
- package/src/runtime/attention-events.ts +1 -1
- package/src/runtime/auto-summarize.ts +0 -2
- package/src/runtime/background-runner.ts +103 -30
- package/src/runtime/{crew-broker-child.ts → broker/crew-broker-child.ts} +2 -2
- package/src/runtime/{crew-broker-client.ts → broker/crew-broker-client.ts} +4 -7
- package/src/runtime/{crew-broker.ts → broker/crew-broker.ts} +13 -21
- package/src/runtime/chain-runner.ts +50 -5
- package/src/runtime/{child-pi-constants.ts → child-pi/child-pi-constants.ts} +1 -1
- package/src/runtime/{child-pi-kill.ts → child-pi/child-pi-kill.ts} +3 -3
- package/src/runtime/{child-pi-spawn.ts → child-pi/child-pi-spawn.ts} +28 -12
- package/src/runtime/{child-pi-steering.ts → child-pi/child-pi-steering.ts} +1 -1
- package/src/runtime/{child-pi-streams.ts → child-pi/child-pi-streams.ts} +11 -4
- package/src/runtime/{child-pi-transcript.ts → child-pi/child-pi-transcript.ts} +6 -6
- package/src/runtime/{child-pi.ts → child-pi/child-pi.ts} +28 -72
- package/src/runtime/{compact-stages → compaction/compact-stages}/bounded-tail.ts +1 -1
- package/src/runtime/{compact-stages → compaction/compact-stages}/index.ts +2 -2
- package/src/runtime/{compaction-summary.ts → compaction/compaction-summary.ts} +3 -3
- package/src/runtime/{tool-output-pruner.ts → compaction/tool-output-pruner.ts} +1 -1
- package/src/runtime/custom-tools/irc-tool.ts +2 -2
- package/src/runtime/delivery-coordinator.ts +0 -3
- package/src/runtime/diagnostic-export.ts +3 -3
- package/src/runtime/foreground-control.ts +1 -1
- package/src/runtime/foreground-watchdog.ts +1 -1
- package/src/runtime/{adaptive-plan.ts → goal-workflow/adaptive-plan.ts} +8 -8
- package/src/runtime/{dynamic-workflow-context.ts → goal-workflow/dynamic-workflow-context.ts} +16 -16
- package/src/runtime/{dynamic-workflow-runner.ts → goal-workflow/dynamic-workflow-runner.ts} +10 -10
- package/src/runtime/{goal-achievement.ts → goal-workflow/goal-achievement.ts} +3 -3
- package/src/runtime/{goal-evaluator.ts → goal-workflow/goal-evaluator.ts} +8 -8
- package/src/runtime/{goal-loop-runner.ts → goal-workflow/goal-loop-runner.ts} +27 -25
- package/src/runtime/{goal-state-store.ts → goal-workflow/goal-state-store.ts} +8 -8
- package/src/runtime/{plan-templates.ts → goal-workflow/plan-templates.ts} +1 -1
- package/src/runtime/group-join.ts +3 -3
- package/src/runtime/handoff-manager.ts +0 -2
- package/src/runtime/{heartbeat-watcher.ts → heartbeat/heartbeat-watcher.ts} +7 -7
- package/src/runtime/iteration-hooks.ts +1 -1
- package/src/runtime/{live-agent-control.ts → live-session/live-agent-control.ts} +2 -2
- package/src/runtime/{live-agent-manager.ts → live-session/live-agent-manager.ts} +4 -4
- package/src/runtime/{live-session-runtime.ts → live-session/live-session-runtime.ts} +39 -41
- package/src/runtime/manifest-cache.ts +1 -1
- package/src/runtime/{model-fallback.ts → model/model-fallback.ts} +1 -1
- package/src/runtime/{pi-args.ts → model/pi-args.ts} +20 -5
- package/src/runtime/model/provider-extensions.ts +116 -0
- package/src/runtime/{runtime-policy.ts → model/runtime-policy.ts} +2 -2
- package/src/runtime/{runtime-resolver.ts → model/runtime-resolver.ts} +3 -3
- package/src/runtime/{runtime-warmup.ts → model/runtime-warmup.ts} +8 -8
- package/src/runtime/orphan-worker-registry.ts +1 -1
- package/src/runtime/{progress-tracker.ts → output/progress-tracker.ts} +1 -1
- package/src/runtime/{result-extractor.ts → output/result-extractor.ts} +4 -4
- package/src/runtime/{sidechain-output.ts → output/sidechain-output.ts} +2 -2
- package/src/runtime/{stream-preview.ts → output/stream-preview.ts} +1 -1
- package/src/runtime/{streaming-output.ts → output/streaming-output.ts} +2 -2
- package/src/runtime/{tool-progress.ts → output/tool-progress.ts} +1 -1
- package/src/runtime/parent-guard.ts +30 -10
- package/src/runtime/pipeline-runner.ts +2 -2
- package/src/runtime/policy-engine.ts +2 -2
- package/src/runtime/{cancellation.ts → process/cancellation.ts} +1 -1
- package/src/runtime/{post-exit-stdio-guard.ts → process/post-exit-stdio-guard.ts} +1 -1
- package/src/runtime/{process-lifecycle.ts → process/process-lifecycle.ts} +3 -3
- package/src/runtime/{checkpoint.ts → recovery/checkpoint.ts} +4 -4
- package/src/runtime/{crash-recovery.ts → recovery/crash-recovery.ts} +93 -21
- package/src/runtime/{overflow-recovery.ts → recovery/overflow-recovery.ts} +1 -1
- package/src/runtime/{recovery-recipes.ts → recovery/recovery-recipes.ts} +1 -1
- package/src/runtime/{retry-executor.ts → recovery/retry-executor.ts} +2 -2
- package/src/runtime/{retry-runner.ts → recovery/retry-runner.ts} +2 -8
- package/src/runtime/run-tracker.ts +1 -1
- package/src/runtime/run-worker.ts +3 -3
- package/src/runtime/{coalesce-tasks.ts → scheduling/coalesce-tasks.ts} +3 -3
- package/src/runtime/{concurrency.ts → scheduling/concurrency.ts} +1 -1
- package/src/runtime/{parallel-research.ts → scheduling/parallel-research.ts} +4 -2
- package/src/runtime/{run-coalesced-task-group.ts → scheduling/run-coalesced-task-group.ts} +95 -36
- package/src/runtime/{task-graph-scheduler.ts → scheduling/task-graph-scheduler.ts} +1 -1
- package/src/runtime/session-resources.ts +1 -1
- package/src/runtime/settings-store.ts +1 -1
- package/src/runtime/single-agent-compose.ts +1 -0
- package/src/runtime/stale-reconciler.ts +1 -1
- package/src/runtime/subagent-manager.ts +1 -1
- package/src/runtime/supervisor-contact.ts +1 -1
- package/src/runtime/task-output-context.ts +7 -5
- package/src/runtime/task-runner/child-executor.ts +62 -22
- package/src/runtime/task-runner/live-executor.ts +8 -8
- package/src/runtime/task-runner/post-execution.ts +12 -12
- package/src/runtime/task-runner/pre-execution.ts +6 -6
- package/src/runtime/task-runner/progress.ts +1 -1
- package/src/runtime/task-runner/run-projection.ts +1 -1
- package/src/runtime/task-runner/scaffold-executor.ts +1 -1
- package/src/runtime/task-runner/state-helpers.ts +2 -2
- package/src/runtime/task-runner.ts +4 -4
- package/src/runtime/team-runner.ts +380 -139
- package/src/runtime/{completion-guard.ts → verification/completion-guard.ts} +1 -1
- package/src/runtime/{green-contract.ts → verification/green-contract.ts} +1 -1
- package/src/runtime/{post-checks.ts → verification/post-checks.ts} +4 -4
- package/src/runtime/{verification-gates.ts → verification/verification-gates.ts} +5 -5
- package/src/runtime/{verification-integrity.ts → verification/verification-integrity.ts} +1 -1
- package/src/schema/config-schema.ts +1 -0
- package/src/schema/team-tool-schema.ts +133 -177
- package/src/state/README.md +44 -0
- package/src/state/atomic-write.ts +24 -3
- package/src/state/{locks.ts → coordination/locks.ts} +118 -38
- package/src/state/{mailbox.ts → coordination/mailbox.ts} +14 -8
- package/src/state/{schedule.ts → coordination/schedule.ts} +3 -3
- package/src/state/{task-claims.ts → coordination/task-claims.ts} +1 -1
- package/src/state/decision-ledger.ts +1 -1
- package/src/state/{event-log-rotation.ts → event-log/event-log-rotation.ts} +161 -31
- package/src/state/{event-log.ts → event-log/event-log.ts} +38 -26
- package/src/state/{jsonl-writer.ts → event-log/jsonl-writer.ts} +14 -6
- package/src/state/hook-instinct-bridge.ts +2 -2
- package/src/state/{active-run-registry.ts → stores/active-run-registry.ts} +7 -7
- package/src/state/{artifact-store.ts → stores/artifact-store.ts} +62 -4
- package/src/state/{blob-store.ts → stores/blob-store.ts} +3 -3
- package/src/state/{health-store.ts → stores/health-store.ts} +3 -3
- package/src/state/{instinct-store.ts → stores/instinct-store.ts} +3 -3
- package/src/state/{observation-store.ts → stores/observation-store.ts} +2 -2
- package/src/state/{run-cache.ts → stores/run-cache.ts} +4 -4
- package/src/state/{run-graph.ts → stores/run-graph.ts} +4 -4
- package/src/state/{run-metrics.ts → stores/run-metrics.ts} +3 -3
- package/src/state/{state-store.ts → stores/state-store.ts} +236 -17
- package/src/state/types.ts +27 -3
- package/src/ui/component.ts +55 -0
- package/src/ui/crew-select-list.ts +3 -1
- package/src/ui/dashboard-panes/agents-pane.ts +1 -1
- package/src/ui/dwf-phase-display.ts +1 -1
- package/src/ui/heartbeat-aggregator.ts +1 -1
- package/src/ui/keybinding-map.ts +179 -6
- package/src/ui/layout-primitives.ts +9 -5
- package/src/ui/live-conversation-overlay.ts +1 -1
- package/src/ui/live-run-sidebar.ts +1 -1
- package/src/ui/overlay-stack.ts +148 -0
- package/src/ui/overlays/agent-picker-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-compose-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-detail-overlay.ts +2 -2
- package/src/ui/powerbar-publisher.ts +1 -1
- package/src/ui/render-scheduler.ts +1 -1
- package/src/ui/run-action-dispatcher.ts +3 -3
- package/src/ui/run-dashboard.ts +5 -33
- package/src/ui/run-event-bus.ts +3 -3
- package/src/ui/run-snapshot-cache.ts +37 -18
- package/src/ui/settings-overlay.ts +13 -21
- package/src/ui/snapshot-types.ts +1 -1
- package/src/ui/status-colors.ts +0 -2
- package/src/ui/terminal-status.ts +1 -1
- package/src/ui/theme-adapter.ts +33 -13
- package/src/ui/tool-renderers/index.ts +8 -0
- package/src/ui/transcript-viewer.ts +37 -13
- package/src/ui/widget/index.ts +32 -9
- package/src/ui/widget/widget-formatters.ts +62 -4
- package/src/ui/widget/widget-model.ts +2 -2
- package/src/ui/widget/widget-renderer.ts +1 -1
- package/src/utils/conflict-detect.ts +58 -5
- package/src/utils/ndjson.ts +2 -2
- package/src/utils/socket-path.ts +1 -1
- package/src/workflows/workflow-config.ts +1 -1
- package/src/worktree/cleanup.ts +1 -1
- package/src/worktree/worktree-manager.ts +88 -39
- package/workflows/chain.workflow.md +2 -2
- package/index.bundle.ts +0 -25
- package/scripts/bench-check.mjs +0 -96
- package/scripts/bench-cold-start.mjs +0 -216
- package/scripts/build-bundle.mjs +0 -92
- package/scripts/check-all-skills.ts +0 -294
- package/scripts/check-bundle-size.mjs +0 -38
- package/scripts/check-bundle-staleness.mjs +0 -97
- package/scripts/check-conflict-markers.mjs +0 -91
- package/scripts/check-lazy-imports.mjs +0 -28
- package/scripts/dev-runner.mjs +0 -106
- package/scripts/profile-startup.mjs +0 -125
- package/scripts/release-smoke.mjs +0 -74
- package/scripts/run-bench.mjs +0 -47
- package/scripts/run-real-chain.ts +0 -41
- package/scripts/smoke-team-perf.ts +0 -43
- package/scripts/test-issue-29-crash.ts +0 -111
- package/scripts/test-issue-29-e2e.ts +0 -183
- package/scripts/test-issue-29-real-runtime.ts +0 -330
- package/scripts/test-issue-29-real-tasks.ts +0 -387
- package/scripts/test-issue-29-team-tool.ts +0 -105
- package/scripts/test-runner.mjs +0 -84
- package/scripts/verify-flicker-fix.ts +0 -109
- package/scripts/verify-skill.ts +0 -550
- package/scripts/watch-bundle.mjs +0 -259
- package/scripts/watchdog-harness.ts +0 -119
- package/src/adapters/claude-adapter.ts +0 -23
- package/src/adapters/codex-adapter.ts +0 -21
- package/src/adapters/cursor-adapter.ts +0 -17
- package/src/adapters/export-util.ts +0 -143
- package/src/adapters/index.ts +0 -15
- package/src/adapters/registry.ts +0 -18
- package/src/adapters/types.ts +0 -23
- package/src/runtime/code-summary.ts +0 -292
- package/src/runtime/cross-extension-rpc.ts +0 -143
- package/src/runtime/hidden-handoff.ts +0 -407
- package/src/runtime/prose-compressor.ts +0 -162
- package/src/subagents/async-entry.ts +0 -1
- package/src/subagents/index.ts +0 -3
- package/src/subagents/live/control.ts +0 -1
- package/src/subagents/live/manager.ts +0 -1
- package/src/subagents/live/realtime.ts +0 -1
- package/src/subagents/live/session-runtime.ts +0 -1
- package/src/subagents/manager.ts +0 -1
- package/src/subagents/spawn.ts +0 -1
- package/test-integration-check.ts +0 -118
- /package/src/runtime/{broker-issuer.ts → broker/broker-issuer.ts} +0 -0
- /package/src/runtime/{crew-broker-tokens.ts → broker/crew-broker-tokens.ts} +0 -0
- /package/src/runtime/{child-pi-pool.ts → child-pi/child-pi-pool.ts} +0 -0
- /package/src/runtime/{compact-pipeline.ts → compaction/compact-pipeline.ts} +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/ansi-strip-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/blank-collapse-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/deduplicate-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/head-snap-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/tail-capture-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/truncation-stage.ts +0 -0
- /package/src/runtime/{important-line-classifier.ts → compaction/important-line-classifier.ts} +0 -0
- /package/src/runtime/{heartbeat-gradient.ts → heartbeat/heartbeat-gradient.ts} +0 -0
- /package/src/runtime/{worker-heartbeat.ts → heartbeat/worker-heartbeat.ts} +0 -0
- /package/src/runtime/{worker-startup.ts → heartbeat/worker-startup.ts} +0 -0
- /package/src/runtime/{intercom-bridge.ts → live-session/intercom-bridge.ts} +0 -0
- /package/src/runtime/{live-control-realtime.ts → live-session/live-control-realtime.ts} +0 -0
- /package/src/runtime/{live-extension-bridge.ts → live-session/live-extension-bridge.ts} +0 -0
- /package/src/runtime/{live-irc.ts → live-session/live-irc.ts} +0 -0
- /package/src/runtime/{live-session-health.ts → live-session/live-session-health.ts} +0 -0
- /package/src/runtime/{model-resolver.ts → model/model-resolver.ts} +0 -0
- /package/src/runtime/{model-scope.ts → model/model-scope.ts} +0 -0
- /package/src/runtime/{output-validator.ts → output/output-validator.ts} +0 -0
- /package/src/runtime/{pi-json-output.ts → output/pi-json-output.ts} +0 -0
- /package/src/runtime/{progress-event-coalescer.ts → output/progress-event-coalescer.ts} +0 -0
- /package/src/runtime/{cancellation-token.ts → process/cancellation-token.ts} +0 -0
- /package/src/runtime/{zombie-scanner.ts → process/zombie-scanner.ts} +0 -0
- /package/src/runtime/{crash-classification.ts → recovery/crash-classification.ts} +0 -0
- /package/src/runtime/{batch-barrier.ts → scheduling/batch-barrier.ts} +0 -0
- /package/src/runtime/{global-worker-cap.ts → scheduling/global-worker-cap.ts} +0 -0
- /package/src/runtime/{parallel-utils.ts → scheduling/parallel-utils.ts} +0 -0
- /package/src/runtime/{scheduler.ts → scheduling/scheduler.ts} +0 -0
- /package/src/runtime/{semaphore.ts → scheduling/semaphore.ts} +0 -0
- /package/src/runtime/{task-graph.ts → scheduling/task-graph.ts} +0 -0
- /package/src/runtime/{verification-worktree.ts → verification/verification-worktree.ts} +0 -0
- /package/src/state/{event-reconstructor.ts → event-log/event-reconstructor.ts} +0 -0
- /package/src/state/{worker-atomic-writer.ts → event-log/worker-atomic-writer.ts} +0 -0
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Cold-start benchmark: bundle vs strip-types.
|
|
4
|
-
*
|
|
5
|
-
* Compares two entry paths from a fresh node process:
|
|
6
|
-
* - STRIP-TYPES: node --experimental-strip-types loads src/extension/register.ts
|
|
7
|
-
* (or src/extension/index.ts via the package entry)
|
|
8
|
-
* - BUNDLE: node loads dist/index.mjs (esbuild-bundled 2.9MB single file)
|
|
9
|
-
*
|
|
10
|
-
* For each path we spawn N child node processes and measure:
|
|
11
|
-
* - totalMs: time from process spawn to its exit
|
|
12
|
-
* - importMs: time the child reports for `await import(...)`
|
|
13
|
-
* - registerMs: time the child reports for registerPiTeams(mockPi)
|
|
14
|
-
*
|
|
15
|
-
* We report:
|
|
16
|
-
* - per-path median, p95, max for each metric
|
|
17
|
-
* - bundle vs strip-types speedup (negative = bundle faster)
|
|
18
|
-
*
|
|
19
|
-
* Usage:
|
|
20
|
-
* node scripts/bench-cold-start.mjs # default 10 iters
|
|
21
|
-
* node scripts/bench-cold-start.mjs --iters 20
|
|
22
|
-
*
|
|
23
|
-
* Output goes to stdout as JSON plus a human-readable summary.
|
|
24
|
-
*/
|
|
25
|
-
import { execFileSync, spawnSync } from "node:child_process";
|
|
26
|
-
import * as fs from "node:fs";
|
|
27
|
-
import * as path from "node:path";
|
|
28
|
-
import { pathToFileURL } from "node:url";
|
|
29
|
-
|
|
30
|
-
const root = path.resolve(import.meta.dirname, "..");
|
|
31
|
-
const args = process.argv.slice(2);
|
|
32
|
-
let iters = 10;
|
|
33
|
-
for (let i = 0; i < args.length; i++) {
|
|
34
|
-
if (args[i] === "--iters" && args[i + 1]) {
|
|
35
|
-
iters = Number(args[i + 1]);
|
|
36
|
-
i++;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Driver template. We capture wall-clock per sample using performance.now()
|
|
41
|
-
// and emit JSON lines (one per sample). The outer harness parses them.
|
|
42
|
-
const driverTemplate = (entrySpec, registerImport) => `
|
|
43
|
-
import { performance } from "node:perf_hooks";
|
|
44
|
-
|
|
45
|
-
const tSpawn = performance.now();
|
|
46
|
-
|
|
47
|
-
function createEvents() {
|
|
48
|
-
const handlers = new Map();
|
|
49
|
-
return {
|
|
50
|
-
on(event, handler) {
|
|
51
|
-
const set = handlers.get(event) ?? new Set();
|
|
52
|
-
set.add(handler);
|
|
53
|
-
handlers.set(event, set);
|
|
54
|
-
return () => set.delete(handler);
|
|
55
|
-
},
|
|
56
|
-
emit(event, payload) {
|
|
57
|
-
for (const h of handlers.get(event) ?? []) h(payload);
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const mockPi = {
|
|
63
|
-
cwd: process.cwd(),
|
|
64
|
-
events: createEvents(),
|
|
65
|
-
hasUI: false,
|
|
66
|
-
getFlag: () => undefined,
|
|
67
|
-
getAllFlags: () => ({}),
|
|
68
|
-
settings: {},
|
|
69
|
-
storage: undefined,
|
|
70
|
-
on() {},
|
|
71
|
-
registerTool() {},
|
|
72
|
-
registerCommand() {},
|
|
73
|
-
appendEntry: async () => undefined,
|
|
74
|
-
sendMessage: async () => undefined,
|
|
75
|
-
sendUserMessage: async () => undefined,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const tImport0 = performance.now();
|
|
79
|
-
const entry = await import(${JSON.stringify(entrySpec)});
|
|
80
|
-
const tImportMs = performance.now() - tImport0;
|
|
81
|
-
|
|
82
|
-
const register = ${registerImport};
|
|
83
|
-
|
|
84
|
-
const tReg0 = performance.now();
|
|
85
|
-
register(mockPi);
|
|
86
|
-
const tRegMs = performance.now() - tReg0;
|
|
87
|
-
|
|
88
|
-
const tTotal = performance.now();
|
|
89
|
-
process.stdout.write(JSON.stringify({
|
|
90
|
-
total: tTotal - tSpawn,
|
|
91
|
-
import: tImportMs,
|
|
92
|
-
register: tRegMs,
|
|
93
|
-
defaultKind: typeof entry.default,
|
|
94
|
-
hasRegister: typeof ${registerImport === "entry.registerPiTeams" ? "entry.registerPiTeams" : "register"},
|
|
95
|
-
}) + "\\n");
|
|
96
|
-
`;
|
|
97
|
-
|
|
98
|
-
async function runPath(label, entrySpec, registerImport, itersCount) {
|
|
99
|
-
const driverPath = path.join(root, `.bench-${label}-${process.pid}.mjs`);
|
|
100
|
-
const driverSrc = driverTemplate(entrySpec, registerImport);
|
|
101
|
-
fs.writeFileSync(driverPath, driverSrc, "utf-8");
|
|
102
|
-
|
|
103
|
-
const cmd = label === "strip-types"
|
|
104
|
-
? ["--experimental-strip-types", "--no-warnings", driverPath]
|
|
105
|
-
: ["--no-warnings", driverPath];
|
|
106
|
-
|
|
107
|
-
const samples = [];
|
|
108
|
-
for (let i = 0; i < itersCount; i++) {
|
|
109
|
-
const t0 = performance.now();
|
|
110
|
-
const r = spawnSync(process.execPath, cmd, { encoding: "utf-8", cwd: root });
|
|
111
|
-
const wall = performance.now() - t0;
|
|
112
|
-
if (r.status !== 0) {
|
|
113
|
-
console.error(`[bench:${label}] iter ${i} failed:`, r.stderr?.slice(0, 200));
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
const lastLine = r.stdout.trim().split("\n").pop();
|
|
117
|
-
try {
|
|
118
|
-
const sample = JSON.parse(lastLine);
|
|
119
|
-
samples.push({ ...sample, wall });
|
|
120
|
-
} catch {
|
|
121
|
-
console.error(`[bench:${label}] iter ${i} parse error:`, lastLine);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
fs.unlinkSync(driverPath);
|
|
126
|
-
return samples;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function stats(arr) {
|
|
130
|
-
const sorted = [...arr].sort((a, b) => a - b);
|
|
131
|
-
const p = (q) => sorted[Math.min(sorted.length - 1, Math.floor((sorted.length - 1) * q))];
|
|
132
|
-
return {
|
|
133
|
-
n: sorted.length,
|
|
134
|
-
min: sorted[0],
|
|
135
|
-
p50: p(0.5),
|
|
136
|
-
p95: p(0.95),
|
|
137
|
-
max: sorted[sorted.length - 1],
|
|
138
|
-
mean: sorted.reduce((s, x) => s + x, 0) / sorted.length,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function pctDelta(newer, older) {
|
|
143
|
-
// positive = newer is slower than older
|
|
144
|
-
return (((newer - older) / older) * 100).toFixed(1);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
console.log(`[bench] Running ${iters} iters per path...`);
|
|
148
|
-
console.log("");
|
|
149
|
-
|
|
150
|
-
const stripSpec = pathToFileURL(path.join(root, "src/extension/register.ts")).href;
|
|
151
|
-
const stripRegister = "(await import(" + JSON.stringify(stripSpec) + ")).registerPiTeams";
|
|
152
|
-
const stripSamples = await runPath("strip-types", stripSpec, stripRegister, iters);
|
|
153
|
-
|
|
154
|
-
const bundleSpec = pathToFileURL(path.join(root, "dist/index.mjs")).href;
|
|
155
|
-
const bundleRegister = "(await import(" + JSON.stringify(bundleSpec) + ")).registerPiTeams";
|
|
156
|
-
const bundleSamples = await runPath("bundle", bundleSpec, bundleRegister, iters);
|
|
157
|
-
|
|
158
|
-
if (stripSamples.length === 0 || bundleSamples.length === 0) {
|
|
159
|
-
console.error("[bench] insufficient samples; aborting");
|
|
160
|
-
process.exit(1);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const summary = {
|
|
164
|
-
timestamp: new Date().toISOString(),
|
|
165
|
-
iters,
|
|
166
|
-
strip: {
|
|
167
|
-
total: stats(stripSamples.map((s) => s.total)),
|
|
168
|
-
import: stats(stripSamples.map((s) => s.import)),
|
|
169
|
-
register: stats(stripSamples.map((s) => s.register)),
|
|
170
|
-
wall: stats(stripSamples.map((s) => s.wall)),
|
|
171
|
-
},
|
|
172
|
-
bundle: {
|
|
173
|
-
total: stats(bundleSamples.map((s) => s.total)),
|
|
174
|
-
import: stats(bundleSamples.map((s) => s.import)),
|
|
175
|
-
register: stats(bundleSamples.map((s) => s.register)),
|
|
176
|
-
wall: stats(bundleSamples.map((s) => s.wall)),
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
// Speedup = strip - bundle (positive = bundle faster)
|
|
181
|
-
summary.speedup = {
|
|
182
|
-
total: summary.strip.total.p50 - summary.bundle.total.p50,
|
|
183
|
-
totalPct: pctDelta(summary.bundle.total.p50, summary.strip.total.p50),
|
|
184
|
-
import: summary.strip.import.p50 - summary.bundle.import.p50,
|
|
185
|
-
importPct: pctDelta(summary.bundle.import.p50, summary.strip.import.p50),
|
|
186
|
-
register: summary.strip.register.p50 - summary.bundle.register.p50,
|
|
187
|
-
registerPct: pctDelta(summary.bundle.register.p50, summary.strip.register.p50),
|
|
188
|
-
wall: summary.strip.wall.p50 - summary.bundle.wall.p50,
|
|
189
|
-
wallPct: pctDelta(summary.bundle.wall.p50, summary.strip.wall.p50),
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
// Print human-readable summary
|
|
193
|
-
console.log("=== Cold-start benchmark: strip-types vs bundle ===\n");
|
|
194
|
-
|
|
195
|
-
const printPath = (label, data) => {
|
|
196
|
-
console.log(` ${label}:`);
|
|
197
|
-
console.log(` total (child process wall-clock): p50=${data.total.p50.toFixed(1)}ms p95=${data.total.p95.toFixed(1)}ms min=${data.total.min.toFixed(1)}ms`);
|
|
198
|
-
console.log(` import (await import(...)): p50=${data.import.p50.toFixed(1)}ms p95=${data.import.p95.toFixed(1)}ms`);
|
|
199
|
-
console.log(` register (registerPiTeams(mockPi)): p50=${data.register.p50.toFixed(1)}ms p95=${data.register.p95.toFixed(1)}ms`);
|
|
200
|
-
console.log("");
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
printPath("STRIP-TYPES (--experimental-strip-types + 1100 .ts files)", summary.strip);
|
|
204
|
-
printPath("BUNDLE (dist/index.mjs, 2.9MB single file)", summary.bundle);
|
|
205
|
-
|
|
206
|
-
console.log(` Speedup (bundle vs strip-types, p50):`);
|
|
207
|
-
console.log(` total: ${summary.speedup.total >= 0 ? "FASTER" : "SLOWER"} by ${Math.abs(summary.speedup.total).toFixed(1)}ms (${summary.speedup.totalPct}%)`);
|
|
208
|
-
console.log(` import: ${summary.speedup.import >= 0 ? "FASTER" : "SLOWER"} by ${Math.abs(summary.speedup.import).toFixed(1)}ms (${summary.speedup.importPct}%)`);
|
|
209
|
-
console.log(` register: ${summary.speedup.register >= 0 ? "FASTER" : "SLOWER"} by ${Math.abs(summary.speedup.register).toFixed(1)}ms (${summary.speedup.registerPct}%)`);
|
|
210
|
-
console.log(` outer wall: ${summary.speedup.wall >= 0 ? "FASTER" : "SLOWER"} by ${Math.abs(summary.speedup.wall).toFixed(1)}ms (${summary.speedup.wallPct}%)`);
|
|
211
|
-
|
|
212
|
-
const benchDir = path.join(root, ".bench");
|
|
213
|
-
fs.mkdirSync(benchDir, { recursive: true });
|
|
214
|
-
const outFile = path.join(benchDir, `cold-start-${Date.now()}.json`);
|
|
215
|
-
fs.writeFileSync(outFile, JSON.stringify(summary, null, 2) + "\n", "utf-8");
|
|
216
|
-
console.log(`\n[bench] Raw results: ${outFile}`);
|
package/scripts/build-bundle.mjs
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* 5.5 — Bundle pi-crew into a single ESM file using esbuild.
|
|
4
|
-
*
|
|
5
|
-
* Output:
|
|
6
|
-
* dist/index.mjs — bundled extension entrypoint
|
|
7
|
-
* dist/index.mjs.map — source map
|
|
8
|
-
*
|
|
9
|
-
* Pi peer dependencies are kept external. Bundling shrinks parse+module-
|
|
10
|
-
* resolution cost on cold start: with strip-types Node still has to parse
|
|
11
|
-
* each .ts file individually, so a single .mjs cuts the per-file overhead.
|
|
12
|
-
*
|
|
13
|
-
* This script is invoked by `npm run build:bundle`. The `package.json#exports`
|
|
14
|
-
* field is configured so:
|
|
15
|
-
* - `dist/index.mjs` is the preferred entrypoint when present (set by Pi
|
|
16
|
-
* extension loader via "pi.extensions").
|
|
17
|
-
* - `index.ts` remains the fallback when dist/ is missing (e.g. running
|
|
18
|
-
* directly out of a clone without prior build).
|
|
19
|
-
*/
|
|
20
|
-
import { build } from "esbuild";
|
|
21
|
-
import * as fs from "node:fs";
|
|
22
|
-
import * as path from "node:path";
|
|
23
|
-
import { fileURLToPath } from "node:url";
|
|
24
|
-
|
|
25
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
26
|
-
const root = path.resolve(here, "..");
|
|
27
|
-
|
|
28
|
-
const distDir = path.join(root, "dist");
|
|
29
|
-
fs.mkdirSync(distDir, { recursive: true });
|
|
30
|
-
|
|
31
|
-
const start = Date.now();
|
|
32
|
-
const result = await build({
|
|
33
|
-
// Bundle entry must be the bare extension (index.bundle.ts) NOT the
|
|
34
|
-
// entry shell (index.ts). If we bundled index.ts, the bundled code
|
|
35
|
-
// would re-resolve dist/index.mjs relative to ITS OWN location
|
|
36
|
-
// (file:///.../dist/index.mjs), producing dist/dist/index.mjs and a
|
|
37
|
-
// recursion error. index.bundle.ts has no shell logic so this is
|
|
38
|
-
// a clean single-file bundle. See index.bundle.ts header for details.
|
|
39
|
-
entryPoints: [path.join(root, "index.bundle.ts")],
|
|
40
|
-
bundle: true,
|
|
41
|
-
format: "esm",
|
|
42
|
-
platform: "node",
|
|
43
|
-
target: "node22",
|
|
44
|
-
outfile: path.join(distDir, "index.mjs"),
|
|
45
|
-
sourcemap: true,
|
|
46
|
-
logLevel: "info",
|
|
47
|
-
// Keep peer deps external so consumers' Pi versions resolve naturally.
|
|
48
|
-
external: [
|
|
49
|
-
"@earendil-works/pi-coding-agent",
|
|
50
|
-
"@earendil-works/pi-ai",
|
|
51
|
-
"@earendil-works/pi-agent-core",
|
|
52
|
-
"@earendil-works/pi-tui",
|
|
53
|
-
// Direct deps as well — bundling their full graph would inflate the
|
|
54
|
-
// output and override consumer-installed versions.
|
|
55
|
-
"cli-highlight",
|
|
56
|
-
"diff",
|
|
57
|
-
"jiti",
|
|
58
|
-
"@sinclair/typebox",
|
|
59
|
-
"acorn",
|
|
60
|
-
// esbuild must stay external: its CJS source references __filename/__dirname
|
|
61
|
-
// (CJS globals) for self-location. Bundling it into the ESM .mjs makes those
|
|
62
|
-
// undefined at runtime → "__filename is not defined" when the dynamic-workflow
|
|
63
|
-
// runner (or strip-types loader) invokes esbuild transformSync. Keeping it
|
|
64
|
-
// external lets it resolve from node_modules as proper CJS. (esbuild also
|
|
65
|
-
// ships a native binary, which shouldn't be bundled anyway.)
|
|
66
|
-
"esbuild",
|
|
67
|
-
],
|
|
68
|
-
// All node:* and Node-builtin modules are external by default for
|
|
69
|
-
// platform=node, but list explicitly for clarity.
|
|
70
|
-
//
|
|
71
|
-
// CJS-shim banner: pi-crew's dependency graph includes CommonJS modules
|
|
72
|
-
// (notably `yaml`) whose source calls `require("process")` etc. esbuild
|
|
73
|
-
// emits these as runtime `__require(...)` calls; in a pure-ESM context
|
|
74
|
-
// `require` is undefined, so we inject a `createRequire`-backed shim
|
|
75
|
-
// at the top of the bundle. This is the standard pattern for shipping
|
|
76
|
-
// CJS-mixed bundles as `.mjs`. See phase-2 H2 investigation (2026-06-30).
|
|
77
|
-
banner: {
|
|
78
|
-
js:
|
|
79
|
-
"// pi-crew bundled by scripts/build-bundle.mjs (5.5)\n" +
|
|
80
|
-
"// CJS-shim for legacy deps (yaml, etc.) that call require() in ESM context.\n" +
|
|
81
|
-
"import { createRequire as __piCrewCreateRequire } from 'node:module';\n" +
|
|
82
|
-
"const require = __piCrewCreateRequire(import.meta.url);\n" +
|
|
83
|
-
"const module = { exports: {} };\n" +
|
|
84
|
-
"const exports = module.exports;\n",
|
|
85
|
-
},
|
|
86
|
-
metafile: true,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
fs.writeFileSync(path.join(distDir, "build-meta.json"), JSON.stringify(result.metafile, null, 2) + "\n", "utf-8");
|
|
90
|
-
const elapsedMs = Date.now() - start;
|
|
91
|
-
const stat = fs.statSync(path.join(distDir, "index.mjs"));
|
|
92
|
-
console.log(`[build-bundle] dist/index.mjs ${(stat.size / 1024).toFixed(1)} KB in ${elapsedMs} ms`);
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Check All Skills Script
|
|
5
|
-
*
|
|
6
|
-
* Runs verify-skill.ts against all skills and produces a summary report.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* node scripts/check-all-skills.ts
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { spawnSync } from "node:child_process";
|
|
13
|
-
import * as fs from "node:fs";
|
|
14
|
-
import * as path from "node:path";
|
|
15
|
-
|
|
16
|
-
interface SkillSummary {
|
|
17
|
-
name: string;
|
|
18
|
-
path: string;
|
|
19
|
-
status: "pass" | "fail" | "warning";
|
|
20
|
-
warnings: string[];
|
|
21
|
-
errors: string[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface Report {
|
|
25
|
-
total: number;
|
|
26
|
-
passed: number;
|
|
27
|
-
failed: number;
|
|
28
|
-
warningsOnly: number;
|
|
29
|
-
skills: SkillSummary[];
|
|
30
|
-
timestamp: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const SKILLS_DIR = path.join(process.cwd(), "skills");
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get all skill directories
|
|
37
|
-
*/
|
|
38
|
-
function getSkillDirs(): string[] {
|
|
39
|
-
if (!fs.existsSync(SKILLS_DIR)) {
|
|
40
|
-
console.error("Skills directory not found: " + SKILLS_DIR);
|
|
41
|
-
return [];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const dirs: string[] = [];
|
|
45
|
-
const entries = fs.readdirSync(SKILLS_DIR, { withFileTypes: true });
|
|
46
|
-
|
|
47
|
-
for (const entry of entries) {
|
|
48
|
-
if (entry.isDirectory()) {
|
|
49
|
-
const skillPath = path.join(SKILLS_DIR, entry.name, "SKILL.md");
|
|
50
|
-
if (fs.existsSync(skillPath)) {
|
|
51
|
-
dirs.push(entry.name);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return dirs.sort();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Run verify-skill.ts for a single skill
|
|
61
|
-
*/
|
|
62
|
-
function verifySingleSkill(skillName: string): {
|
|
63
|
-
passed: boolean;
|
|
64
|
-
warnings: string[];
|
|
65
|
-
errors: string[];
|
|
66
|
-
} {
|
|
67
|
-
const skillPath = path.join(SKILLS_DIR, skillName, "SKILL.md");
|
|
68
|
-
|
|
69
|
-
const result = spawnSync("node", ["scripts/verify-skill.ts", skillPath], {
|
|
70
|
-
cwd: process.cwd(),
|
|
71
|
-
encoding: "utf-8",
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const output = result.stdout + result.stderr;
|
|
75
|
-
const warnings: string[] = [];
|
|
76
|
-
const errors: string[] = [];
|
|
77
|
-
|
|
78
|
-
// Parse output
|
|
79
|
-
const warningMatches = output.match(/[^\n]*⚠️[^\n]*/g);
|
|
80
|
-
const errorMatches = output.match(/[^\n]+FAIL[^\n]+/g);
|
|
81
|
-
|
|
82
|
-
if (warningMatches) {
|
|
83
|
-
warnings.push(...warningMatches.map((w) => w.trim()));
|
|
84
|
-
}
|
|
85
|
-
if (errorMatches) {
|
|
86
|
-
errors.push(...errorMatches.map((e) => e.trim()));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const passed = result.status === 0;
|
|
90
|
-
|
|
91
|
-
return { passed, warnings, errors };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Generate markdown report
|
|
96
|
-
*/
|
|
97
|
-
function generateMarkdownReport(report: Report): string {
|
|
98
|
-
const lines: string[] = [];
|
|
99
|
-
|
|
100
|
-
lines.push("# Skill Verification Report");
|
|
101
|
-
lines.push("");
|
|
102
|
-
lines.push("Generated: " + report.timestamp);
|
|
103
|
-
lines.push("");
|
|
104
|
-
|
|
105
|
-
// Summary table
|
|
106
|
-
lines.push("## Summary");
|
|
107
|
-
lines.push("");
|
|
108
|
-
lines.push("| Status | Count |");
|
|
109
|
-
lines.push("|--------|-------|");
|
|
110
|
-
lines.push("| PASS | " + report.passed + " |");
|
|
111
|
-
lines.push("| FAIL | " + report.failed + " |");
|
|
112
|
-
lines.push("| Warnings | " + report.warningsOnly + " |");
|
|
113
|
-
lines.push("| **Total** | **" + report.total + "** |");
|
|
114
|
-
lines.push("");
|
|
115
|
-
|
|
116
|
-
// Skill list by status
|
|
117
|
-
lines.push("## Skills by Status");
|
|
118
|
-
lines.push("");
|
|
119
|
-
|
|
120
|
-
// Passed skills
|
|
121
|
-
const passedSkills = report.skills.filter((s) => s.status === "pass");
|
|
122
|
-
if (passedSkills.length > 0) {
|
|
123
|
-
lines.push("### Passing Skills");
|
|
124
|
-
lines.push("");
|
|
125
|
-
for (const skill of passedSkills) {
|
|
126
|
-
lines.push("- " + skill.name);
|
|
127
|
-
}
|
|
128
|
-
lines.push("");
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Failed skills
|
|
132
|
-
const failedSkills = report.skills.filter((s) => s.status === "fail");
|
|
133
|
-
if (failedSkills.length > 0) {
|
|
134
|
-
lines.push("### Failing Skills");
|
|
135
|
-
lines.push("");
|
|
136
|
-
for (const skill of failedSkills) {
|
|
137
|
-
lines.push("- **" + skill.name + "**");
|
|
138
|
-
for (const error of skill.errors) {
|
|
139
|
-
lines.push(" - " + error);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
lines.push("");
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Warning skills
|
|
146
|
-
const warningSkills = report.skills.filter((s) => s.status === "warning");
|
|
147
|
-
if (warningSkills.length > 0) {
|
|
148
|
-
lines.push("### Skills with Warnings");
|
|
149
|
-
lines.push("");
|
|
150
|
-
for (const skill of warningSkills) {
|
|
151
|
-
lines.push("- **" + skill.name + "**");
|
|
152
|
-
for (const warning of skill.warnings) {
|
|
153
|
-
lines.push(" - " + warning);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
lines.push("");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Recommendations
|
|
160
|
-
lines.push("## Recommendations");
|
|
161
|
-
lines.push("");
|
|
162
|
-
if (failedSkills.length > 0) {
|
|
163
|
-
lines.push("1. Fix " + failedSkills.length + " failing skills to have proper RED/GREEN gates");
|
|
164
|
-
lines.push("2. Add trigger sections (When to Activate) if missing");
|
|
165
|
-
lines.push("3. Add anti-patterns sections to prevent common mistakes");
|
|
166
|
-
lines.push("");
|
|
167
|
-
}
|
|
168
|
-
if (warningSkills.length > 0) {
|
|
169
|
-
lines.push("4. Review " + warningSkills.length + " skills with warnings for improvements");
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return lines.join("\n");
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Generate JSON report
|
|
177
|
-
*/
|
|
178
|
-
function generateJsonReport(report: Report): string {
|
|
179
|
-
return JSON.stringify(report, null, 2);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Main entry point
|
|
184
|
-
*/
|
|
185
|
-
async function main() {
|
|
186
|
-
console.log("Checking all skills...\n");
|
|
187
|
-
|
|
188
|
-
const skillNames = getSkillDirs();
|
|
189
|
-
console.log("Found " + skillNames.length + " skills\n");
|
|
190
|
-
|
|
191
|
-
const report: Report = {
|
|
192
|
-
total: skillNames.length,
|
|
193
|
-
passed: 0,
|
|
194
|
-
failed: 0,
|
|
195
|
-
warningsOnly: 0,
|
|
196
|
-
skills: [],
|
|
197
|
-
timestamp: new Date().toISOString(),
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
for (const skillName of skillNames) {
|
|
201
|
-
process.stdout.write(".");
|
|
202
|
-
|
|
203
|
-
const result = verifySingleSkill(skillName);
|
|
204
|
-
|
|
205
|
-
let status: "pass" | "fail" | "warning" = "pass";
|
|
206
|
-
if (!result.passed && result.errors.length > 0) {
|
|
207
|
-
status = "fail";
|
|
208
|
-
report.failed++;
|
|
209
|
-
} else if (result.warnings.length > 0) {
|
|
210
|
-
status = "warning";
|
|
211
|
-
report.warningsOnly++;
|
|
212
|
-
} else {
|
|
213
|
-
report.passed++;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
report.skills.push({
|
|
217
|
-
name: skillName,
|
|
218
|
-
path: path.join("skills", skillName, "SKILL.md"),
|
|
219
|
-
status,
|
|
220
|
-
warnings: result.warnings,
|
|
221
|
-
errors: result.errors,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
console.log("\n\n");
|
|
226
|
-
|
|
227
|
-
// Print summary
|
|
228
|
-
console.log("=== Skill Verification Summary ===");
|
|
229
|
-
console.log("Total: " + report.total);
|
|
230
|
-
console.log("Passed: " + report.passed);
|
|
231
|
-
console.log("Failed: " + report.failed);
|
|
232
|
-
console.log("Warnings only: " + report.warningsOnly);
|
|
233
|
-
console.log("");
|
|
234
|
-
|
|
235
|
-
// List failed skills
|
|
236
|
-
if (report.failed > 0) {
|
|
237
|
-
console.log("Failing skills:");
|
|
238
|
-
for (const skill of report.skills.filter((s) => s.status === "fail")) {
|
|
239
|
-
console.log(" - " + skill.name);
|
|
240
|
-
for (const error of skill.errors) {
|
|
241
|
-
console.log(" " + error);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
console.log("");
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// List skills with warnings
|
|
248
|
-
if (report.warningsOnly > 0) {
|
|
249
|
-
console.log("Skills with warnings:");
|
|
250
|
-
for (const skill of report.skills.filter((s) => s.status === "warning")) {
|
|
251
|
-
console.log(" - " + skill.name);
|
|
252
|
-
for (const warning of skill.warnings) {
|
|
253
|
-
console.log(" " + warning);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
console.log("");
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Write reports
|
|
260
|
-
const reportDir = path.join(process.cwd(), "reports");
|
|
261
|
-
if (!fs.existsSync(reportDir)) {
|
|
262
|
-
fs.mkdirSync(reportDir, { recursive: true });
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
266
|
-
const mdReportPath = path.join(reportDir, "skill-verification-" + timestamp + ".md");
|
|
267
|
-
const jsonReportPath = path.join(reportDir, "skill-verification-" + timestamp + ".json");
|
|
268
|
-
const latestMdPath = path.join(reportDir, "skill-verification-latest.md");
|
|
269
|
-
const latestJsonPath = path.join(reportDir, "skill-verification-latest.json");
|
|
270
|
-
|
|
271
|
-
fs.writeFileSync(mdReportPath, generateMarkdownReport(report));
|
|
272
|
-
fs.writeFileSync(jsonReportPath, generateJsonReport(report));
|
|
273
|
-
fs.writeFileSync(latestMdPath, generateMarkdownReport(report));
|
|
274
|
-
fs.writeFileSync(latestJsonPath, generateJsonReport(report));
|
|
275
|
-
|
|
276
|
-
console.log("Reports written to:");
|
|
277
|
-
console.log(" - " + mdReportPath);
|
|
278
|
-
console.log(" - " + jsonReportPath);
|
|
279
|
-
console.log(" - " + latestMdPath + " (latest)");
|
|
280
|
-
console.log(" - " + latestJsonPath + " (latest)");
|
|
281
|
-
|
|
282
|
-
// Exit with appropriate code
|
|
283
|
-
if (report.failed > 0) {
|
|
284
|
-
process.exit(1);
|
|
285
|
-
} else if (report.warningsOnly > 0) {
|
|
286
|
-
process.exit(2);
|
|
287
|
-
}
|
|
288
|
-
process.exit(0);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
main().catch((err) => {
|
|
292
|
-
console.error("Fatal error:", err);
|
|
293
|
-
process.exit(1);
|
|
294
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* CI gate: enforce a max size budget on dist/index.mjs.
|
|
4
|
-
*
|
|
5
|
-
* The bundle is the cold-start entrypoint (preferred over strip-types
|
|
6
|
-
* loading since v0.9.17). A growing bundle directly increases parse
|
|
7
|
-
* time and npm install cost. This guard FAILS the build if the bundle
|
|
8
|
-
* exceeds the budget, surfacing regressions early.
|
|
9
|
-
*
|
|
10
|
-
* Budget: 3.5 MB (see ROADMAP-2026-07-27 Sprint 6 CI-4).
|
|
11
|
-
*
|
|
12
|
-
* Exits:
|
|
13
|
-
* 0 — bundle is within budget (or absent, deferring to build:bundle)
|
|
14
|
-
* 1 — bundle exceeds budget
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { existsSync, statSync } from "node:fs";
|
|
18
|
-
|
|
19
|
-
const BUDGET_BYTES = 3.5 * 1024 * 1024; // 3.5 MB
|
|
20
|
-
const distPath = "dist/index.mjs";
|
|
21
|
-
|
|
22
|
-
if (!existsSync(distPath)) {
|
|
23
|
-
console.log("[check-bundle-size] dist/index.mjs absent — nothing to check. OK.");
|
|
24
|
-
process.exit(0);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const sizeBytes = statSync(distPath).size;
|
|
28
|
-
|
|
29
|
-
if (sizeBytes > BUDGET_BYTES) {
|
|
30
|
-
console.error(
|
|
31
|
-
`[check-bundle-size] FAIL: dist/index.mjs (${(sizeBytes / 1024 / 1024).toFixed(2)} MB) exceeds budget (${(BUDGET_BYTES / 1024 / 1024).toFixed(1)} MB).`,
|
|
32
|
-
);
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
console.log(
|
|
37
|
-
`[check-bundle-size] OK: dist/index.mjs is ${(sizeBytes / 1024 / 1024).toFixed(2)} MB (budget ${(BUDGET_BYTES / 1024 / 1024).toFixed(1)} MB).`,
|
|
38
|
-
);
|