diff --git a/axiom-pi/README.md b/axiom-pi/README.md
new file mode 100644
index 00000000..4cb8b806
--- /dev/null
+++ b/axiom-pi/README.md
@@ -0,0 +1,74 @@
+# axiom-pi
+
+Axiom's commands and hooks for the [Pi coding agent](https://pi.dev/).
+
+Axiom's iOS/Apple-platform expertise lives in **skills**, which Pi loads natively
+(`npx skills add CharlesWiltgen/Axiom -a pi -g`). This extension adds the two
+layers Pi can't get from skills alone:
+
+- **`/axiom-*` commands** — the Axiom commands, ported to Pi. In Claude Code each
+ launches a sub-agent; Pi has no sub-agents, so each command sends a
+ natural-language prompt that triggers the matching skill inline.
+- **Session and tool hooks** — the parts of Axiom's Claude Code hooks that are
+ additive on Pi (skills cover the rest).
+
+## What it adds
+
+### Commands
+
+`/axiom-fix-build`, `/axiom-audit `, `/axiom-health-check`,
+`/axiom-analyze-crash`, `/axiom-triage`, `/axiom-console`, `/axiom-ui`,
+`/axiom-profile`, `/axiom-compare-traces`, `/axiom-optimize-build`,
+`/axiom-run-tests`, `/axiom-test-simulator`, `/axiom-screenshot`,
+`/axiom-status`, `/axiom-ask`.
+
+`/axiom-audit` offers the audit areas (memory, concurrency, security, …) as
+argument completions.
+
+### Hooks
+
+- **Session ground truth** (`before_agent_start`) — injects the iOS/Xcode
+ version behavioral rules (so the agent never claims iOS 26 "doesn't exist")
+ and lists which Axiom command-line tools (`xclog`, `xcsym`, `xcui`, `xcprof`)
+ are on your `PATH`. Gated to Apple projects; override with
+ `AXIOM_SESSION_CONTEXT=always|never`.
+- **Swift write guardrail** (`tool_result`) — runs `swiftformat` on written
+ `.swift` files (when installed) and flags `@State` declarations missing an
+ explicit access level.
+- **Crash-file routing** (`tool_result`) — when a `.ips`/`.crash`/`.xccrashpoint`
+ file is read, suggests the right `xcsym` command.
+- **Bash skill hints** (`tool_result`) — scans command output for known iOS
+ error signatures and points at the matching skill.
+
+## Install
+
+The recommended install gets the skills **and** this extension in one command —
+the repo's root `package.json` declares both via a `pi` manifest (`pi.skills` +
+`pi.extensions`):
+
+```bash
+pi install git:github.com/CharlesWiltgen/Axiom
+```
+
+To work on just the extension from a local checkout, symlink it into Pi's
+extensions directory instead:
+
+```bash
+ln -s "$(pwd)/axiom-pi" ~/.pi/agent/extensions/axiom-pi
+```
+
+Pi discovers extensions from `~/.pi/agent/extensions/` (global) and
+`.pi/extensions/` (project), reading the entry point from each package's
+`pi.extensions` field.
+
+## Develop
+
+```bash
+npm install # dev dependencies (Pi types, TypeScript, vitest)
+npm run typecheck
+npm test
+```
+
+The command table, session context, and guardrail logic are pure functions in
+`src/{commands,session,guardrails}.ts` with colocated tests; `src/index.ts` is
+the thin Pi wiring. Pi loads TypeScript directly — no build step.
diff --git a/axiom-pi/package-lock.json b/axiom-pi/package-lock.json
new file mode 100644
index 00000000..b85b55ea
--- /dev/null
+++ b/axiom-pi/package-lock.json
@@ -0,0 +1,3266 @@
+{
+ "name": "axiom-pi",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "axiom-pi",
+ "version": "0.0.0",
+ "license": "MIT",
+ "devDependencies": {
+ "@earendil-works/pi-coding-agent": "^0.79.3",
+ "@types/node": "^25.9.3",
+ "typescript": "^6.0.3",
+ "vitest": "^4.1.8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent": {
+ "version": "0.79.3",
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-coding-agent/-/pi-coding-agent-0.79.3.tgz",
+ "integrity": "sha512-B3rAyw4/f1l3EYjQpCKpevzuBIPjYor6fHxPHQpLMdn/NTv3536i1P4ZrsyFkKpXqJWH66xKK5hyf8sqRe3dGA==",
+ "dev": true,
+ "hasShrinkwrap": true,
+ "license": "MIT",
+ "dependencies": {
+ "@earendil-works/pi-agent-core": "^0.79.3",
+ "@earendil-works/pi-ai": "^0.79.3",
+ "@earendil-works/pi-tui": "^0.79.3",
+ "@silvia-odwyer/photon-node": "0.3.4",
+ "chalk": "5.6.2",
+ "cross-spawn": "7.0.6",
+ "diff": "8.0.4",
+ "glob": "13.0.6",
+ "highlight.js": "10.7.3",
+ "hosted-git-info": "9.0.3",
+ "ignore": "7.0.5",
+ "jiti": "2.7.0",
+ "minimatch": "10.2.5",
+ "proper-lockfile": "4.1.2",
+ "typebox": "1.1.38",
+ "undici": "8.3.0",
+ "yaml": "2.9.0"
+ },
+ "bin": {
+ "pi": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=22.19.0"
+ },
+ "optionalDependencies": {
+ "@mariozechner/clipboard": "0.3.9"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@anthropic-ai/sdk": {
+ "version": "0.91.1",
+ "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.91.1.tgz",
+ "integrity": "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-schema-to-ts": "^3.1.1"
+ },
+ "bin": {
+ "anthropic-ai-sdk": "bin/cli"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/crc32": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
+ "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/sha256-browser": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
+ "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-js": "^5.2.0",
+ "@aws-crypto/supports-web-crypto": "^5.2.0",
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/sha256-js": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
+ "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/supports-web-crypto": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
+ "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/util": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
+ "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/client-bedrock-runtime": {
+ "version": "3.1048.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1048.0.tgz",
+ "integrity": "sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/credential-provider-node": "^3.972.42",
+ "@aws-sdk/eventstream-handler-node": "^3.972.16",
+ "@aws-sdk/middleware-eventstream": "^3.972.12",
+ "@aws-sdk/middleware-websocket": "^3.972.19",
+ "@aws-sdk/token-providers": "3.1048.0",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/fetch-http-handler": "^5.4.2",
+ "@smithy/node-http-handler": "^4.7.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/core": {
+ "version": "3.974.11",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.974.11.tgz",
+ "integrity": "sha512-QpnINq5FZH6EOaDEkmHdT7eUunbvD27pDNQypaWjFyYz7Zl1q3UCMQErBZxpmfGfI7MvI2TlK8KTkgNpv8b1ug==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.8",
+ "@aws-sdk/xml-builder": "^3.972.24",
+ "@aws/lambda-invoke-store": "^0.2.2",
+ "@smithy/core": "^3.24.2",
+ "@smithy/signature-v4": "^5.4.2",
+ "@smithy/types": "^4.14.1",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.972.37",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.37.tgz",
+ "integrity": "sha512-/jpPvEh6f7ntmIzf7dNxoNX6Q8vt8UpesCjbW6mFfk4V1NW6bIy9qxcQ6WbA8As5yQhsZOe+xeNd4xHX8kdY2Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.972.39",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.39.tgz",
+ "integrity": "sha512-pIgTpisWyWg7X1bUbzSjuUYosYTD0Ghz2M0hkSTmb3a6i3qV3uU+NYJPI/E2XSC0HcsZh5rsLPzeXrkb2DS0Cg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/fetch-http-handler": "^5.4.2",
+ "@smithy/node-http-handler": "^4.7.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.972.41",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.41.tgz",
+ "integrity": "sha512-u2tyjaxJJzW8UtW4SM1ZcPMDwO6y+kV+llvou+Adts0FAKyzes5jG4izQN+KX3yE8ZROpS5y1LJ//xL2iSf76w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/credential-provider-env": "^3.972.37",
+ "@aws-sdk/credential-provider-http": "^3.972.39",
+ "@aws-sdk/credential-provider-login": "^3.972.41",
+ "@aws-sdk/credential-provider-process": "^3.972.37",
+ "@aws-sdk/credential-provider-sso": "^3.972.41",
+ "@aws-sdk/credential-provider-web-identity": "^3.972.41",
+ "@aws-sdk/nested-clients": "^3.997.9",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/credential-provider-imds": "^4.3.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-login": {
+ "version": "3.972.41",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.41.tgz",
+ "integrity": "sha512-0LBitxXiAiaE5nlFPfpNIww/8FRY/I7WIndWsc9GmNFOM7cE1wNpVNQEGEk9Outg5l8xl+3vybxFyUy4l9q/LQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/nested-clients": "^3.997.9",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.972.42",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.42.tgz",
+ "integrity": "sha512-D4oon2zbqqsWOJUM99Gm3/ZyJ0IJvTXVN3PyloGb3kQEyI36fjCZheZj422lAgTWWd6TSHgiImLt3RIaLdv3dQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "^3.972.37",
+ "@aws-sdk/credential-provider-http": "^3.972.39",
+ "@aws-sdk/credential-provider-ini": "^3.972.41",
+ "@aws-sdk/credential-provider-process": "^3.972.37",
+ "@aws-sdk/credential-provider-sso": "^3.972.41",
+ "@aws-sdk/credential-provider-web-identity": "^3.972.41",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/credential-provider-imds": "^4.3.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.972.37",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.37.tgz",
+ "integrity": "sha512-7nVaHBUaWIddASYfVaA9O4D5ZVjewU3sCol9WqZPGfW0nR+0WqE0xHZnD/U2L33PlOB8KNXGKZ6wOES/QijKzg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.972.41",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.41.tgz",
+ "integrity": "sha512-IOWAWEHe5LkjSKkkUUX9ciV6Y1scHTsnfEkdt5yyC4Slrc7AGbkLPrpntjqh18ksJAMOaVhoBsO8p2WyTcY2wQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/nested-clients": "^3.997.9",
+ "@aws-sdk/token-providers": "3.1048.0",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.972.41",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.41.tgz",
+ "integrity": "sha512-mbACk9Yypa8nm4iGZLs0PofOXEcTDOUw6wDnsPXNDNSd2WNXs1tSo+6nc/fh0jLYdfVZThhBL98PHW4aXFsG5A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/nested-clients": "^3.997.9",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/eventstream-handler-node": {
+ "version": "3.972.16",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.16.tgz",
+ "integrity": "sha512-yedpPgKftqjU5SlPFHfqWpOw6xSCRieWRG1euWOlXn4WJxt2VX92VprCa2PpSOXjVCAeK6dTjW9eJRXVig9yGA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/middleware-eventstream": {
+ "version": "3.972.12",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.12.tgz",
+ "integrity": "sha512-tHTHHCHNrq6XklQvlzHBDJG4Iuhh7NVPRdtmvP+nHFA+5sxPlIDzlAHHgfoYHGvT3NXP1yVP/L5c3opUn6T3Qg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/middleware-websocket": {
+ "version": "3.972.19",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.19.tgz",
+ "integrity": "sha512-mkEhOGYozqKQkbFaVrjwr0faiwwZza1v5/jSY6Tucm3bD+uKTazIUH/4Yo6aMnQD2ua2W9cMP6s8mvwTcjtqHw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/fetch-http-handler": "^5.4.2",
+ "@smithy/signature-v4": "^5.4.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/nested-clients": {
+ "version": "3.997.9",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.9.tgz",
+ "integrity": "sha512-jPR3rnmRI4hWYyzfmTGBr7NblMp8QYYeflHXba1H6+7CGrWVqWKQzaXFQ4qbExqPRsXN3T3L3JxFhr6aouXUGQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/signature-v4-multi-region": "^3.996.27",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/fetch-http-handler": "^5.4.2",
+ "@smithy/node-http-handler": "^4.7.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.996.27",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.27.tgz",
+ "integrity": "sha512-0Phbz4t6HI3D3skxvG2uI+VWU034/nSIw1T8d+FPzzQG9EQTrw94o9mOKO2Gv3n3Oc8P7JD7RAUxkoneLWv5Eg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/signature-v4": "^5.4.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/token-providers": {
+ "version": "3.1048.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1048.0.tgz",
+ "integrity": "sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.974.11",
+ "@aws-sdk/nested-clients": "^3.997.9",
+ "@aws-sdk/types": "^3.973.8",
+ "@smithy/core": "^3.24.2",
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/types": {
+ "version": "3.973.8",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.8.tgz",
+ "integrity": "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/util-locate-window": {
+ "version": "3.965.5",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz",
+ "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/xml-builder": {
+ "version": "3.972.24",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.24.tgz",
+ "integrity": "sha512-V8z5YcDPfsvzrBlj0xR1vhRtocblhYbqdreCJB/voGd4Sr5zjNAeWxexbnqVtskTJe0vFb5KMqbSL++ePl+zRw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@nodable/entities": "2.1.0",
+ "@smithy/types": "^4.14.1",
+ "fast-xml-parser": "5.7.3",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws/lambda-invoke-store": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz",
+ "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@babel/runtime": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-agent-core": {
+ "version": "0.79.3",
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.79.3.tgz",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@earendil-works/pi-ai": "^0.79.3",
+ "ignore": "7.0.5",
+ "typebox": "1.1.38",
+ "yaml": "2.9.0"
+ },
+ "engines": {
+ "node": ">=22.19.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-ai": {
+ "version": "0.79.3",
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.79.3.tgz",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@anthropic-ai/sdk": "0.91.1",
+ "@aws-sdk/client-bedrock-runtime": "3.1048.0",
+ "@google/genai": "1.52.0",
+ "@mistralai/mistralai": "2.2.1",
+ "@smithy/node-http-handler": "4.7.3",
+ "http-proxy-agent": "7.0.2",
+ "https-proxy-agent": "7.0.6",
+ "openai": "6.26.0",
+ "partial-json": "0.1.7",
+ "typebox": "1.1.38"
+ },
+ "bin": {
+ "pi-ai": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=22.19.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-tui": {
+ "version": "0.79.3",
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.79.3.tgz",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "1.6.0",
+ "marked": "15.0.12"
+ },
+ "engines": {
+ "node": ">=22.19.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@google/genai": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz",
+ "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "google-auth-library": "^10.3.0",
+ "p-retry": "^4.6.2",
+ "protobufjs": "^7.5.4",
+ "ws": "^8.18.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "@modelcontextprotocol/sdk": "^1.25.2"
+ },
+ "peerDependenciesMeta": {
+ "@modelcontextprotocol/sdk": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard/-/clipboard-0.3.9.tgz",
+ "integrity": "sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@mariozechner/clipboard-darwin-arm64": "0.3.9",
+ "@mariozechner/clipboard-darwin-universal": "0.3.9",
+ "@mariozechner/clipboard-darwin-x64": "0.3.9",
+ "@mariozechner/clipboard-linux-arm64-gnu": "0.3.9",
+ "@mariozechner/clipboard-linux-arm64-musl": "0.3.9",
+ "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.9",
+ "@mariozechner/clipboard-linux-x64-gnu": "0.3.9",
+ "@mariozechner/clipboard-linux-x64-musl": "0.3.9",
+ "@mariozechner/clipboard-win32-arm64-msvc": "0.3.9",
+ "@mariozechner/clipboard-win32-x64-msvc": "0.3.9"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-darwin-arm64": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-arm64/-/clipboard-darwin-arm64-0.3.9.tgz",
+ "integrity": "sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-darwin-universal": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-universal/-/clipboard-darwin-universal-0.3.9.tgz",
+ "integrity": "sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-darwin-x64": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-x64/-/clipboard-darwin-x64-0.3.9.tgz",
+ "integrity": "sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-arm64-gnu": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-gnu/-/clipboard-linux-arm64-gnu-0.3.9.tgz",
+ "integrity": "sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-arm64-musl": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-musl/-/clipboard-linux-arm64-musl-0.3.9.tgz",
+ "integrity": "sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-riscv64-gnu": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-riscv64-gnu/-/clipboard-linux-riscv64-gnu-0.3.9.tgz",
+ "integrity": "sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-x64-gnu": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-gnu/-/clipboard-linux-x64-gnu-0.3.9.tgz",
+ "integrity": "sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-x64-musl": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-musl/-/clipboard-linux-x64-musl-0.3.9.tgz",
+ "integrity": "sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-win32-arm64-msvc": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-arm64-msvc/-/clipboard-win32-arm64-msvc-0.3.9.tgz",
+ "integrity": "sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-win32-x64-msvc": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-x64-msvc/-/clipboard-win32-x64-msvc-0.3.9.tgz",
+ "integrity": "sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@mistralai/mistralai": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-2.2.1.tgz",
+ "integrity": "sha512-uKU8CZmL2RzYKmplsU01hii4p3pe4HqJefpWNRWXm1Tcm0Sm4xXfwSLIy4k7ZCPlbETCGcp69E7hZs+WOJ5itQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "ws": "^8.18.0",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-to-json-schema": "^3.25.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@nodable/entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodable"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/codegen": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
+ "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/fetch": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
+ "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/inquire": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz",
+ "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/utf8": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
+ "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@silvia-odwyer/photon-node": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@silvia-odwyer/photon-node/-/photon-node-0.3.4.tgz",
+ "integrity": "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/core": {
+ "version": "3.24.3",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.3.tgz",
+ "integrity": "sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/credential-provider-imds": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.3.tgz",
+ "integrity": "sha512-I2Bti0DKFo2IJyN28ijCsx51BAumEYR4/1yZ1FXyBygy9MqbnMqCev4JPth/MbpRfBSRAX35hITSnAdJRo1u5w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/fetch-http-handler": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.3.tgz",
+ "integrity": "sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/node-http-handler": {
+ "version": "4.7.3",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.3.tgz",
+ "integrity": "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/signature-v4": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.4.3.tgz",
+ "integrity": "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.24.3",
+ "@smithy/types": "^4.14.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/types": {
+ "version": "4.14.2",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.2.tgz",
+ "integrity": "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/@types/node": {
+ "version": "22.19.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz",
+ "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/bignumber.js": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/bowser": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz",
+ "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/brace-expansion": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
+ "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/diff": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz",
+ "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/fast-xml-builder": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
+ "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "path-expression-matcher": "^1.5.0",
+ "xml-naming": "^0.1.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/fast-xml-parser": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz",
+ "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@nodable/entities": "^2.1.0",
+ "fast-xml-builder": "^1.1.7",
+ "path-expression-matcher": "^1.5.0",
+ "strnum": "^2.2.3"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/gaxios": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
+ "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "node-fetch": "^3.3.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/gcp-metadata": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
+ "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^7.0.0",
+ "google-logging-utils": "^1.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/get-east-asian-width": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
+ "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/glob": {
+ "version": "13.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
+ "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "minimatch": "^10.2.2",
+ "minipass": "^7.1.3",
+ "path-scurry": "^2.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/google-auth-library": {
+ "version": "10.6.2",
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
+ "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "gaxios": "^7.1.4",
+ "gcp-metadata": "8.1.2",
+ "google-logging-utils": "1.1.3",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/google-logging-utils": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
+ "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/highlight.js": {
+ "version": "10.7.3",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
+ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/hosted-git-info": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz",
+ "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^11.1.0"
+ },
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/jiti": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/json-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/json-schema-to-ts": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz",
+ "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "ts-algebra": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/jwa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/jws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/lru-cache": {
+ "version": "11.4.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.4.0.tgz",
+ "integrity": "sha512-W+R+kFL4HgVxONq2bhXPi3bGpzGe/yEhVOp233qw9wCRtgncJ15P3bC+e4zZMu4Cq7d+WAJjXGW0uUkifhcatA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/marked": {
+ "version": "15.0.12",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz",
+ "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/minipass": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+ "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/openai": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/openai/-/openai-6.26.0.tgz",
+ "integrity": "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "openai": "bin/cli"
+ },
+ "peerDependencies": {
+ "ws": "^8.18.0",
+ "zod": "^3.25 || ^4.0"
+ },
+ "peerDependenciesMeta": {
+ "ws": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/p-retry": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/p-retry/node_modules/@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/partial-json": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/partial-json/-/partial-json-0.1.7.tgz",
+ "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/path-expression-matcher": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz",
+ "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/path-scurry": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
+ "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/proper-lockfile": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
+ "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "retry": "^0.12.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/proper-lockfile/node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/protobufjs": {
+ "version": "7.5.9",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.9.tgz",
+ "integrity": "sha512-Od4muIm3HW1AouyHF5lONOf1FWo3hY1NbFDoy191X9GzhpgW1clCoaFjfVs2rKJNFYpTNJbje4cbAIDBZJ63ZA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/strnum": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz",
+ "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/ts-algebra": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz",
+ "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "dev": true,
+ "license": "0BSD"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/typebox": {
+ "version": "1.1.38",
+ "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.1.38.tgz",
+ "integrity": "sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/undici": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.3.0.tgz",
+ "integrity": "sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=22.19.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/ws": {
+ "version": "8.20.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
+ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/xml-naming": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz",
+ "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/yaml": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/@earendil-works/pi-coding-agent/node_modules/zod-to-json-schema": {
+ "version": "3.25.2",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz",
+ "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==",
+ "dev": true,
+ "license": "ISC",
+ "peerDependencies": {
+ "zod": "^3.25.28 || ^4"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.1",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
+ "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz",
+ "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tybys/wasm-util": "^0.10.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ },
+ "peerDependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1"
+ }
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.133.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz",
+ "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
+ "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz",
+ "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz",
+ "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz",
+ "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz",
+ "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz",
+ "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz",
+ "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz",
+ "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz",
+ "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz",
+ "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz",
+ "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz",
+ "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz",
+ "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "1.10.0",
+ "@emnapi/runtime": "1.10.0",
+ "@napi-rs/wasm-runtime": "^1.1.4"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz",
+ "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz",
+ "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
+ "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "25.9.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz",
+ "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": ">=7.24.0 <7.24.7"
+ }
+ },
+ "node_modules/@vitest/expect": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz",
+ "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.1.0",
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "chai": "^6.2.2",
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz",
+ "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "4.1.8",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.21"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz",
+ "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz",
+ "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "4.1.8",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz",
+ "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "magic-string": "^0.30.21",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz",
+ "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz",
+ "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.1.8",
+ "convert-source-map": "^2.0.0",
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/chai": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
+ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
+ "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/expect-type": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
+ "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
+ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.32.0",
+ "lightningcss-darwin-arm64": "1.32.0",
+ "lightningcss-darwin-x64": "1.32.0",
+ "lightningcss-freebsd-x64": "1.32.0",
+ "lightningcss-linux-arm-gnueabihf": "1.32.0",
+ "lightningcss-linux-arm64-gnu": "1.32.0",
+ "lightningcss-linux-arm64-musl": "1.32.0",
+ "lightningcss-linux-x64-gnu": "1.32.0",
+ "lightningcss-linux-x64-musl": "1.32.0",
+ "lightningcss-win32-arm64-msvc": "1.32.0",
+ "lightningcss-win32-x64-msvc": "1.32.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
+ "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
+ "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
+ "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
+ "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
+ "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
+ "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
+ "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
+ "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
+ "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
+ "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
+ "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/obug": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz",
+ "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==",
+ "dev": true,
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.15",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+ "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.12",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/rolldown": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz",
+ "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.133.0",
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.0.3",
+ "@rolldown/binding-darwin-arm64": "1.0.3",
+ "@rolldown/binding-darwin-x64": "1.0.3",
+ "@rolldown/binding-freebsd-x64": "1.0.3",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.3",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.3",
+ "@rolldown/binding-linux-arm64-musl": "1.0.3",
+ "@rolldown/binding-linux-ppc64-gnu": "1.0.3",
+ "@rolldown/binding-linux-s390x-gnu": "1.0.3",
+ "@rolldown/binding-linux-x64-gnu": "1.0.3",
+ "@rolldown/binding-linux-x64-musl": "1.0.3",
+ "@rolldown/binding-openharmony-arm64": "1.0.3",
+ "@rolldown/binding-wasm32-wasi": "1.0.3",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.3",
+ "@rolldown/binding-win32-x64-msvc": "1.0.3"
+ }
+ },
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/std-env": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz",
+ "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinybench": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz",
+ "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
+ "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "dev": true,
+ "license": "0BSD",
+ "optional": true
+ },
+ "node_modules/typescript": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
+ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
+ "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vite": {
+ "version": "8.0.16",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz",
+ "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lightningcss": "^1.32.0",
+ "picomatch": "^4.0.4",
+ "postcss": "^8.5.15",
+ "rolldown": "1.0.3",
+ "tinyglobby": "^0.2.17"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.1.18",
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitest": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz",
+ "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/expect": "4.1.8",
+ "@vitest/mocker": "4.1.8",
+ "@vitest/pretty-format": "4.1.8",
+ "@vitest/runner": "4.1.8",
+ "@vitest/snapshot": "4.1.8",
+ "@vitest/spy": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "es-module-lexer": "^2.0.0",
+ "expect-type": "^1.3.0",
+ "magic-string": "^0.30.21",
+ "obug": "^2.1.1",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.3",
+ "std-env": "^4.0.0-rc.1",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tinyrainbow": "^3.1.0",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@opentelemetry/api": "^1.9.0",
+ "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "4.1.8",
+ "@vitest/browser-preview": "4.1.8",
+ "@vitest/browser-webdriverio": "4.1.8",
+ "@vitest/coverage-istanbul": "4.1.8",
+ "@vitest/coverage-v8": "4.1.8",
+ "@vitest/ui": "4.1.8",
+ "happy-dom": "*",
+ "jsdom": "*",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-preview": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ },
+ "vite": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ }
+ }
+}
diff --git a/axiom-pi/package.json b/axiom-pi/package.json
new file mode 100644
index 00000000..208238ba
--- /dev/null
+++ b/axiom-pi/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "axiom-pi",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "description": "Axiom extension for the Pi coding agent — /axiom-* commands and session/tool hooks for Apple-platform development",
+ "pi": {
+ "extensions": [
+ "./src/index.ts"
+ ]
+ },
+ "files": [
+ "src",
+ "README.md",
+ "LICENSE"
+ ],
+ "scripts": {
+ "typecheck": "tsc --noEmit",
+ "test": "vitest run",
+ "test:watch": "vitest"
+ },
+ "keywords": [
+ "pi",
+ "pi-agent",
+ "ios",
+ "swift",
+ "swiftui",
+ "xcode",
+ "axiom"
+ ],
+ "author": "Charles Wiltgen",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/CharlesWiltgen/Axiom.git",
+ "directory": "axiom-pi"
+ },
+ "homepage": "https://charleswiltgen.github.io/Axiom/start/pi-install",
+ "bugs": {
+ "url": "https://github.com/CharlesWiltgen/Axiom/issues"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "devDependencies": {
+ "@earendil-works/pi-coding-agent": "^0.79.3",
+ "@types/node": "^25.9.3",
+ "typescript": "^6.0.3",
+ "vitest": "^4.1.8"
+ }
+}
diff --git a/axiom-pi/src/commands.test.ts b/axiom-pi/src/commands.test.ts
new file mode 100644
index 00000000..d81e0404
--- /dev/null
+++ b/axiom-pi/src/commands.test.ts
@@ -0,0 +1,47 @@
+import { describe, it, expect } from "vitest";
+import { AXIOM_COMMANDS, AUDIT_AREAS } from "./commands.ts";
+
+describe("AXIOM_COMMANDS", () => {
+ it("registers exactly the 15 Axiom commands, in order", () => {
+ expect(AXIOM_COMMANDS.map((c) => c.name)).toEqual([
+ "axiom-fix-build", "axiom-audit", "axiom-health-check", "axiom-analyze-crash",
+ "axiom-triage", "axiom-console", "axiom-ui", "axiom-profile",
+ "axiom-compare-traces", "axiom-optimize-build", "axiom-run-tests",
+ "axiom-test-simulator", "axiom-screenshot", "axiom-status", "axiom-ask",
+ ]);
+ });
+
+ it("gives every command a non-empty prompt for both empty and non-empty args", () => {
+ for (const cmd of AXIOM_COMMANDS) {
+ expect(cmd.prompt("").length).toBeGreaterThan(0);
+ expect(cmd.prompt("Foo.swift").length).toBeGreaterThan(0);
+ }
+ });
+});
+
+describe("axiom-audit prompt", () => {
+ const audit = AXIOM_COMMANDS.find((c) => c.name === "axiom-audit")!;
+
+ it("names the area when one is given", () => {
+ expect(audit.prompt("memory")).toContain("memory");
+ });
+
+ it("routes 'all' to a full health check", () => {
+ expect(audit.prompt("all")).toContain("health check");
+ });
+
+ it("suggests audits when no area is given", () => {
+ expect(audit.prompt("")).toContain("which Axiom audits");
+ });
+
+ it("offers the audit areas as completions", () => {
+ expect(audit.completions).toBe(AUDIT_AREAS);
+ });
+});
+
+describe("axiom-analyze-crash prompt", () => {
+ it("includes the crash file path argument", () => {
+ const cmd = AXIOM_COMMANDS.find((c) => c.name === "axiom-analyze-crash")!;
+ expect(cmd.prompt("/tmp/foo.ips")).toContain("/tmp/foo.ips");
+ });
+});
diff --git a/axiom-pi/src/commands.ts b/axiom-pi/src/commands.ts
new file mode 100644
index 00000000..6a0402e2
--- /dev/null
+++ b/axiom-pi/src/commands.ts
@@ -0,0 +1,171 @@
+/**
+ * Axiom commands, ported to Pi.
+ *
+ * Each Axiom `/axiom:*` command launches an agent in Claude Code. Pi has no
+ * sub-agent system, so each command instead registers as `/axiom-` and
+ * sends a natural-language prompt that triggers the matching skill inline.
+ *
+ * Pure data + prompt builders — no Pi imports, so the table is unit-testable.
+ */
+
+export type AxiomCommand = {
+ /** Registered as `/` in Pi. */
+ name: string;
+ description: string;
+ /** Argument completions offered after the command (e.g. audit areas). */
+ completions?: readonly string[];
+ /** Builds the user message that triggers the matching skill workflow. */
+ prompt: (args: string) => string;
+};
+
+/** Audit areas accepted by `/axiom-audit` (mirrors the Claude command argument). */
+export const AUDIT_AREAS = [
+ "all", "memory", "concurrency", "accessibility", "energy",
+ "swiftui-performance", "swiftui-architecture", "swiftui-nav", "swiftui-layout",
+ "swift-performance", "core-data", "swiftdata", "database-schema", "networking",
+ "codable", "icloud", "storage", "liquid-glass", "textkit", "testing", "build",
+ "spritekit", "security", "modernization", "camera", "foundation-models",
+ "screenshots", "ux-flow",
+] as const;
+
+export const AXIOM_COMMANDS: readonly AxiomCommand[] = [
+ {
+ name: "axiom-fix-build",
+ description: "Diagnose and fix an Xcode build failure (environment-first)",
+ prompt: () =>
+ "My Xcode build is failing. Use the axiom-build skill to diagnose it " +
+ "environment-first — check for zombie xcodebuild processes " +
+ "(`pgrep -x xcodebuild`), Derived Data, the SPM cache, and simulator " +
+ "state before touching code — then apply the fix and verify it builds.",
+ },
+ {
+ name: "axiom-audit",
+ description: "Run an Axiom code audit (memory, concurrency, security, …) or suggest relevant ones",
+ completions: AUDIT_AREAS,
+ prompt: (args) => {
+ const area = args.trim();
+ if (!area) {
+ return "Analyze this project's structure and tell me which Axiom audits " +
+ "are most relevant (memory, concurrency, data safety, performance, " +
+ "security, accessibility, UX), then run the ones I confirm.";
+ }
+ if (area === "all") {
+ return "Run a full Axiom health check across all relevant domains and " +
+ "give a unified, prioritized report.";
+ }
+ return `Run an Axiom ${area} audit on this codebase using the matching ` +
+ "skill. Report findings by severity (CRITICAL/HIGH/MEDIUM/LOW) with " +
+ "file:line and concrete fixes.";
+ },
+ },
+ {
+ name: "axiom-health-check",
+ description: "Full project health check across all Axiom audit domains",
+ prompt: () =>
+ "Run a full Axiom health check on this project — audit across memory, " +
+ "concurrency, data safety, performance, networking, security, and " +
+ "accessibility, then give one prioritized, de-duplicated report.",
+ },
+ {
+ name: "axiom-analyze-crash",
+ description: "Symbolicate and triage a crash report (.ips, MetricKit, .crash, .xccrashpoint)",
+ prompt: (args) => {
+ const f = args.trim();
+ const target = f ? `: ${f}` : " (point me at the file if I haven't given a path)";
+ return `Analyze this crash report${target}. Run ` +
+ "`xcsym crash --format=summary` to symbolicate and categorize it, then " +
+ "explain the crash pattern and the fix. See the axiom-tools crash workflow.";
+ },
+ },
+ {
+ name: "axiom-triage",
+ description: "Triage a corpus of production crashes from Sentry / App Store Connect",
+ prompt: (args) =>
+ `Triage my production crashes${args.trim() ? ` from ${args.trim()}` : ""} — ` +
+ "fetch the unresolved issues, run `xcsym triage` to classify and cluster " +
+ "them, flag suspension/idle-runloop noise, and rank the root-cause families " +
+ "to fix first.",
+ },
+ {
+ name: "axiom-console",
+ description: "Capture simulator console output with xclog",
+ prompt: (args) =>
+ `Capture the simulator console with \`xclog\`${args.trim() ? ` for ${args.trim()}` : ""} — ` +
+ "use `xclog list` to find the bundle id, then " +
+ "`xclog launch --timeout 30s --max-lines 200` for a bounded " +
+ "capture, and summarize errors. See axiom-tools (xclog-ref).",
+ },
+ {
+ name: "axiom-ui",
+ description: "Drive and validate the simulator UI & accessibility with xcui",
+ prompt: (args) =>
+ `Drive and validate the simulator UI with \`xcui\`${args.trim() ? `: ${args.trim()}` : ""}. ` +
+ "Run `xcui doctor` first, then tap by accessibility id, dump the " +
+ "accessibility tree, and assert on labels/traits/VoiceOver/Dynamic Type. " +
+ "See axiom-tools (xcui-ref).",
+ },
+ {
+ name: "axiom-profile",
+ description: "Record and analyze a CPU/performance trace with xcprof (no Instruments GUI)",
+ prompt: (args) =>
+ `Profile my app's performance with \`xcprof\`${args.trim() ? ` (${args.trim()})` : ""} — ` +
+ "`xcprof record --preset cpu --attach ` then " +
+ "`xcprof analyze --json`, and give an honest hot-frame report. " +
+ "See axiom-tools (xcprof-ref).",
+ },
+ {
+ name: "axiom-compare-traces",
+ description: "Diff two performance traces for CPU regressions (xcprof compare)",
+ prompt: (args) =>
+ "Compare two performance traces for CPU-share regressions with " +
+ `\`xcprof compare \`${args.trim() ? `: ${args.trim()}` : ""} ` +
+ "and report what regressed. See the axiom-performance trace-comparison workflow.",
+ },
+ {
+ name: "axiom-optimize-build",
+ description: "Find and apply Xcode build-time optimizations",
+ prompt: () =>
+ "Analyze my Xcode build performance and suggest optimizations — slow " +
+ "type-checking expressions, expensive build-phase scripts, suboptimal " +
+ "build settings, and parallelization opportunities. Use the axiom-build skill.",
+ },
+ {
+ name: "axiom-run-tests",
+ description: "Run XCUITests and parse the results",
+ prompt: (args) =>
+ `Run my tests${args.trim() ? ` (${args.trim()})` : ""} with xcodebuild, parse ` +
+ "the .xcresult, and show failures with details and attachments. Use the " +
+ "axiom-testing skill.",
+ },
+ {
+ name: "axiom-test-simulator",
+ description: "Run a simulator test scenario with visual + accessibility verification",
+ prompt: (args) =>
+ `Set up and run a simulator test scenario${args.trim() ? `: ${args.trim()}` : ""} — ` +
+ "drive the UI with `xcui`, capture screenshots for visual verification, " +
+ "assert on the accessibility tree, and check logs for crashes/errors.",
+ },
+ {
+ name: "axiom-screenshot",
+ description: "Capture a simulator screenshot for verification",
+ prompt: (args) =>
+ `Capture a simulator screenshot${args.trim() ? ` of ${args.trim()}` : " of the current screen"} ` +
+ "and verify the UI state (no placeholder text, correct layout, no debug overlays).",
+ },
+ {
+ name: "axiom-status",
+ description: "Axiom project health dashboard (environment + suggestions)",
+ prompt: () =>
+ "Show the Axiom project health dashboard — read the environment " +
+ "(IPHONEOS_DEPLOYMENT_TARGET, Xcode version, simulator state, available " +
+ "Axiom tools) and suggest concrete improvements.",
+ },
+ {
+ name: "axiom-ask",
+ description: "Ask an iOS/Swift question routed to the right Axiom skill",
+ prompt: (args) =>
+ args.trim()
+ ? `Answer this iOS/Swift question, loading the most relevant Axiom skill first: ${args.trim()}`
+ : "What iOS/Swift question can I help with? I'll route it to the most relevant Axiom skill.",
+ },
+];
diff --git a/axiom-pi/src/guardrails.test.ts b/axiom-pi/src/guardrails.test.ts
new file mode 100644
index 00000000..aa2c294f
--- /dev/null
+++ b/axiom-pi/src/guardrails.test.ts
@@ -0,0 +1,116 @@
+import { describe, it, expect } from "vitest";
+import {
+ unscopedStateVars,
+ classifyCrashPath,
+ crashFileHint,
+ bashOutputHints,
+ inputPath,
+ swiftGuardrailWarning,
+ toolResultHint,
+} from "./guardrails.ts";
+
+describe("unscopedStateVars", () => {
+ it("flags @State var without an access level, with 1-based line numbers", () => {
+ const swift = [
+ "struct V: View {",
+ " @State var count = 0",
+ ' @State private var name = ""',
+ " @State var flagged = true // axiom-ignore",
+ "}",
+ ].join("\n");
+ expect(unscopedStateVars(swift)).toEqual([{ line: 2, text: "@State var count = 0" }]);
+ });
+
+ it("returns nothing when every @State is scoped", () => {
+ expect(unscopedStateVars("@State private var a = 1\n@State public var b = 2")).toEqual([]);
+ });
+});
+
+describe("classifyCrashPath", () => {
+ it("classifies each crash-path shape", () => {
+ expect([
+ classifyCrashPath("/x/a.ips"),
+ classifyCrashPath("/x/a.crash"),
+ classifyCrashPath("/x/Foo.xccrashpoint"),
+ classifyCrashPath("/x/Foo.xccrashpoint/Logs/a.crash"),
+ classifyCrashPath("/x/Foo.xccrashpoint/Info.plist"),
+ classifyCrashPath("/x/main.swift"),
+ ]).toEqual([
+ "ips", "crash_text", "xccrashpoint_bundle_root",
+ "xccrashpoint_inner_crash", "xccrashpoint_inner_other", "",
+ ]);
+ });
+});
+
+describe("crashFileHint", () => {
+ it("names xcsym and echoes the path for a crash file", () => {
+ const hint = crashFileHint("/tmp/foo.ips");
+ expect(hint).toContain("xcsym crash");
+ expect(hint).toContain("/tmp/foo.ips");
+ });
+
+ it("is null for a non-crash path", () => {
+ expect(crashFileHint("/tmp/main.swift")).toBeNull();
+ });
+});
+
+describe("bashOutputHints", () => {
+ it("returns the matching skill hints, in rule order", () => {
+ expect(bashOutputHints("error: Sendable closure; linker command failed")).toEqual([
+ "💡 Concurrency issue — load the axiom-concurrency skill.",
+ "💡 Build configuration issue — try /axiom-fix-build.",
+ ]);
+ });
+
+ it("is empty for empty output", () => {
+ expect(bashOutputHints("")).toEqual([]);
+ });
+});
+
+describe("inputPath", () => {
+ it("reads either path or filePath, else undefined", () => {
+ expect(inputPath({ path: "/a" })).toBe("/a");
+ expect(inputPath({ filePath: "/b" })).toBe("/b");
+ expect(inputPath({})).toBeUndefined();
+ expect(inputPath(null)).toBeUndefined();
+ });
+});
+
+describe("swiftGuardrailWarning", () => {
+ it("warns about unscoped @State with line numbers", () => {
+ const w = swiftGuardrailWarning("struct V {\n @State var x = 0\n}");
+ expect(w).toContain("@State private var");
+ expect(w).toContain("L2");
+ });
+
+ it("is null when every @State is scoped", () => {
+ expect(swiftGuardrailWarning("@State private var x = 0")).toBeNull();
+ });
+});
+
+describe("toolResultHint", () => {
+ const readSwift = () => "struct V {\n @State var x = 0\n}";
+
+ it("returns the Swift guardrail warning for a .swift write", () => {
+ const hint = toolResultHint({ toolName: "write", input: { path: "/a/V.swift" }, content: [] }, readSwift);
+ expect(hint).toContain("@State private var");
+ });
+
+ it("ignores non-Swift writes", () => {
+ expect(toolResultHint({ toolName: "edit", input: { path: "/a/x.txt" }, content: [] }, readSwift)).toBeNull();
+ });
+
+ it("returns bash skill hints from output text", () => {
+ const hint = toolResultHint(
+ { toolName: "bash", input: {}, content: [{ type: "text", text: "data race here" }] },
+ readSwift,
+ );
+ expect(hint).toBe("💡 Concurrency issue — load the axiom-concurrency skill.");
+ });
+
+ it("returns null when nothing matches", () => {
+ expect(
+ toolResultHint({ toolName: "bash", input: {}, content: [{ type: "text", text: "all good" }] }, readSwift),
+ ).toBeNull();
+ });
+});
diff --git a/axiom-pi/src/guardrails.ts b/axiom-pi/src/guardrails.ts
new file mode 100644
index 00000000..4e1679bd
--- /dev/null
+++ b/axiom-pi/src/guardrails.ts
@@ -0,0 +1,148 @@
+/**
+ * Tool-hook logic ported from Axiom's Claude Code hooks. Pure functions so
+ * they're unit-testable; the Pi wiring in index.ts feeds them tool I/O.
+ *
+ * - unscopedStateVars ← swift-guardrails.sh (@State without access control)
+ * - crashFileHint ← pretool-crash-route.py (route crash Reads to xcsym)
+ * - bashOutputHints ← posttool-bash-hints.py (suggest a skill from output)
+ */
+
+/**
+ * `@State var` declarations missing an explicit access level. Without one,
+ * child views can create independent copies of the state — a silent-bug class.
+ * Honors a `// axiom-ignore` trailing comment, matching the Claude hook.
+ */
+export function unscopedStateVars(swift: string): { line: number; text: string }[] {
+ const SCOPED = /@State\s+(private|internal|fileprivate|public|package)\s+var\b/;
+ const hits: { line: number; text: string }[] = [];
+ const lines = swift.split("\n");
+ for (let i = 0; i < lines.length; i++) {
+ const text = lines[i];
+ if (!/@State\s+var\b/.test(text)) continue;
+ if (SCOPED.test(text)) continue;
+ if (/\/\/\s*axiom-ignore/.test(text)) continue;
+ hits.push({ line: i + 1, text: text.trim() });
+ }
+ return hits;
+}
+
+type CrashKind =
+ | "ips"
+ | "crash_text"
+ | "xccrashpoint_bundle_root"
+ | "xccrashpoint_inner_crash"
+ | "xccrashpoint_inner_other"
+ | "";
+
+/** Categorize a path so the caller can pick the right crash hint. */
+export function classifyCrashPath(p: string): CrashKind {
+ if (!p) return "";
+ if (p.endsWith(".xccrashpoint") || p.endsWith(".xccrashpoint/")) return "xccrashpoint_bundle_root";
+ if (p.includes(".xccrashpoint/")) {
+ return p.endsWith(".crash") ? "xccrashpoint_inner_crash" : "xccrashpoint_inner_other";
+ }
+ if (p.endsWith(".ips")) return "ips";
+ if (p.endsWith(".crash")) return "crash_text";
+ return "";
+}
+
+const CRASH_HINTS: Record, (p: string) => string> = {
+ ips: (p) =>
+ `This is an .ips crash report. Before reading it as text, run ` +
+ `\`xcsym crash --format=summary "${p}"\` — it symbolicates against local ` +
+ `dSYMs and tags the crash pattern. Analyze the JSON output, not the raw .ips. ` +
+ `See the axiom-tools skill (xcsym-ref).`,
+ crash_text: (p) =>
+ `This is an Apple legacy .crash text file. Run ` +
+ `\`xcsym crash --format=summary "${p}"\` first — xcsym parses the legacy ` +
+ `format, symbolicates via dSYM discovery, and surfaces pattern_tag + crashed frames.`,
+ xccrashpoint_inner_crash: (p) =>
+ `This is a .crash inside an .xccrashpoint bundle. Pass it directly to ` +
+ `\`xcsym crash --format=summary "${p}"\`. Prefer a \`LocallySymbolicated/\` ` +
+ `sibling with the same timestamp if present.`,
+ xccrashpoint_bundle_root: (p) =>
+ `This is an .xccrashpoint bundle (a directory). xcsym needs a .crash file ` +
+ `inside it — they live at \`${p}/Filters/*/Logs/*.crash\`. List the directory, ` +
+ `then pass the right one to \`xcsym crash\`.`,
+ xccrashpoint_inner_other: () =>
+ `This file is inside an .xccrashpoint bundle but isn't the crash payload. ` +
+ `For crash analysis, route \`Filters/*/Logs/*.crash\` under the bundle root to ` +
+ `\`xcsym crash --format=summary\`.`,
+};
+
+/** Advisory hint when a crash file is read, or null when the path isn't a crash. */
+export function crashFileHint(p: string): string | null {
+ const kind = classifyCrashPath(p);
+ return kind ? CRASH_HINTS[kind](p) : null;
+}
+
+// Output-signature rules from posttool-bash-hints.py. The Python hook's
+// duration-aware rules (slow-build / slow-test) are intentionally omitted: Pi's
+// tool_result event carries no command duration to gate them on.
+const BASH_PATTERN_RULES: { pattern: RegExp; hint: string }[] = [
+ { pattern: /Unable to simultaneously satisfy constraints/, hint: "💡 Auto Layout conflict — load the axiom-uikit skill." },
+ { pattern: /Actor-isolated|Sendable|data race|@MainActor/, hint: "💡 Concurrency issue — load the axiom-concurrency skill." },
+ { pattern: /no such column|FOREIGN KEY constraint|migration/, hint: "💡 Database migration issue — load the axiom-data skill." },
+ { pattern: /retain cycle|memory leak|deinit.*never called/, hint: "💡 Memory issue — load the axiom-performance skill." },
+ { pattern: /CKError|CKRecord.*error/, hint: "💡 CloudKit issue — load the axiom-data skill." },
+ { pattern: /ubiquitous.*error|iCloud Drive|NSFileCoordinator/, hint: "💡 iCloud Drive issue — load the axiom-data skill." },
+ { pattern: /file.*disappeared|file not found|storage.*full/, hint: "💡 File storage issue — load the axiom-data skill." },
+ { pattern: /FileProtection|data protection|file.*locked/, hint: "💡 File protection issue — load the axiom-data skill." },
+ { pattern: /error:.*module.*not found|linker command failed/, hint: "💡 Build configuration issue — try /axiom-fix-build." },
+];
+
+/** Every skill hint whose pattern matches the Bash output, in rule order. */
+export function bashOutputHints(output: string): string[] {
+ if (!output) return [];
+ return BASH_PATTERN_RULES.filter((r) => r.pattern.test(output)).map((r) => r.hint);
+}
+
+/** A file path off a tool event's input, tolerating either `path` or `filePath`. */
+export function inputPath(input: unknown): string | undefined {
+ if (typeof input !== "object" || input === null) return undefined;
+ const rec = input as Record;
+ const p = rec.path ?? rec.filePath;
+ return typeof p === "string" ? p : undefined;
+}
+
+/** Formatted `@State` access-control warning for Swift source, or null. */
+export function swiftGuardrailWarning(swiftSource: string): string | null {
+ const hits = unscopedStateVars(swiftSource).slice(0, 3);
+ if (hits.length === 0) return null;
+ const detail = hits.map((h) => ` L${h.line}: ${h.text}`).join("\n");
+ return (
+ "⚠️ Axiom guardrail: `@State` without an explicit access level " +
+ "(use `@State private var` — child views can otherwise create independent " +
+ `state copies):\n${detail}`
+ );
+}
+
+/** Minimal structural shape of a Pi `tool_result` event (keeps this module Pi-free). */
+export type ToolResultLike = {
+ toolName: string;
+ input: unknown;
+ content: ReadonlyArray<{ type: string; text?: string }>;
+};
+
+/**
+ * Advisory text to append to a `write`/`edit`/`bash` tool result, or null.
+ * `readFile` is injected so this is unit-testable without touching disk.
+ * Crash-file routing is handled pre-read on `tool_call`, not here.
+ */
+export function toolResultHint(event: ToolResultLike, readFile: (p: string) => string): string | null {
+ if (event.toolName === "write" || event.toolName === "edit") {
+ const p = inputPath(event.input);
+ if (!p || !p.endsWith(".swift")) return null;
+ try {
+ return swiftGuardrailWarning(readFile(p));
+ } catch {
+ return null; // file unreadable (e.g. deleted) — nothing to check
+ }
+ }
+ if (event.toolName === "bash") {
+ const text = event.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join("\n");
+ const hints = bashOutputHints(text);
+ return hints.length ? hints.join("\n") : null;
+ }
+ return null;
+}
diff --git a/axiom-pi/src/index.ts b/axiom-pi/src/index.ts
new file mode 100644
index 00000000..33845fc7
--- /dev/null
+++ b/axiom-pi/src/index.ts
@@ -0,0 +1,107 @@
+/**
+ * axiom-pi — Axiom's commands and hooks for the Pi coding agent.
+ *
+ * Skills are installed separately (`npx skills add CharlesWiltgen/Axiom -a pi`).
+ * This extension adds the two layers Pi can't get from skills alone:
+ * - the `/axiom-*` commands (trigger the matching skill inline), and
+ * - the SessionStart / tool hooks (version ground truth, Swift guardrail,
+ * swiftformat, crash-file routing, Bash skill hints).
+ */
+
+import type {
+ ExtensionAPI,
+ BeforeAgentStartEvent,
+ ToolCallEvent,
+ ToolResultEvent,
+} from "@earendil-works/pi-coding-agent";
+import * as fs from "node:fs";
+
+import { AXIOM_COMMANDS } from "./commands.ts";
+import {
+ AXIOM_TOOLS,
+ buildAxiomContext,
+ findOnPath,
+ resolveContextDecision,
+ type ResolvedTool,
+} from "./session.ts";
+import { crashFileHint, inputPath, toolResultHint } from "./guardrails.ts";
+
+export default function axiomPi(pi: ExtensionAPI): void {
+ // --- Commands: /axiom- → trigger the matching skill ----------------
+ for (const cmd of AXIOM_COMMANDS) {
+ pi.registerCommand(cmd.name, {
+ description: cmd.description,
+ getArgumentCompletions: (prefix) => {
+ if (!cmd.completions) return null;
+ const matches = cmd.completions.filter((c) => c.startsWith(prefix));
+ return matches.length ? matches.map((value) => ({ value, label: value })) : null;
+ },
+ handler: async (args) => {
+ try {
+ pi.sendUserMessage(cmd.prompt(args)); // synchronous; queues the prompt
+ } catch (err) {
+ console.error(`[axiom-pi] /${cmd.name} failed to dispatch:`, err);
+ }
+ },
+ });
+ }
+
+ // --- Session hook: version ground truth + tool availability --------------
+ // Computed once from the session's initial cwd (the gate + PATH probe are
+ // stable for a session) and chained onto the system prompt each turn. Pi
+ // passes the freshly-rebuilt BASE prompt to this event every turn
+ // (agent-session resets to base when no extension modifies it), so the
+ // append is idempotent — it never accumulates. `undefined` = not yet computed.
+ let cachedContext: string | null | undefined;
+
+ function axiomContextForSession(cwd: string): string | null {
+ if (cachedContext !== undefined) return cachedContext;
+ if (!resolveContextDecision(cwd, process.env.AXIOM_SESSION_CONTEXT)) {
+ cachedContext = null;
+ return null;
+ }
+ const availableTools: ResolvedTool[] = [];
+ for (const t of AXIOM_TOOLS) {
+ const resolvedPath = findOnPath(t.name);
+ if (resolvedPath) availableTools.push({ ...t, resolvedPath });
+ }
+ cachedContext = buildAxiomContext({ now: new Date(), availableTools });
+ return cachedContext;
+ }
+
+ pi.on("before_agent_start", (event: BeforeAgentStartEvent, ctx) => {
+ const context = axiomContextForSession(ctx.cwd);
+ if (!context) return;
+ return { systemPrompt: `${event.systemPrompt}\n\n${context}` };
+ });
+
+ // --- Pre-read hook: route crash-file Reads to xcsym ----------------------
+ // Fires before the Read executes (advisory, never blocks) so the agent is
+ // told to symbolicate with xcsym before relying on the raw, unsymbolicated file.
+ pi.on("tool_call", (event: ToolCallEvent) => {
+ if (event.toolName !== "read") return;
+ const p = inputPath(event.input);
+ const hint = p ? crashFileHint(p) : null;
+ if (hint) pi.sendMessage({ customType: "axiom-crash-hint", content: hint, display: true });
+ });
+
+ // --- Post-tool hooks: Swift guardrail + swiftformat, Bash skill hints -----
+ pi.on("tool_result", async (event: ToolResultEvent) => {
+ // Compute the advisory first (reads the pre-format file, so the @State
+ // warning's line numbers match what the model wrote), then format.
+ const hint = toolResultHint(event, (p) => fs.readFileSync(p, "utf8"));
+
+ if (event.toolName === "write" || event.toolName === "edit") {
+ const p = inputPath(event.input);
+ if (p && p.endsWith(".swift") && findOnPath("swiftformat")) {
+ try {
+ await pi.exec("swiftformat", [p, "--quiet"]);
+ } catch {
+ // Formatting is best-effort — never fail the write.
+ }
+ }
+ }
+
+ if (hint) return { content: [...event.content, { type: "text", text: hint }] };
+ });
+}
diff --git a/axiom-pi/src/session.test.ts b/axiom-pi/src/session.test.ts
new file mode 100644
index 00000000..246c599f
--- /dev/null
+++ b/axiom-pi/src/session.test.ts
@@ -0,0 +1,93 @@
+import { describe, it, expect } from "vitest";
+import * as fs from "node:fs";
+import * as os from "node:os";
+import * as path from "node:path";
+import {
+ formatDate,
+ iosGroundTruth,
+ findOnPath,
+ toolContextBlock,
+ buildAxiomContext,
+ isAppleProject,
+ resolveContextDecision,
+} from "./session.ts";
+
+describe("formatDate", () => {
+ it("stamps weekday and ISO date in local time", () => {
+ expect(formatDate(new Date(2026, 5, 14))).toBe("Sunday, 2026-06-14");
+ });
+});
+
+describe("iosGroundTruth", () => {
+ it("states the iOS 26 ground truth and no-denial rule, stamped with the date", () => {
+ const text = iosGroundTruth(new Date(2026, 5, 14));
+ expect(text).toContain("iOS 26 is the current major line");
+ expect(text).toContain('NEVER claim an iOS/Xcode version "doesn\'t exist"');
+ expect(text).toContain("Sunday, 2026-06-14");
+ });
+});
+
+describe("findOnPath", () => {
+ const env: NodeJS.ProcessEnv = { PATH: ["/a", "/b"].join(path.delimiter) };
+
+ it("returns the first PATH dir that contains the binary", () => {
+ const found = findOnPath("tool", env, (p) => p === path.join("/b", "tool"));
+ expect(found).toBe(path.join("/b", "tool"));
+ });
+
+ it("returns null when the binary is on no PATH dir", () => {
+ expect(findOnPath("tool", env, () => false)).toBeNull();
+ });
+});
+
+describe("toolContextBlock", () => {
+ it("is empty when no tools are available", () => {
+ expect(toolContextBlock([])).toBe("");
+ });
+
+ it("lists available tools with their resolved paths", () => {
+ const block = toolContextBlock([{ name: "xcsym", blurb: "crash", resolvedPath: "/usr/local/bin/xcsym" }]);
+ expect(block).toContain("xcsym");
+ expect(block).toContain("/usr/local/bin/xcsym");
+ });
+});
+
+describe("buildAxiomContext", () => {
+ it("wraps ground truth and available tools in the importance marker", () => {
+ const ctx = buildAxiomContext({
+ now: new Date(2026, 5, 14),
+ availableTools: [{ name: "xclog", blurb: "console", resolvedPath: "/bin/xclog" }],
+ });
+ expect(ctx).toContain("");
+ expect(ctx).toContain("iOS 26 is the current major line");
+ expect(ctx).toContain("/bin/xclog");
+ });
+});
+
+describe("isAppleProject / resolveContextDecision", () => {
+ it("detects a directory containing an Xcode project", () => {
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "axiom-apple-"));
+ try {
+ fs.mkdirSync(path.join(dir, "App.xcodeproj"));
+ expect(isAppleProject(dir)).toBe(true);
+ } finally {
+ fs.rmSync(dir, { recursive: true, force: true });
+ }
+ });
+
+ it("returns false for a marker-free git repo", () => {
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "axiom-plain-"));
+ try {
+ fs.writeFileSync(path.join(dir, ".git"), ""); // stops the upward walk at this dir
+ fs.writeFileSync(path.join(dir, "notes.txt"), "hi");
+ expect(isAppleProject(dir)).toBe(false);
+ } finally {
+ fs.rmSync(dir, { recursive: true, force: true });
+ }
+ });
+
+ it("honors the AXIOM_SESSION_CONTEXT override without scanning", () => {
+ expect(resolveContextDecision("/nonexistent", "never")).toBe(false);
+ expect(resolveContextDecision("/nonexistent", "always")).toBe(true);
+ });
+});
diff --git a/axiom-pi/src/session.ts b/axiom-pi/src/session.ts
new file mode 100644
index 00000000..3dd856e4
--- /dev/null
+++ b/axiom-pi/src/session.ts
@@ -0,0 +1,195 @@
+/**
+ * Session-context injection, ported from Axiom's SessionStart hook
+ * (session-start.py / project_detect.py).
+ *
+ * Pi already loads the `axiom-*` skills (their descriptions sit in context),
+ * so this does NOT re-inject skill content. It injects only what skills can't
+ * supply: the iOS-version behavioral ground truth, and which bundled Axiom
+ * command-line tools are on PATH. The Apple-project gate keeps it quiet in
+ * non-Apple repos (fail-open — doubt injects).
+ */
+
+import * as fs from "node:fs";
+import * as path from "node:path";
+
+const WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
+
+/** "Sunday, 2026-06-14" in local time, matching the Claude hook's stamp. */
+export function formatDate(now: Date): string {
+ const y = now.getFullYear();
+ const m = String(now.getMonth() + 1).padStart(2, "0");
+ const d = String(now.getDate()).padStart(2, "0");
+ return `${WEEKDAYS[now.getDay()]}, ${y}-${m}-${d}`;
+}
+
+/** iOS/Xcode version ground truth + behavioral rules (additive, never asserts a cutoff). */
+export function iosGroundTruth(now: Date): string {
+ return `## iOS / Xcode VERSION GROUND TRUTH (Current date: ${formatDate(now)})
+
+iOS 26 is the current major line — Apple went straight from iOS 18 to iOS 26 at
+WWDC 2025; the in-between majors (19-25) were never released. Xcode 26 ships with
+it. A newer major may have shipped since your training cutoff — don't assume 26 is
+still the latest.
+
+BEHAVIORAL RULES:
+1. NEVER claim an iOS/Xcode version "doesn't exist" or is "wrong" because it
+ postdates your training — that includes iOS 26 and anything above it.
+2. NEVER state which iOS/Xcode version is "current" or "latest" from training
+ alone — defer to Axiom skills, or check https://support.apple.com/en-us/123075.
+3. For iOS-version or new-API questions, load the relevant Axiom skill first
+ (axiom-apple-docs, axiom-swiftui) — they carry WWDC 2025+ documentation.
+4. Before giving OS-version-specific advice, establish the user's DEPLOYMENT TARGET.
+ Advice for a newer OS than the target can name APIs the user cannot ship. For any
+ API marked new in a newer cycle, give the \`@available\`/\`#available\` gate and the
+ pre-cycle fallback — not just the new path.
+
+This is a behavioral instruction grounded in Apple's release history, not a claim
+about your training data.`;
+}
+
+export type AxiomTool = { name: string; blurb: string };
+
+/** The four command-line tools Axiom ships. Detected on PATH at runtime. */
+export const AXIOM_TOOLS: readonly AxiomTool[] = [
+ { name: "xclog", blurb: "simulator console capture — `xclog list`, `xclog launch --timeout 30s`" },
+ { name: "xcsym", blurb: "crash symbolication — `xcsym crash `, `xcsym verify `" },
+ { name: "xcui", blurb: "scriptable sim UI & accessibility — `xcui doctor`, `xcui assert`, `xcui voiceover`" },
+ { name: "xcprof", blurb: "structured xctrace capture/analysis — `xcprof record`, `xcprof analyze`, `xcprof compare`" },
+];
+
+/** True if `p` is an executable regular file (not a directory or non-exec file). */
+function isExecutableFile(p: string): boolean {
+ try {
+ if (!fs.statSync(p).isFile()) return false;
+ fs.accessSync(p, fs.constants.X_OK);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+/** First directory on PATH holding an executable `name`, or null. Predicate injectable for tests. */
+export function findOnPath(
+ name: string,
+ env: NodeJS.ProcessEnv = process.env,
+ isExecutable: (p: string) => boolean = isExecutableFile,
+): string | null {
+ for (const dir of (env.PATH || "").split(path.delimiter)) {
+ if (dir && isExecutable(path.join(dir, name))) return path.join(dir, name);
+ }
+ return null;
+}
+
+export type ResolvedTool = { name: string; blurb: string; resolvedPath: string };
+
+/** Markdown block listing the Axiom tools found on PATH, or "" when none. */
+export function toolContextBlock(available: readonly ResolvedTool[]): string {
+ if (available.length === 0) return "";
+ const lines = available.map((t) => `- **${t.name}** (\`${t.resolvedPath}\`): ${t.blurb}`).join("\n");
+ return `\n\n---\n\n**Axiom command-line tools on your PATH** — call them via \`bash\`:\n${lines}`;
+}
+
+/** The full `` context block injected before each turn. */
+export function buildAxiomContext(opts: { now: Date; availableTools: readonly ResolvedTool[] }): string {
+ return `
+You have Axiom iOS/Apple-platform development skills installed (the \`axiom-*\`
+skills). For ANY iOS, Swift, or Xcode question, load the relevant skill before
+answering.
+
+${iosGroundTruth(opts.now)}${toolContextBlock(opts.availableTools)}
+`;
+}
+
+// --- Apple-project gate (port of project_detect.py) ------------------------
+// Cardinal sin is a false negative (a real Apple project read as non-Apple →
+// Axiom silently off), so every path fails OPEN (inject) on doubt or error.
+
+const APPLE_MARKER_SUFFIXES = [".xcodeproj", ".xcworkspace", ".swiftpm", ".playground", ".swift"];
+const APPLE_MARKER_NAMES = new Set(["Podfile"]);
+const PRUNE_DIRS = new Set([
+ "node_modules", ".git", "build", ".build", "Pods", "DerivedData", "dist",
+ "target", ".venv", "venv", "vendor", "Carthage", ".gradle", "__pycache__", "out",
+ "Intermediate", "Binaries", "Saved", "DerivedDataCache", // Unreal
+ "Library", "Temp", "Obj", // Unity
+]);
+const UPWARD_MAX_LEVELS = 6;
+const DOWNWARD_MAX_DEPTH = 4;
+const MAX_ENTRIES = 10_000;
+
+function isMarker(name: string): boolean {
+ return APPLE_MARKER_NAMES.has(name) || APPLE_MARKER_SUFFIXES.some((s) => name.endsWith(s));
+}
+
+function dirHasMarker(dir: string): boolean {
+ try {
+ return fs.readdirSync(dir).some(isMarker);
+ } catch {
+ return false;
+ }
+}
+
+/** Bounded, pruned DFS for an Apple marker. Entry-cap hit → fail-open (true). */
+function downwardHasMarker(root: string): boolean {
+ let seen = 0;
+ const stack: Array<[string, number]> = [[root, 0]];
+ while (stack.length) {
+ const [dir, depth] = stack.pop()!;
+ let entries: fs.Dirent[];
+ try {
+ entries = fs.readdirSync(dir, { withFileTypes: true });
+ } catch {
+ continue;
+ }
+ for (const e of entries) {
+ if (++seen > MAX_ENTRIES) return true;
+ if (isMarker(e.name)) return true;
+ if (depth < DOWNWARD_MAX_DEPTH && !PRUNE_DIRS.has(e.name)) {
+ let isDir = false;
+ try {
+ isDir = e.isDirectory();
+ } catch {
+ isDir = false;
+ }
+ if (isDir) stack.push([path.join(dir, e.name), depth + 1]);
+ }
+ }
+ }
+ return false;
+}
+
+/** True if `start` is inside, or contains, an Apple project. Errors → fail-open. */
+export function isAppleProject(start: string): boolean {
+ try {
+ let cur = path.resolve(start);
+ if (!fs.existsSync(cur) || !fs.statSync(cur).isDirectory()) return true;
+ const home = process.env.HOME ? path.resolve(process.env.HOME) : null;
+ let scanRoot = cur;
+ let levels = 0;
+ for (;;) {
+ if (levels <= UPWARD_MAX_LEVELS && dirHasMarker(cur)) return true;
+ if (fs.existsSync(path.join(cur, ".git"))) {
+ scanRoot = cur;
+ break;
+ }
+ const parent = path.dirname(cur);
+ if (parent === cur) break;
+ if (home !== null && cur === home) break;
+ levels++;
+ cur = parent;
+ }
+ return downwardHasMarker(scanRoot);
+ } catch {
+ return true;
+ }
+}
+
+/**
+ * Whether to inject Axiom context. `AXIOM_SESSION_CONTEXT`: "never" → skip,
+ * "always" → inject without scanning, anything else → auto-detect.
+ */
+export function resolveContextDecision(cwd: string, override: string | undefined): boolean {
+ const o = (override || "").trim().toLowerCase();
+ if (o === "never") return false;
+ if (o === "always") return true;
+ return isAppleProject(cwd);
+}
diff --git a/axiom-pi/tsconfig.json b/axiom-pi/tsconfig.json
new file mode 100644
index 00000000..6cd7f406
--- /dev/null
+++ b/axiom-pi/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "lib": ["ES2023"],
+ "types": ["node"],
+ "strict": true,
+ "noEmit": true,
+ "skipLibCheck": true,
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "include": ["src"]
+}
diff --git a/package.json b/package.json
index 30d6d26c..af111cb0 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,10 @@
"version": "27.0.0-beta.3",
"description": "Battle-tested Claude Code skills, agents, and tools for modern xOS (iOS, iPadOS, tvOS, watchOS) development — Swift 6, SwiftUI, Liquid Glass, Apple Intelligence, and more",
"type": "module",
+ "pi": {
+ "skills": [".claude-plugin/plugins/axiom/skills"],
+ "extensions": ["axiom-pi/src/index.ts"]
+ },
"scripts": {
"build": "npm run build:codex && npm run build:mcp && npm run build:docs",
"build:codex": "node scripts/build-codex.ts",