@tekmidian/pai 0.43.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chain-CEC1a5mX.mjs → chain-DAEC9AU7.mjs} +2 -2
- package/dist/{chain-CEC1a5mX.mjs.map → chain-DAEC9AU7.mjs.map} +1 -1
- package/dist/cli/index.mjs +4 -4
- package/dist/cli/program.mjs +4 -4
- package/dist/daemon/index.mjs +2 -2
- package/dist/{daemon-QIvCXB5f.mjs → daemon-BVbvL8IA.mjs} +2 -2
- package/dist/{daemon-BhldpFvO.mjs → daemon-ebLDoKM3.mjs} +2 -2
- package/dist/{daemon-BhldpFvO.mjs.map → daemon-ebLDoKM3.mjs.map} +1 -1
- package/dist/daemon-mcp/index.mjs +3 -3
- package/dist/{fallback-BQJ8PbCK.mjs → fallback-CxGDTXWt.mjs} +2 -2
- package/dist/{fallback-BQJ8PbCK.mjs.map → fallback-CxGDTXWt.mjs.map} +1 -1
- package/dist/hooks/load-project-context.mjs.map +1 -1
- package/dist/hooks/mcp-deferred-reminder.mjs.map +1 -1
- package/dist/{planner-BlKGgpWI.mjs → planner-B4DvNpXd.mjs} +3 -3
- package/dist/{planner-BlKGgpWI.mjs.map → planner-B4DvNpXd.mjs.map} +1 -1
- package/dist/{program-C5jRQ1kg.mjs → program-cr5U1-DK.mjs} +612 -54
- package/dist/program-cr5U1-DK.mjs.map +1 -0
- package/dist/{run-ByBKowN5.mjs → run-BgExF8Xg.mjs} +16 -4
- package/dist/{run-ByBKowN5.mjs.map → run-BgExF8Xg.mjs.map} +1 -1
- package/docs/commands/README.md +3 -1
- package/docs/commands/audit.md +25 -2
- package/package.json +1 -1
- package/src/hooks/ts/lib/context-fill.test.ts +40 -0
- package/src/hooks/ts/session-start/load-project-context.ts +3 -3
- package/src/hooks/ts/session-start/mcp-deferred-reminder.ts +2 -2
- package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +0 -1
- package/dist/hooks/session-commands.mjs +0 -26
- package/dist/hooks/session-commands.mjs.map +0 -7
- package/dist/program-C5jRQ1kg.mjs.map +0 -1
- package/src/hooks/ts/session-start/session-commands.ts +0 -30
package/docs/commands/README.md
CHANGED
|
@@ -45,16 +45,18 @@ Generated man pages for every `pai` command area. Read any page in the terminal
|
|
|
45
45
|
| Command | Description |
|
|
46
46
|
|---------|-------------|
|
|
47
47
|
| `pai audit` | Diagnostic audits: token-waste report and friends |
|
|
48
|
-
| `pai audit tokens` | Token-waste audit: memory files, hooks, session usage, spawn overhead, daemon, env, schedule, skill catalogue |
|
|
48
|
+
| `pai audit tokens` | Token-waste audit: memory files, hooks, session usage, spawn overhead, daemon, env, schedule, skill catalogue, subagents, MCP |
|
|
49
49
|
| `pai audit tokens daemon` | LLM spawns, KG-extraction parse failures, work-queue counts from the daemon log |
|
|
50
50
|
| `pai audit tokens env` | ANTHROPIC_BASE_URL / model-override env on every live claude process |
|
|
51
51
|
| `pai audit tokens files [paths...]` | Token count per memory file (CLAUDE.md chain, CORE skill, whisper rules, auto-memory) |
|
|
52
52
|
| `pai audit tokens hooks` | Token cost of every SessionStart / UserPromptSubmit hook |
|
|
53
53
|
| `pai audit tokens ladder` | LIVE: first-turn context at increasing headless-worker configuration (spawns real claude -p calls) |
|
|
54
|
+
| `pai audit tokens mcp` | MCP servers: configured vs. pinned vs. loaded-live vs. used in the last 30 days |
|
|
54
55
|
| `pai audit tokens schedule` | Launchd agents / crontab entries that outpace the measured prompt-cache TTL |
|
|
55
56
|
| `pai audit tokens session [path]` | Cache/input/output token split for a session transcript (default: newest) |
|
|
56
57
|
| `pai audit tokens skills` | Token cost of the SKILL.md / command / plugin catalogue, top entries, duplicate names |
|
|
57
58
|
| `pai audit tokens spawn` | Spawn-overhead comparison: Agent-tool subagents vs. pai workers |
|
|
59
|
+
| `pai audit tokens subagents` | Token cost of Claude Code subagent definitions (~/.claude/agents, <cwd>/.claude/agents) and their model pinning |
|
|
58
60
|
| `pai backup` | Backup registry, config, and Postgres database to PAI_HOME/backups/ |
|
|
59
61
|
| `pai clear-names` | Recovery: wipe corrupted iTerm2 session name state. |
|
|
60
62
|
| `pai config` | PAI_HOME namespace dir: path, migrate |
|
package/docs/commands/audit.md
CHANGED
|
@@ -14,17 +14,18 @@ pai audit <subcommand> [options]
|
|
|
14
14
|
|
|
15
15
|
| Command | Description |
|
|
16
16
|
|---------|-------------|
|
|
17
|
-
| [`pai audit tokens`](#pai-audit-tokens) | Token-waste audit: memory files, hooks, session usage, spawn overhead, daemon, env, schedule, skill catalogue |
|
|
17
|
+
| [`pai audit tokens`](#pai-audit-tokens) | Token-waste audit: memory files, hooks, session usage, spawn overhead, daemon, env, schedule, skill catalogue, subagents, MCP |
|
|
18
18
|
|
|
19
19
|
### pai audit tokens
|
|
20
20
|
|
|
21
|
-
Token-waste audit: memory files, hooks, session usage, spawn overhead, daemon, env, schedule, skill catalogue
|
|
21
|
+
Token-waste audit: memory files, hooks, session usage, spawn overhead, daemon, env, schedule, skill catalogue, subagents, MCP
|
|
22
22
|
|
|
23
23
|
**Options**
|
|
24
24
|
|
|
25
25
|
| Option | Description | Default |
|
|
26
26
|
|--------|-------------|---------|
|
|
27
27
|
| `--json` | Print JSON instead of a table | |
|
|
28
|
+
| `--record <dir>` | Write a dated, numbered markdown+JSON snapshot of the combined report to <dir> | |
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
### pai audit tokens files [paths...]
|
|
@@ -53,6 +54,12 @@ Cache/input/output token split for a session transcript (default: newest)
|
|
|
53
54
|
|----------|------|-------------|
|
|
54
55
|
| `[path]` | optional | Session JSONL path (default: newest under ~/.claude/projects) |
|
|
55
56
|
|
|
57
|
+
**Options**
|
|
58
|
+
|
|
59
|
+
| Option | Description | Default |
|
|
60
|
+
|--------|-------------|---------|
|
|
61
|
+
| `--ctx-threshold <n>` | Per-turn context size above which a turn counts as 'above threshold' (default 200000) | |
|
|
62
|
+
|
|
56
63
|
|
|
57
64
|
### pai audit tokens spawn
|
|
58
65
|
|
|
@@ -92,6 +99,22 @@ Token cost of the SKILL.md / command / plugin catalogue, top entries, duplicate
|
|
|
92
99
|
| `--top <n>` | How many top-by-tokens entries to show (default 15) | |
|
|
93
100
|
|
|
94
101
|
|
|
102
|
+
### pai audit tokens subagents
|
|
103
|
+
|
|
104
|
+
Token cost of Claude Code subagent definitions (~/.claude/agents, <cwd>/.claude/agents) and their model pinning
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
### pai audit tokens mcp
|
|
108
|
+
|
|
109
|
+
MCP servers: configured vs. pinned vs. loaded-live vs. used in the last 30 days
|
|
110
|
+
|
|
111
|
+
**Options**
|
|
112
|
+
|
|
113
|
+
| Option | Description | Default |
|
|
114
|
+
|--------|-------------|---------|
|
|
115
|
+
| `--connect` | Actually connect to every stdio MCP server to count exposed tools (side-effecting; never on by default) | |
|
|
116
|
+
|
|
117
|
+
|
|
95
118
|
### pai audit tokens ladder
|
|
96
119
|
|
|
97
120
|
LIVE: first-turn context at increasing headless-worker configuration (spawns real claude -p calls)
|
package/package.json
CHANGED
|
@@ -632,6 +632,46 @@ describe("contextFillThresholds — trigger source", () => {
|
|
|
632
632
|
});
|
|
633
633
|
});
|
|
634
634
|
|
|
635
|
+
// ---------------------------------------------------------------------------
|
|
636
|
+
// contextFillThresholds — the 2026-09-20 regime change (override 80 -> 20 on
|
|
637
|
+
// a 1M window). Same min(measured, configured) formula, no code change
|
|
638
|
+
// needed, but the specific numbers of that day are worth pinning down: a
|
|
639
|
+
// project's measured history (784k, from the prior 78-79% regime) is now
|
|
640
|
+
// HIGHER than the newly configured 20%-of-1M trigger (200k), so the clamp
|
|
641
|
+
// must take the configured value, not the stale measured one.
|
|
642
|
+
// ---------------------------------------------------------------------------
|
|
643
|
+
|
|
644
|
+
describe("contextFillThresholds — 2026-09-20 regime change (override 80 -> 20)", () => {
|
|
645
|
+
it("measured 784k + configured 200k (override=20, 1M window) -> clamps to 200k", () => {
|
|
646
|
+
const t = contextFillThresholds(readingAt(1_000_000), { CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "20" }, { measuredTrigger: 784_000 });
|
|
647
|
+
expect(t.configuredTriggerTokens).toBe(200_000);
|
|
648
|
+
expect(t.triggerSource).toBe("measured-clamped");
|
|
649
|
+
expect(t.effectiveTriggerTokens).toBe(200_000);
|
|
650
|
+
expect(t.warmupTokens).toBe(100_000); // 200,000 - 100,000
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
it("measured 784k + configured 800k (override=80, 1M window) -> measured wins at 784k", () => {
|
|
654
|
+
const t = contextFillThresholds(readingAt(1_000_000), { CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "80" }, { measuredTrigger: 784_000 });
|
|
655
|
+
expect(t.configuredTriggerTokens).toBe(800_000);
|
|
656
|
+
expect(t.triggerSource).toBe("measured");
|
|
657
|
+
expect(t.effectiveTriggerTokens).toBe(784_000);
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
it("measured null + configured 200k (override=20, no compaction history yet) -> 200k", () => {
|
|
661
|
+
const t = contextFillThresholds(readingAt(1_000_000), { CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "20" }, { measuredTrigger: null });
|
|
662
|
+
expect(t.triggerSource).toBe("configured");
|
|
663
|
+
expect(t.effectiveTriggerTokens).toBe(200_000);
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it("measured 784k + override unset (defaults to 80, configured 800k) -> measured wins at 784k", () => {
|
|
667
|
+
const t = contextFillThresholds(readingAt(1_000_000), {}, { measuredTrigger: 784_000 });
|
|
668
|
+
expect(t.autocompactPct).toBe(80);
|
|
669
|
+
expect(t.configuredTriggerTokens).toBe(800_000);
|
|
670
|
+
expect(t.triggerSource).toBe("measured");
|
|
671
|
+
expect(t.effectiveTriggerTokens).toBe(784_000);
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
|
|
635
675
|
// ---------------------------------------------------------------------------
|
|
636
676
|
// Foreign-model transcripts — a headless worker on another provider (a
|
|
637
677
|
// different context window) shares the project folder; its compactions must
|
|
@@ -498,9 +498,9 @@ Session Commands:
|
|
|
498
498
|
// 8.5. INJECT THE PAUSE CHECKPOINT
|
|
499
499
|
//
|
|
500
500
|
// `pai pause` writes the handover to TODO.md under `## Continue`. Until now
|
|
501
|
-
// nothing read it back:
|
|
502
|
-
//
|
|
503
|
-
//
|
|
501
|
+
// nothing read it back: CORE SKILL.md only told the model to look there *if
|
|
502
|
+
// the user typed "go"*, so a resumed session started blind unless the user
|
|
503
|
+
// knew the magic word. Writing a handover nobody delivers is not a
|
|
504
504
|
// handover. Inject it, and say plainly that it is the previous session's
|
|
505
505
|
// state rather than an instruction to act on.
|
|
506
506
|
if (existsSync(todoPath)) {
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* call: see ../lib/mcp-deferred-reminder.ts for the rationale and text.
|
|
12
12
|
*
|
|
13
13
|
* stdout is captured by Claude Code and injected into the session context,
|
|
14
|
-
* same channel as
|
|
15
|
-
*
|
|
14
|
+
* same channel as inject-observations. Never blocks session start: always
|
|
15
|
+
* exits 0.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { decideMcpDeferredReminder, type ReminderHookInput } from "../lib/mcp-deferred-reminder.js";
|
|
@@ -15,7 +15,6 @@ describe("session-start hooks: worker sessions get no injected context", () => {
|
|
|
15
15
|
"src/hooks/ts/session-start/load-project-context.ts",
|
|
16
16
|
"src/hooks/ts/session-start/mcp-deferred-reminder.ts",
|
|
17
17
|
"src/hooks/ts/session-start/post-compact-inject.ts",
|
|
18
|
-
"src/hooks/ts/session-start/session-commands.ts",
|
|
19
18
|
];
|
|
20
19
|
|
|
21
20
|
function runHook(entrypoint: string, env: NodeJS.ProcessEnv): string {
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { createRequire as __paiCreateRequire } from 'node:module';
|
|
3
|
-
const require = __paiCreateRequire(import.meta.url);
|
|
4
|
-
if (!process.env.PAI_QUIET_NOTICES) process.env.PAI_QUIET_NOTICES = '1';
|
|
5
|
-
|
|
6
|
-
// src/hooks/ts/lib/worker-session.ts
|
|
7
|
-
function isWorkerSession(env = process.env) {
|
|
8
|
-
return env.PAI_WORKER === "1";
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// src/hooks/ts/session-start/session-commands.ts
|
|
12
|
-
if (isWorkerSession()) process.exit(0);
|
|
13
|
-
var commands = `<system-reminder>
|
|
14
|
-
SESSION COMMANDS (always available):
|
|
15
|
-
|
|
16
|
-
- "go" / "continue" / "weiter" \u2192 Read Notes/TODO.md, find ## Continue section, resume work
|
|
17
|
-
- "pause session" \u2192 Save state to TODO.md, update session note, stop (no compact)
|
|
18
|
-
- "end session" \u2192 Finalize note, commit if needed, start fresh next time
|
|
19
|
-
- "cpp" \u2192 Release workflow: version bump \u2192 build \u2192 npm publish \u2192 git add ALL \u2192 ONE commit \u2192 git push
|
|
20
|
-
|
|
21
|
-
When user says "go" with no other context, ALWAYS check TODO.md first.
|
|
22
|
-
|
|
23
|
-
IMPORTANT: Full PAI context may be truncated due to size. For complete instructions (response format, workflows, principles), READ: ~/.claude/Skills/CORE/SKILL.md
|
|
24
|
-
</system-reminder>`;
|
|
25
|
-
console.log(commands);
|
|
26
|
-
//# sourceMappingURL=session-commands.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/hooks/ts/lib/worker-session.ts", "../../../src/hooks/ts/session-start/session-commands.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Worker-session detection.\n *\n * A disposable headless worker (a `claude -p` run started by an orchestrating\n * session, possibly against a different model provider with a different\n * context window) shares the project directory and the hook configuration\n * with the real session that spawned it. Left alone, the hooks treat it as a\n * session in its own right: they inject project context into it, create and\n * rename a numbered session note for it, autosave it, and enqueue a\n * model-written handover for it. Its compactions also land in the project's\n * transcript folder, where they are indistinguishable from a real session's\n * and drag the measured compaction trigger down (observed 2026-09-17: two\n * workers compacting at ~151k tokens pulled a project's trigger from ~784k\n * to ~151k, and the real session's handover fired at ~50k tokens).\n *\n * The launcher marks such sessions with `PAI_WORKER=1`. Every hook that does\n * per-session bookkeeping returns immediately when this predicate is true.\n * Deliberately NOT guarded: the security validator (a worker's shell\n * commands must still be checked) and observability capture.\n */\nexport function isWorkerSession(env: NodeJS.ProcessEnv = process.env): boolean {\n return env.PAI_WORKER === \"1\";\n}\n", "#!/usr/bin/env node\n\n/**\n * session-commands.ts\n *\n * Tiny SessionStart hook that injects critical session commands inline.\n * Stays under 2KB to avoid persisted-output truncation.\n *\n * This runs BEFORE load-core-context so these commands are always available\n * even when the full CORE skill gets truncated.\n */\n\nimport { isWorkerSession } from \"../lib/worker-session.js\";\n\nif (isWorkerSession()) process.exit(0); // disposable worker: no per-session bookkeeping\n\nconst commands = `<system-reminder>\nSESSION COMMANDS (always available):\n\n- \"go\" / \"continue\" / \"weiter\" \u2192 Read Notes/TODO.md, find ## Continue section, resume work\n- \"pause session\" \u2192 Save state to TODO.md, update session note, stop (no compact)\n- \"end session\" \u2192 Finalize note, commit if needed, start fresh next time\n- \"cpp\" \u2192 Release workflow: version bump \u2192 build \u2192 npm publish \u2192 git add ALL \u2192 ONE commit \u2192 git push\n\nWhen user says \"go\" with no other context, ALWAYS check TODO.md first.\n\nIMPORTANT: Full PAI context may be truncated due to size. For complete instructions (response format, workflows, principles), READ: ~/.claude/Skills/CORE/SKILL.md\n</system-reminder>`;\n\nconsole.log(commands);\n"],
|
|
5
|
-
"mappings": ";;;;;;AAoBO,SAAS,gBAAgB,MAAyB,QAAQ,KAAc;AAC7E,SAAO,IAAI,eAAe;AAC5B;;;ACRA,IAAI,gBAAgB,EAAG,SAAQ,KAAK,CAAC;AAErC,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAajB,QAAQ,IAAI,QAAQ;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|