monorepo_root = true [monorepo] config_roots = ["extensions/*"] [tools] node = "latest" go = "latest" biome = "latest" "aqua:mikefarah/yq" = "latest" "aqua:rvben/rumdl" = "latest" "aqua:tamasfe/taplo" = "latest" "go:golang.org/x/perf/cmd/benchstat" = "latest" [tasks.default] description = "List tasks" run = "mise tasks ls" [tasks.install] description = "Install Node dependencies" run = ["npm ci", "node scripts/patch_pi_test_harness.mjs"] sources = ["package.json", "package-lock.json", "scripts/patch_pi_test_harness.mjs"] outputs = ["node_modules/vitest/package.json"] [tasks.lock] description = "Regenerate package lock" run = "npm install --package-lock-only" [tasks.codegen] description = "Write configured generated extension files" run = "node scripts/codegen.mjs" [tasks.fmt] description = "Format repo" depends = ["install"] run = [ "npm run fmt", "rumdl fmt .", "taplo format", ] [tasks.format-files] description = "Format selected repository TypeScript files without touching unrelated work" depends = ["install"] usage = ''' arg "" var=#true ''' run = '''biome check --write{% for file in usage.files %} "{{ file }}"{% endfor %}''' [tasks.lint] description = "Verify formatting and lint" depends = ["install"] run = [ "npm run lint", "taplo format --check", "node scripts/check_frontmatter.mjs", "node scripts/check_skills.mjs", ] [tasks.test] description = "Run tests" tools."aqua:nushell/nushell" = "latest" depends = ["install"] usage = ''' arg "[args]" var=#true ''' run = [ '''npm run test --{% for arg in usage.args %} "{{ arg }}"{% endfor %}''', "node --test .pi/skills/modernize/scripts/audit.test.mjs", ] [tasks.context-startup] description = "Compare stock, configured, and no-Pi-text headless context (three live requests)" usage = ''' arg "[cwd]" help="Project directory to measure" ''' run = ''' node scripts/context-startup.mjs{% if usage.cwd %} "{{ usage.cwd }}"{% endif %} ''' [tasks.context-startup-sources] description = "Estimate APPEND_SYSTEM and skill tokens by source (no measurement prompt)" run = "node scripts/context-startup-session.mjs --sources" [tasks.context-startup-skill-descriptions] description = "Rank pi/agent skill descriptions by size and show the largest five" run = "node scripts/context-startup-session.mjs --skill-descriptions" [tasks.context-extensions] description = "Inspect runtime extensions and measure leave-one-out input tokens (N+2 live requests)" usage = ''' arg "[cwd]" help="Project directory to measure" ''' run = ''' node scripts/context-extensions.mjs{% if usage.cwd %} "{{ usage.cwd }}"{% endif %} ''' [tasks.context-guidance-check] description = "Read-only live activation check for tool-owned mockup guidance" depends = ["install"] env.PI_OFFLINE = "1" run = ''' pi --print --mode json --no-session --no-extensions --extension extensions/mockup/index.ts --no-context-files --tools read,mockup "Plan an interactive 80-column terminal task-list mockup with keyboard selection. Planning only: do not create or edit files, execute commands, call mockup, or open a browser. Load the applicable authoring guidance using read only, then explain the document boundary and target-platform constraints." | node --input-type=module -e " import { createInterface } from 'node:readline'; import { basename, dirname } from 'node:path'; const missing = new Set(['mockup-html']); const calls = new Map(); let completed = false; for await (const line of createInterface({ input: process.stdin })) { const event = JSON.parse(line); if (event.type === 'tool_execution_start') { if (event.toolName !== 'read') throw new Error('Unexpected tool: ' + event.toolName); console.log('read ' + event.args.path); if (basename(event.args.path) === 'SKILL.md') calls.set(event.toolCallId, basename(dirname(event.args.path))); } if (event.type === 'tool_execution_end' && !event.isError) missing.delete(calls.get(event.toolCallId)); if (event.type === 'message_end' && event.message.role === 'assistant' && event.message.stopReason === 'stop') { completed = true; console.log(event.message.content.filter(part => part.type === 'text').map(part => part.text).join('\n')); } } if (missing.size || !completed) throw new Error('Incomplete guidance check: ' + [...missing].join(', ')); console.log('PASS: mockup guidance read; only read tools used; turn completed.'); " ''' [tasks.context-startup-test] description = "Check the startup context measurement script" depends = ["install"] run = [ "biome check scripts/context-startup.mjs scripts/context-startup-session.mjs scripts/context-startup.test.ts scripts/context-extensions.mjs scripts/context-extensions.test.ts", "rumdl check scripts/context-startup.md", "taplo format --check mise.toml", { task = "//:test", args = [ "scripts/context-startup.test.ts", "scripts/context-extensions.test.ts", ] }, ] [tasks.context-startup-fmt] description = "Format context measurement files only" depends = ["install"] run = [ "biome check --write scripts/context-startup.mjs scripts/context-startup-session.mjs scripts/context-startup.test.ts scripts/context-extensions.mjs scripts/context-extensions.test.ts", "rumdl fmt scripts/context-startup.md", "taplo format mise.toml", ] [tasks.bench] description = "Run all extension benchmarks sequentially" depends = ["install"] run = "mise run --jobs 1 //extensions/...:bench" [tasks.modernize-bench] description = "Benchmark modernize audit" tools.hyperfine = "latest" usage = ''' arg "[args]" var=#true ''' run = ''' node .pi/skills/modernize/scripts/audit.bench.mjs{% for arg in usage.args %} "{{ arg }}"{% endfor %} ''' [tasks.extension-startup-bench] description = "Benchmark configured extension startup to RPC readiness" depends = ["install"] run = "node scripts/extension-startup.bench.mjs" [tasks.debug-bench] description = "Benchmark the generated debug writer at startup and per record" depends = ["install"] usage = ''' arg "[template]" help="Template copy to measure, defaults to the current template" ''' run = 'node scripts/codegen/pi-ext-debug.bench.mjs{% if usage.template %} "{{ usage.template }}"{% endif %}' [tasks.extension-startup-benchstat] description = "Compare extension startup benchmark results" depends = ["install"] usage = ''' arg "" arg "" ''' run = 'benchstat "{{ usage.baseline }}" "{{ usage.candidate }}"' [tasks.e2e] description = "Run local E2E in disposable OS temp (PI_EXT_E2E_FILTER= for one suite; real S3: //extensions/bak:e2e-s3)" depends = ["install"] run = "node scripts/e2e.mjs //extensions/chrome-cdp:e2e //extensions/klaus:e2e //extensions/mockup:e2e //extensions/strata:e2e //extensions/the-system:e2e" [tasks.build-ext] description = "Build selected extension packages into dist/ (--release for the release variant)" depends = ["install"] usage = ''' arg "" var=#true flag "--release" help="Minified release variant without sourcemaps" ''' run = ''' node --no-warnings scripts/build/cli.ts{% if usage.release %} --release{% endif %}{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.build-all] description = "Build every extension package into dist/ (--release for the release variant)" depends = ["install"] usage = ''' flag "--release" help="Minified release variant without sourcemaps" ''' run = ''' node --no-warnings scripts/build/cli.ts --all{% if usage.release %} --release{% endif %} ''' [tasks.settings-entries] description = "Print the explicit dist/ package list for ~/.pi/agent/settings.json packages" run = "node --no-warnings scripts/build/settings-entries.ts" [tasks.verify-packages] description = "Load generated packages relocated outside the checkout through Pi (all built packages when none given)" depends = ["install"] usage = ''' arg "[extensions]" var=#true flag "--collection" help="Load the selected packages together and fail on identity, tool, command, flag, or skill conflicts" ''' run = ''' node --no-warnings scripts/build/verify-cli.ts{% if usage.collection %} --collection{% endif %}{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.build] description = "Typecheck and statically validate extensions" depends = ["install"] usage = ''' arg "[extensions]" var=#true ''' run = [ "npm run typecheck", '''node scripts/extensions.mjs check{% for extension in usage.extensions %} "{{ extension }}"{% endfor %}''', ] [tasks.check] description = "Typecheck and run static extension checks" depends = ["install"] run = [ "npm run typecheck", "node scripts/check_skills.mjs", "node scripts/test_extensions_static_check.mjs", "node scripts/extensions.mjs check", ] [tasks.release-all] description = "Build and validate all release packages and exact archives" depends = ["install"] run = "node --no-warnings scripts/build/release.ts" [tasks.ci] description = "Release gate" run = [ { tasks = ["check", "lint"] }, { task = "test" }, { task = "e2e" }, { task = "release-all" }, ] [tasks.list] description = "List extensions" usage = ''' arg "[extensions]" var=#true ''' run = ''' node scripts/extensions.mjs list{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.changelog] description = "Generate changelog" usage = ''' arg "" var=#true ''' run = ''' node scripts/extensions.mjs changelog{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.readme] description = "Generate/update READMEs" usage = ''' arg "[extensions]" var=#true flag "--model " ''' run = ''' node scripts/extensions.mjs readme --write{% if usage.model %} --model "{{ usage.model }}"{% endif %}{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.release-plan] description = "Preview release artifacts" usage = ''' arg "[extensions]" var=#true flag "--model " ''' run = ''' node scripts/extensions.mjs release-plan{% if usage.model %} --model "{{ usage.model }}"{% endif %}{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.release-prepare] description = "Generate release artifacts" usage = ''' arg "[extensions]" var=#true flag "--model " ''' run = ''' node scripts/extensions.mjs release-prepare{% if usage.model %} --model "{{ usage.model }}"{% endif %}{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.clean] description = "Remove generated caches and scratch artifacts" run = ''' find . -path ./.git -prune -o -path ./.jj -prune -o -type d -name node_modules -prune -exec rm -rf {} + ''' [tasks.publish] description = "Publish prepared release artifacts" usage = ''' arg "[extensions]" var=#true ''' run = ''' node scripts/extensions.mjs publish{% for extension in usage.extensions %} "{{ extension }}"{% endfor %} ''' [tasks.pre-commit] description = "Pre-commit hook: check + lint" run = [{ tasks = ["check", "lint"] }] [tasks.pre-push] description = "Pre-push hook: check + lint" run = [{ tasks = ["check", "lint"] }]