@rubytech/create-maxy-code 0.1.568 → 0.1.570
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/package.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +7 -5
- package/payload/platform/plugins/admin/hooks/__tests__/pdf-text-layer-inject.test.sh +177 -0
- package/payload/platform/plugins/admin/hooks/__tests__/quote-path-write-gate.test.sh +152 -0
- package/payload/platform/plugins/admin/hooks/__tests__/quote-pdf-bash-gate.test.sh +95 -0
- package/payload/platform/plugins/admin/hooks/__tests__/quote-render-gate.test.sh +141 -45
- package/payload/platform/plugins/admin/hooks/__tests__/quote-render-pdf-conformance.test.sh +114 -0
- package/payload/platform/plugins/admin/hooks/pdf-text-layer-inject.sh +137 -0
- package/payload/platform/plugins/admin/hooks/quote-path-write-gate.sh +137 -0
- package/payload/platform/plugins/admin/hooks/quote-pdf-bash-gate.sh +70 -0
- package/payload/platform/plugins/admin/hooks/quote-render-gate.sh +105 -37
- package/payload/platform/plugins/admin/hooks/quote-render-pdf-conformance.sh +178 -0
- package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js +50 -4
- package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js.map +1 -1
- package/payload/platform/plugins/admin/skills/a4-print-documents/SKILL.md +12 -1
- package/payload/platform/plugins/admin/skills/a4-print-documents/pdf-inspect.mjs +113 -0
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +14 -0
- package/payload/platform/plugins/docs/references/admin-session.md +15 -0
- package/payload/platform/scripts/__tests__/mailbox-inject-registered.test.sh +19 -43
- package/payload/platform/scripts/__tests__/preference-hooks-registered.test.sh +3 -1
- package/payload/platform/scripts/__tests__/public-prompt-gate-registered.test.sh +22 -37
- package/payload/platform/scripts/__tests__/public-surface-registered.test.sh +12 -35
- package/payload/platform/scripts/__tests__/quote-ownership-contract.test.sh +86 -0
- package/payload/platform/scripts/lib/__tests__/account-settings-reconcile.test.sh +73 -0
- package/payload/platform/scripts/lib/account-settings-reconcile.sh +88 -0
- package/payload/platform/scripts/lib/provision-account-dir.sh +11 -144
- package/payload/platform/scripts/setup-account.sh +11 -53
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts +20 -0
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js +78 -1
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.d.ts +129 -0
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.js +344 -0
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/index.js +107 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.d.ts +42 -0
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js +215 -0
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.d.ts +108 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.js +299 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.js.map +1 -0
- package/payload/platform/templates/account-settings.json +159 -0
- package/payload/server/server.js +750 -656
- package/payload/platform/scripts/lib/__tests__/account-settings-askgate.test.sh +0 -144
- package/payload/platform/scripts/lib/__tests__/account-settings-mailbox-inject.test.sh +0 -166
- package/payload/platform/scripts/lib/__tests__/account-settings-pdf-conformance.test.sh +0 -151
- package/payload/platform/scripts/lib/__tests__/account-settings-public-surface.test.sh +0 -109
- package/payload/platform/scripts/lib/account-settings-askgate.sh +0 -98
- package/payload/platform/scripts/lib/account-settings-mailbox-inject.sh +0 -91
- package/payload/platform/scripts/lib/account-settings-pdf-conformance.sh +0 -98
- package/payload/platform/scripts/lib/account-settings-public-surface.sh +0 -109
|
@@ -70,151 +70,18 @@ provision_account_dir() {
|
|
|
70
70
|
[ -d "$ACCOUNT_DIR/.git" ] || git init -q "$ACCOUNT_DIR"
|
|
71
71
|
|
|
72
72
|
# --- project-level .claude/settings.json (hooks; no allowlist) -------------
|
|
73
|
+
# The hook set is data, not a heredoc: platform/templates/account-settings.json
|
|
74
|
+
# is copied verbatim (every $PLATFORM_ROOT in it is a literal Claude Code
|
|
75
|
+
# resolves at hook-run time, so no substitution is needed). Keeping it as a
|
|
76
|
+
# file is what lets account-settings-reconcile.sh converge accounts that
|
|
77
|
+
# already exist, which this writer alone never could — it runs at provision
|
|
78
|
+
# time, and the upgrade path re-provisions the house account and no other.
|
|
73
79
|
local ACCOUNT_SETTINGS="$ACCOUNT_DIR/.claude/settings.json"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"allow": [],
|
|
80
|
-
"deny": []
|
|
81
|
-
},
|
|
82
|
-
"hooks": {
|
|
83
|
-
"PreToolUse": [
|
|
84
|
-
{
|
|
85
|
-
"matcher": "Write",
|
|
86
|
-
"hooks": [
|
|
87
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
|
|
88
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard.sh" }
|
|
89
|
-
]
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"matcher": "Edit",
|
|
93
|
-
"hooks": [
|
|
94
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
|
|
95
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard.sh" }
|
|
96
|
-
]
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"matcher": "NotebookEdit",
|
|
100
|
-
"hooks": [
|
|
101
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
|
|
102
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard.sh" }
|
|
103
|
-
]
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
"matcher": "Bash",
|
|
107
|
-
"hooks": [
|
|
108
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
|
|
109
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard-bash-pre.sh" },
|
|
110
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/quote-engine-gate.sh" }
|
|
111
|
-
]
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
"hooks": [
|
|
115
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
|
|
116
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/public-tool-surface.sh" }
|
|
117
|
-
]
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
"matcher": "WebFetch",
|
|
121
|
-
"hooks": [
|
|
122
|
-
{ "type": "command", "command": "node $HOOKS_PATH/webfetch-preflight.mjs" }
|
|
123
|
-
]
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
"matcher": "AskUserQuestion",
|
|
127
|
-
"hooks": [
|
|
128
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/askuserquestion-investigate-gate.sh" },
|
|
129
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/askuserquestion-channel-carrier-gate.sh" }
|
|
130
|
-
]
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
"matcher": "mcp__plugin_browser_browser__browser-pdf-save",
|
|
134
|
-
"hooks": [
|
|
135
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/quote-render-gate.sh" }
|
|
136
|
-
]
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
"matcher": "mcp__plugin_browser_browser__browser-pdf-save",
|
|
140
|
-
"hooks": [
|
|
141
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/preference-consult-gate.sh" }
|
|
142
|
-
]
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
"matcher": "mcp__plugin_email_email__email-send|mcp__plugin_email_email__email-reply|mcp__plugin_email_email__email-draft-send|mcp__plugin_outlook_outlook__outlook-mail-send|mcp__plugin_outlook_outlook__outlook-mail-reply|mcp__plugin_outlook_outlook__outlook-draft-send|SendUserFile",
|
|
146
|
-
"hooks": [
|
|
147
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/preference-consult-gate.sh" }
|
|
148
|
-
]
|
|
149
|
-
}
|
|
150
|
-
],
|
|
151
|
-
"PostToolUse": [
|
|
152
|
-
{
|
|
153
|
-
"matcher": "Bash",
|
|
154
|
-
"hooks": [
|
|
155
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard-bash-post.sh" }
|
|
156
|
-
]
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
"matcher": "Agent",
|
|
160
|
-
"hooks": [
|
|
161
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/post-tool-use-agent.sh" }
|
|
162
|
-
]
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
"matcher": "mcp__plugin_browser_browser__browser-pdf-save",
|
|
166
|
-
"hooks": [
|
|
167
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/quote-render-pdf-conformance.sh" }
|
|
168
|
-
]
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"matcher": "mcp__.*__.*-(export|import)-parse$",
|
|
172
|
-
"hooks": [
|
|
173
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
|
|
174
|
-
]
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
"matcher": "mcp__.*",
|
|
178
|
-
"hooks": [
|
|
179
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/mcp-tool-missing.sh" }
|
|
180
|
-
]
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
"matcher": "Write",
|
|
184
|
-
"hooks": [
|
|
185
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/admin-authoring-observer.sh" }
|
|
186
|
-
]
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
"matcher": "Edit",
|
|
190
|
-
"hooks": [
|
|
191
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/admin-authoring-observer.sh" }
|
|
192
|
-
]
|
|
193
|
-
}
|
|
194
|
-
],
|
|
195
|
-
"UserPromptSubmit": [
|
|
196
|
-
{
|
|
197
|
-
"hooks": [
|
|
198
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
|
|
199
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/prompt-optimiser-directive.sh" },
|
|
200
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/datetime-inject.sh" },
|
|
201
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/mailbox-inject.sh" },
|
|
202
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/preference-consult-directive.sh" },
|
|
203
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/public-tool-surface.sh" }
|
|
204
|
-
]
|
|
205
|
-
}
|
|
206
|
-
],
|
|
207
|
-
"Stop": [
|
|
208
|
-
{
|
|
209
|
-
"hooks": [
|
|
210
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/prompt-optimiser-compliance.sh" },
|
|
211
|
-
{ "type": "command", "command": "bash $HOOKS_PATH/public-tool-surface.sh" }
|
|
212
|
-
]
|
|
213
|
-
}
|
|
214
|
-
]
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
SETTINGS_EOF
|
|
80
|
+
if [ -f "$TEMPLATES_DIR/account-settings.json" ]; then
|
|
81
|
+
cp "$TEMPLATES_DIR/account-settings.json" "$ACCOUNT_SETTINGS"
|
|
82
|
+
else
|
|
83
|
+
echo " [acct-settings] WARNING: template missing at $TEMPLATES_DIR/account-settings.json — settings.json not written" >&2
|
|
84
|
+
fi
|
|
218
85
|
|
|
219
86
|
# --- agent identities + specialist plugin templates ------------------------
|
|
220
87
|
cp "$TEMPLATES_DIR/agents/admin/IDENTITY.md" "$ACCOUNT_DIR/agents/admin/IDENTITY.md"
|
|
@@ -34,14 +34,6 @@ ACCOUNTS_DIR="$INSTALL_DIR/data/accounts"
|
|
|
34
34
|
. "$SCRIPT_DIR/lib/resolve-account-dir.sh"
|
|
35
35
|
# shellcheck source=lib/provision-account-dir.sh
|
|
36
36
|
. "$SCRIPT_DIR/lib/provision-account-dir.sh"
|
|
37
|
-
# shellcheck source=lib/account-settings-askgate.sh
|
|
38
|
-
. "$SCRIPT_DIR/lib/account-settings-askgate.sh"
|
|
39
|
-
# shellcheck source=lib/account-settings-pdf-conformance.sh
|
|
40
|
-
. "$SCRIPT_DIR/lib/account-settings-pdf-conformance.sh"
|
|
41
|
-
# shellcheck source=lib/account-settings-mailbox-inject.sh
|
|
42
|
-
. "$SCRIPT_DIR/lib/account-settings-mailbox-inject.sh"
|
|
43
|
-
# shellcheck source=lib/account-settings-public-surface.sh
|
|
44
|
-
. "$SCRIPT_DIR/lib/account-settings-public-surface.sh"
|
|
45
37
|
# shellcheck source=lib/read-brand-json.sh
|
|
46
38
|
. "$SCRIPT_DIR/lib/read-brand-json.sh"
|
|
47
39
|
# Resolve brand-aware persistent users.json path before the resolver runs.
|
|
@@ -73,49 +65,15 @@ provision_account_dir "$ACCOUNT_DIR" "$ACCOUNT_ID" "house"
|
|
|
73
65
|
reconcile_all_accounts_owned_dirs "$ACCOUNTS_DIR"
|
|
74
66
|
|
|
75
67
|
# ------------------------------------------------------------------
|
|
76
|
-
# 4.
|
|
68
|
+
# 4. Converge the whole hook set on every account
|
|
77
69
|
# ------------------------------------------------------------------
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# 5. Retrofit the quote-render PDF-conformance matcher onto every account
|
|
89
|
-
# ------------------------------------------------------------------
|
|
90
|
-
# Standing check + durable backfill (Task 1929): provision_account_dir writes the
|
|
91
|
-
# PostToolUse browser-pdf-save matcher (quote-render-pdf-conformance.sh) only at
|
|
92
|
-
# provision time, and this script re-provisions only the house account. An
|
|
93
|
-
# account created before Task 1922 keeps a settings.json without the matcher and
|
|
94
|
-
# never runs the PDF gate. Reconcile every account on every install so the gate
|
|
95
|
-
# reaches pre-1922 accounts. Idempotent; logs one [backfill-1929] line per account.
|
|
96
|
-
reconcile_all_accounts_pdf_conformance "$ACCOUNTS_DIR"
|
|
97
|
-
|
|
98
|
-
# ------------------------------------------------------------------
|
|
99
|
-
# 6. Retrofit the per-turn <mailboxes> injection hook onto every account
|
|
100
|
-
# ------------------------------------------------------------------
|
|
101
|
-
# Standing check + durable backfill (Task 2157): provision_account_dir writes the
|
|
102
|
-
# UserPromptSubmit array only at provision time, and this script re-provisions
|
|
103
|
-
# only the house account. A client sub-account created by the account-lifecycle
|
|
104
|
-
# tool keeps a settings.json without mailbox-inject.sh and never gets the
|
|
105
|
-
# standing mailbox list, so its sessions go on learning attachment state by
|
|
106
|
-
# polling one mail plugin and reading that plugin's miss as an account-wide fact.
|
|
107
|
-
# Reconcile every account on every install. Idempotent; logs one [backfill-2157]
|
|
108
|
-
# line per account.
|
|
109
|
-
reconcile_all_accounts_mailbox_inject "$ACCOUNTS_DIR"
|
|
110
|
-
|
|
111
|
-
# ------------------------------------------------------------------
|
|
112
|
-
# 7. Retrofit the realised-public-tool-surface hook onto every account
|
|
113
|
-
# ------------------------------------------------------------------
|
|
114
|
-
# Standing check + durable backfill (Task 2339): provision_account_dir writes the
|
|
115
|
-
# matcher-less PreToolUse entry and the Stop entry only at provision time, and
|
|
116
|
-
# this script re-provisions only the house account. Without this, the hook that
|
|
117
|
-
# records what a public spawn's tools actually did would reach house accounts
|
|
118
|
-
# only — including not reaching the account where five tools were seen running
|
|
119
|
-
# under a one-tool allowlist. Reconcile every account on every install.
|
|
120
|
-
# Idempotent; logs one [backfill-2339] line per account.
|
|
121
|
-
reconcile_all_accounts_public_surface "$ACCOUNTS_DIR"
|
|
70
|
+
# provision_account_dir writes the full hook set, but only at provision time,
|
|
71
|
+
# and this script re-provisions the house account and no other — so an account
|
|
72
|
+
# created before a hook landed would run a stale set indefinitely. This step
|
|
73
|
+
# converges each account's settings against the shipped template instead, and
|
|
74
|
+
# states the divergence count on every run including zero. It is the single
|
|
75
|
+
# writer of account settings: a hook added to
|
|
76
|
+
# platform/templates/account-settings.json needs no backfill of its own.
|
|
77
|
+
# (Task 2475 retired the four one-hook backfill libs this replaced.)
|
|
78
|
+
. "$SCRIPT_DIR/lib/account-settings-reconcile.sh"
|
|
79
|
+
reconcile_all_accounts_settings "$ACCOUNTS_DIR"
|
|
@@ -10,6 +10,26 @@
|
|
|
10
10
|
* into `op=account-agent-registry error`. Exported for its own unit test: the
|
|
11
11
|
* propagation half cannot be provoked through the filesystem from outside. */
|
|
12
12
|
export declare function ignoringRaceWith(code: 'EEXIST' | 'ENOENT', act: () => void): void;
|
|
13
|
+
/** What the CLI will be able to dispatch from the registry we just wrote.
|
|
14
|
+
*
|
|
15
|
+
* Task 2469 — the mirror is keyed on filename and dispatch is keyed on the
|
|
16
|
+
* frontmatter `name`, so `synced=<N>` cannot answer "can this be reached?".
|
|
17
|
+
* A card with no name, and two cards claiming one name, both mirror cleanly
|
|
18
|
+
* and neither dispatches; a specialist that is never dispatched never fails,
|
|
19
|
+
* so no transition log anywhere carries it. Only a state reconcile sees it.
|
|
20
|
+
*
|
|
21
|
+
* Measured over the registry rather than the source directory, because the
|
|
22
|
+
* registry is the directory the CLI reads: where an operator's own regular
|
|
23
|
+
* file sits at a card's name, that file is what resolves, and it is that file
|
|
24
|
+
* this must report on.
|
|
25
|
+
*
|
|
26
|
+
* Exported for its own unit test and for callers that want the state without
|
|
27
|
+
* re-running a sync. */
|
|
28
|
+
export declare function resolveRegistryNames(registryDir: string): {
|
|
29
|
+
resolvable: number;
|
|
30
|
+
unnamed: string[];
|
|
31
|
+
dupeNames: string[];
|
|
32
|
+
};
|
|
13
33
|
/** Mirror `<accountDir>/specialists/agents/*.md` into
|
|
14
34
|
* `<accountDir>/.claude/agents/` as symlinks, and remove every registry
|
|
15
35
|
* symlink the source no longer has. Emits exactly one line:
|
package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-agent-registry.d.ts","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;;+EAU+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,MAAM,IAAI,GAAG,IAAI,CAOjF;AAED;;;;+EAI+E;AAC/E,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"account-agent-registry.d.ts","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;;+EAU+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,MAAM,IAAI,GAAG,IAAI,CAOjF;AA6BD;;;;;;;;;;;;;;yBAcyB;AACzB,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG;IACzD,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB,CAsBA;AAED;;;;+EAI+E;AAC/E,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAgG9F"}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// It never throws. A registry that cannot be written is a specialist that
|
|
24
24
|
// cannot be dispatched, which is the state before this module existed; a spawn
|
|
25
25
|
// that dies instead is strictly worse.
|
|
26
|
-
import { existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, symlinkSync, unlinkSync } from 'node:fs';
|
|
26
|
+
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, symlinkSync, unlinkSync } from 'node:fs';
|
|
27
27
|
import { dirname, join, resolve } from 'node:path';
|
|
28
28
|
/** Two spawns in the same account sync concurrently — an admin session and a
|
|
29
29
|
* channel session are routine — and they write identical content. Whoever
|
|
@@ -46,6 +46,72 @@ export function ignoringRaceWith(code, act) {
|
|
|
46
46
|
throw err;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
/** The `name:` value from a card's frontmatter, or null. CRLF-tolerant and
|
|
50
|
+
* quote-stripping, matching the reader in `specialist-roster.ts` and the one
|
|
51
|
+
* in the roster census, so every surface agrees on what a card is called. A
|
|
52
|
+
* card that cannot be read — a dangling link, a directory at a `.md` path,
|
|
53
|
+
* EACCES — yields null rather than throwing, because "we could not tell" and
|
|
54
|
+
* "it does not resolve" are the same answer to the dispatcher. */
|
|
55
|
+
function readFrontmatterName(file) {
|
|
56
|
+
let raw;
|
|
57
|
+
try {
|
|
58
|
+
raw = readFileSync(file, 'utf8');
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
64
|
+
if (!fm)
|
|
65
|
+
return null;
|
|
66
|
+
const m = fm[1].match(/^name:\s*(.*?)\r?$/m);
|
|
67
|
+
if (!m)
|
|
68
|
+
return null;
|
|
69
|
+
let value = m[1].trim();
|
|
70
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
71
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
72
|
+
value = value.slice(1, -1);
|
|
73
|
+
}
|
|
74
|
+
return value || null;
|
|
75
|
+
}
|
|
76
|
+
/** What the CLI will be able to dispatch from the registry we just wrote.
|
|
77
|
+
*
|
|
78
|
+
* Task 2469 — the mirror is keyed on filename and dispatch is keyed on the
|
|
79
|
+
* frontmatter `name`, so `synced=<N>` cannot answer "can this be reached?".
|
|
80
|
+
* A card with no name, and two cards claiming one name, both mirror cleanly
|
|
81
|
+
* and neither dispatches; a specialist that is never dispatched never fails,
|
|
82
|
+
* so no transition log anywhere carries it. Only a state reconcile sees it.
|
|
83
|
+
*
|
|
84
|
+
* Measured over the registry rather than the source directory, because the
|
|
85
|
+
* registry is the directory the CLI reads: where an operator's own regular
|
|
86
|
+
* file sits at a card's name, that file is what resolves, and it is that file
|
|
87
|
+
* this must report on.
|
|
88
|
+
*
|
|
89
|
+
* Exported for its own unit test and for callers that want the state without
|
|
90
|
+
* re-running a sync. */
|
|
91
|
+
export function resolveRegistryNames(registryDir) {
|
|
92
|
+
let entries;
|
|
93
|
+
try {
|
|
94
|
+
entries = readdirSync(registryDir).filter((n) => n.endsWith('.md')).sort();
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return { resolvable: 0, unnamed: [], dupeNames: [] };
|
|
98
|
+
}
|
|
99
|
+
const claims = new Map();
|
|
100
|
+
const unnamed = [];
|
|
101
|
+
for (const file of entries) {
|
|
102
|
+
const name = readFrontmatterName(join(registryDir, file));
|
|
103
|
+
if (name === null) {
|
|
104
|
+
unnamed.push(file);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
claims.set(name, (claims.get(name) ?? 0) + 1);
|
|
108
|
+
}
|
|
109
|
+
const dupeNames = Array.from(claims.entries())
|
|
110
|
+
.filter(([, n]) => n > 1)
|
|
111
|
+
.map(([name]) => name)
|
|
112
|
+
.sort();
|
|
113
|
+
return { resolvable: claims.size, unnamed, dupeNames };
|
|
114
|
+
}
|
|
49
115
|
/** Mirror `<accountDir>/specialists/agents/*.md` into
|
|
50
116
|
* `<accountDir>/.claude/agents/` as symlinks, and remove every registry
|
|
51
117
|
* symlink the source no longer has. Emits exactly one line:
|
|
@@ -138,6 +204,17 @@ export function syncAccountAgentRegistry(accountDir, log) {
|
|
|
138
204
|
pruned++;
|
|
139
205
|
}
|
|
140
206
|
log(`op=account-agent-registry synced=${synced} pruned=${pruned} collisions=${collisions.join(',')}`);
|
|
207
|
+
// Task 2469 — a second line, not three more fields on the first. That one
|
|
208
|
+
// is a transition record: what this spawn changed. This is a state
|
|
209
|
+
// reconcile: what is reachable now. Emitted every spawn including zero, so
|
|
210
|
+
// an account with no specialists is distinguishable from a reconcile that
|
|
211
|
+
// did not run. On the error path below it is deliberately absent — after a
|
|
212
|
+
// failed sync the reachable set is unknown, and reporting zero would assert
|
|
213
|
+
// something this never measured.
|
|
214
|
+
const resolution = resolveRegistryNames(registryDir);
|
|
215
|
+
log(`op=agent-registry-resolution resolvable=${resolution.resolvable}` +
|
|
216
|
+
` unnamed=${resolution.unnamed.join(',')}` +
|
|
217
|
+
` dupeNames=${resolution.dupeNames.join(',')}`);
|
|
141
218
|
}
|
|
142
219
|
catch (err) {
|
|
143
220
|
log(`op=account-agent-registry error reason=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-agent-registry.js","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,0EAA0E;AAC1E,uEAAuE;AACvE,gFAAgF;AAChF,0EAA0E;AAC1E,6EAA6E;AAC7E,EAAE;AACF,+DAA+D;AAC/D,6EAA6E;AAC7E,gFAAgF;AAChF,sDAAsD;AACtD,EAAE;AACF,gFAAgF;AAChF,sEAAsE;AACtE,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,uDAAuD;AACvD,EAAE;AACF,0EAA0E;AAC1E,+EAA+E;AAC/E,uCAAuC;AAEvC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"account-agent-registry.js","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Logger } from './types.js';
|
|
2
|
+
export declare const TAG = "[blocked-tool]";
|
|
3
|
+
export interface ToolUseRecord {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
/** One transcript's scan result. `agentId` is `—` for the session's own
|
|
8
|
+
* transcript and `agent-<id>` for a subagent's — the field that distinguishes
|
|
9
|
+
* a card the operator CAN see in the session UI from one they cannot. */
|
|
10
|
+
export interface TranscriptScan {
|
|
11
|
+
agentId: string;
|
|
12
|
+
path: string;
|
|
13
|
+
mtimeMs: number;
|
|
14
|
+
unmatched: ToolUseRecord[];
|
|
15
|
+
}
|
|
16
|
+
export interface BlockedCall {
|
|
17
|
+
sessionId: string;
|
|
18
|
+
agentId: string;
|
|
19
|
+
toolUseId: string;
|
|
20
|
+
tool: string;
|
|
21
|
+
blockedForMs: number;
|
|
22
|
+
}
|
|
23
|
+
export interface BlockedCensusSnapshot {
|
|
24
|
+
/** Transcripts read this tick, across every live session. */
|
|
25
|
+
scanned: number;
|
|
26
|
+
blocked: BlockedCall[];
|
|
27
|
+
/** The session ids that were live this tick. A previously-blocked call whose
|
|
28
|
+
* session is no longer here did not resolve — the session went away — and
|
|
29
|
+
* reporting that as `op=cleared` would tell the operator the block lifted. */
|
|
30
|
+
liveSessionIds: string[];
|
|
31
|
+
}
|
|
32
|
+
/** PURE. Every `tool_use` id in these lines with no matching `tool_result`.
|
|
33
|
+
* Order is first-sighting order. Malformed lines are skipped, not thrown on:
|
|
34
|
+
* a JSONL read can land mid-append. A `tool_use` carrying no `name` is
|
|
35
|
+
* reported as `unknown` rather than dropped — an unnamed blocked call is
|
|
36
|
+
* still a blocked call. */
|
|
37
|
+
export declare function unmatchedToolUses(lines: readonly string[]): ToolUseRecord[];
|
|
38
|
+
/** PURE. Which unmatched calls are blocked. Blocked means unmatched AND the
|
|
39
|
+
* transcript has not advanced for `staleMs`. Without the staleness term every
|
|
40
|
+
* in-flight call would be reported, which would make the signal useless. */
|
|
41
|
+
export declare function blockedFromScans(sessionId: string, scans: readonly TranscriptScan[], nowMs: number, staleMs: number): BlockedCall[];
|
|
42
|
+
/** PURE. Emitted every tick INCLUDING zero, so a census that stopped ticking is
|
|
43
|
+
* distinguishable from one that found nothing. `sessions` is separate from
|
|
44
|
+
* `scanned` on purpose: `sessions=3 scanned=0` is a census that could not
|
|
45
|
+
* resolve a transcript for any live session, which without the first field
|
|
46
|
+
* reads exactly like a quiet box. */
|
|
47
|
+
export declare function formatBlockedCensus(s: BlockedCensusSnapshot): string;
|
|
48
|
+
/** PURE. */
|
|
49
|
+
export declare function formatBlocked(c: BlockedCall): string;
|
|
50
|
+
/** PURE. Same ids as its `op=blocked` twin, so the pair is greppable. Emitted
|
|
51
|
+
* ONLY when the session is still live and the result landed. */
|
|
52
|
+
export declare function formatCleared(c: BlockedCall): string;
|
|
53
|
+
/** PURE. The other way a blocked call leaves the reported set: its session
|
|
54
|
+
* stopped being live. The call did NOT resolve, and saying `op=cleared` here
|
|
55
|
+
* would tell the operator the block lifted when the session actually went
|
|
56
|
+
* away with the card still unanswered. */
|
|
57
|
+
export declare function formatSessionGone(c: BlockedCall): string;
|
|
58
|
+
export declare const DEFAULT_STALE_MS = 120000;
|
|
59
|
+
export declare const DEFAULT_NOTIFY_AFTER_MS = 180000;
|
|
60
|
+
/** A `tool_result` always follows its `tool_use` in the same file, so a
|
|
61
|
+
* contiguous tail containing the use contains its result too — unless one
|
|
62
|
+
* result exceeds this window, in which case that one call reads as unmatched.
|
|
63
|
+
* 1 MB is a chosen bound, not a measured one; the failure mode it admits is a
|
|
64
|
+
* false `op=blocked` on a call whose result was larger than the window. */
|
|
65
|
+
export declare const TAIL_BYTES: number;
|
|
66
|
+
export interface BlockedCensusIo {
|
|
67
|
+
listSessionIds(): string[];
|
|
68
|
+
/** The session's own transcript (`agentId: '—'`) followed by every
|
|
69
|
+
* `<sessionId>/subagents/agent-*.jsonl`. */
|
|
70
|
+
listTranscripts(sessionId: string): Array<{
|
|
71
|
+
agentId: string;
|
|
72
|
+
path: string;
|
|
73
|
+
}>;
|
|
74
|
+
/** Last `maxBytes` of the file split into lines, plus its mtime. Null when
|
|
75
|
+
* the file cannot be read. The first line is dropped when the read started
|
|
76
|
+
* mid-record. */
|
|
77
|
+
readTail(path: string, maxBytes: number): {
|
|
78
|
+
lines: string[];
|
|
79
|
+
mtimeMs: number;
|
|
80
|
+
} | null;
|
|
81
|
+
now(): number;
|
|
82
|
+
}
|
|
83
|
+
/** IMPURE. `scanned` counts transcripts actually READ, so a session whose
|
|
84
|
+
* files vanished does not inflate the count into looking like coverage. */
|
|
85
|
+
export declare function collectBlockedCensus(io: BlockedCensusIo, staleMs: number, tailBytes: number): BlockedCensusSnapshot;
|
|
86
|
+
/** `claudeConfigDir` is the state root (`CLAUDE_CONFIG_DIR`), NOT a spawn cwd.
|
|
87
|
+
* Task 1490 re-points the manager's `spawnCwd` per sub-account spawn, so a
|
|
88
|
+
* client session's transcript is filed under a slug derived from the
|
|
89
|
+
* sub-account directory rather than the house cwd (http-server.ts:815 states
|
|
90
|
+
* this: reading `deps.spawnCwd` "would always miss the file"). Keying this
|
|
91
|
+
* census on one cwd would make it blind to exactly the sub-account sessions it
|
|
92
|
+
* was written for, so it resolves each session through the all-slug scan
|
|
93
|
+
* instead. */
|
|
94
|
+
export declare function defaultBlockedCensusIo(claudeConfigDir: string): BlockedCensusIo;
|
|
95
|
+
export interface BlockedToolCensusDeps {
|
|
96
|
+
/** State root (`CLAUDE_CONFIG_DIR`), not a spawn cwd. See
|
|
97
|
+
* defaultBlockedCensusIo for why a cwd cannot be used here. */
|
|
98
|
+
claudeConfigDir: string;
|
|
99
|
+
intervalMs: number;
|
|
100
|
+
staleMs?: number;
|
|
101
|
+
notifyAfterMs?: number;
|
|
102
|
+
logger: Logger;
|
|
103
|
+
/** Injected in tests; production uses defaultBlockedCensusIo(claudeConfigDir). */
|
|
104
|
+
io?: BlockedCensusIo;
|
|
105
|
+
/** The loopback POST to the UI's notification route. Absent means log-only. */
|
|
106
|
+
notify?: (c: BlockedCall) => Promise<{
|
|
107
|
+
delivered: boolean;
|
|
108
|
+
channel: string;
|
|
109
|
+
}>;
|
|
110
|
+
}
|
|
111
|
+
export interface BlockedToolCensus {
|
|
112
|
+
tickOnce(): BlockedCensusSnapshot;
|
|
113
|
+
latest(): BlockedCensusSnapshot | null;
|
|
114
|
+
start(): void;
|
|
115
|
+
stop(): void;
|
|
116
|
+
}
|
|
117
|
+
export declare function createBlockedToolCensus(deps: BlockedToolCensusDeps): BlockedToolCensus;
|
|
118
|
+
/** Production notifier. POSTs to the brand UI's loopback route, the same
|
|
119
|
+
* transport `postLogLineViaFetch` uses. A throw or a non-200 resolves to
|
|
120
|
+
* `delivered:false` rather than rejecting: the census logs the outcome either
|
|
121
|
+
* way, and a send that failed silently is the blind spot this task closes. */
|
|
122
|
+
export declare function postBlockedNotifyViaFetch(opts: {
|
|
123
|
+
uiPort: string;
|
|
124
|
+
logger: Logger;
|
|
125
|
+
}): (c: BlockedCall) => Promise<{
|
|
126
|
+
delivered: boolean;
|
|
127
|
+
channel: string;
|
|
128
|
+
}>;
|
|
129
|
+
//# sourceMappingURL=blocked-tool-census.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocked-tool-census.d.ts","sourceRoot":"","sources":["../src/blocked-tool-census.ts"],"names":[],"mappings":"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"}
|