@erclx/aitk 3.45.0 → 3.47.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/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/claude-orchestrate/REQUIREMENT.md +3 -1
- package/claude/skills/claude-orchestrate/references/orchestrator-dispatch.md +18 -2
- package/claude/skills/claude-teach/REQUIREMENT.md +3 -0
- package/claude/skills/claude-teach/SKILL.md +18 -1
- package/claude/skills/claude-worker/SKILL.md +41 -4
- package/docs/agents/commands.md +9 -0
- package/docs/agents/counts.md +1 -1
- package/docs/agents/index.md +1 -1
- package/docs/agents/sessions.md +27 -2
- package/docs/agents/teach.md +12 -0
- package/governance/rules/claude/561-teach.md +1 -1
- package/governance/rules/ui/400-ui.md +1 -0
- package/governance/rules/ui/410-a11y.md +2 -0
- package/governance/rules/ui/420-forms.md +1 -0
- package/governance/rules/ui/430-ux-completeness.md +2 -0
- package/governance/rules/ui/440-surface-capture.md +13 -5
- package/package.json +1 -1
- package/src/cli.ts +4 -0
- package/src/commands/serve.ts +159 -0
- package/src/commands/sessions.ts +83 -6
- package/src/process/harness.ts +167 -0
- package/src/serve/static.ts +322 -0
- package/src/sessions/resolve.ts +103 -0
package/src/sessions/resolve.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { basename } from 'node:path'
|
|
1
2
|
import { $ } from 'bun'
|
|
2
3
|
import { gitEnv } from '@/git-env'
|
|
3
4
|
import {
|
|
@@ -186,3 +187,105 @@ export async function resolveSessions(
|
|
|
186
187
|
|
|
187
188
|
return { kind: 'resolved', dir: registry.dir, confidence, sessions }
|
|
188
189
|
}
|
|
190
|
+
|
|
191
|
+
/** The environment slice the caller's own identity is read from. */
|
|
192
|
+
export type Env = Record<string, string | undefined>
|
|
193
|
+
|
|
194
|
+
/** Why the caller's own row could not be named, rather than an empty result. */
|
|
195
|
+
export type SelfUnresolved = 'no-identity' | 'no-row'
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* What the environment offers about the session making the call.
|
|
199
|
+
*
|
|
200
|
+
* Both fields are candidates rather than a pair, since a client sets them
|
|
201
|
+
* independently and a caller can arrive carrying either one alone.
|
|
202
|
+
*/
|
|
203
|
+
export interface SelfIdentity {
|
|
204
|
+
readonly sessionId: string | null
|
|
205
|
+
readonly pid: number | null
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export type SelfReport =
|
|
209
|
+
| { readonly kind: 'self'; readonly session: ResolvedSession }
|
|
210
|
+
| {
|
|
211
|
+
readonly kind: 'unresolved'
|
|
212
|
+
readonly reason: SelfUnresolved
|
|
213
|
+
readonly identity: SelfIdentity
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* A positive integer, which is what separates a pid from a socket named for
|
|
218
|
+
* something else. Signal zero addresses the caller's own process group, so a
|
|
219
|
+
* zero would match a row rather than failing to.
|
|
220
|
+
*/
|
|
221
|
+
function pidOf(value: string | undefined): number | null {
|
|
222
|
+
if (value === undefined) return null
|
|
223
|
+
const pid = Number(value.trim())
|
|
224
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Reads whatever the environment states about the calling session.
|
|
229
|
+
*
|
|
230
|
+
* Three identifier namespaces are in play and only two of them join to a
|
|
231
|
+
* roster row. `CLAUDE_CODE_SESSION_ID` is the roster's own `sessionId` and is
|
|
232
|
+
* read first because it survives a rename, where the name a session carries is
|
|
233
|
+
* derived from what it turned out to be doing and rotates while a build runs.
|
|
234
|
+
* `CLAUDE_CODE_HOST_SESSION_ID` is deliberately never read: it holds a
|
|
235
|
+
* `local_`-prefixed value from the harness namespace that matches no row, and
|
|
236
|
+
* it is the variable a reader searching the environment for a session id finds
|
|
237
|
+
* first.
|
|
238
|
+
*
|
|
239
|
+
* The socket path is the last rung because its basename is the caller's pid by
|
|
240
|
+
* a client convention rather than a published interface, so a client that
|
|
241
|
+
* moves it drops this rung while leaving the two above it standing.
|
|
242
|
+
*/
|
|
243
|
+
export function callerIdentity(env: Env = process.env): SelfIdentity {
|
|
244
|
+
const stated = env.CLAUDE_CODE_SESSION_ID?.trim()
|
|
245
|
+
const socket = env.CLAUDE_CODE_MESSAGING_SOCKET
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
sessionId: stated !== undefined && stated.length > 0 ? stated : null,
|
|
249
|
+
pid:
|
|
250
|
+
pidOf(env.CLAUDE_PID) ??
|
|
251
|
+
pidOf(
|
|
252
|
+
socket === undefined
|
|
253
|
+
? undefined
|
|
254
|
+
: basename(socket).replace(/\.sock$/, ''),
|
|
255
|
+
),
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Names which row of a roster belongs to the caller.
|
|
261
|
+
*
|
|
262
|
+
* The read that already returns every field marks none of them as the caller,
|
|
263
|
+
* so this performs the join rather than adding a source. An identity the
|
|
264
|
+
* environment does not carry and an identity no row matches are separated,
|
|
265
|
+
* because the first is a client that states nothing and the second is a
|
|
266
|
+
* session the roster cannot see. A session driving from Remote Control is the
|
|
267
|
+
* measured instance of the second: it is addressable on the message channel
|
|
268
|
+
* and holds no local process record for the roster to report.
|
|
269
|
+
*/
|
|
270
|
+
export function selfOf(
|
|
271
|
+
sessions: readonly ResolvedSession[],
|
|
272
|
+
identity: SelfIdentity,
|
|
273
|
+
): SelfReport {
|
|
274
|
+
if (identity.sessionId === null && identity.pid === null) {
|
|
275
|
+
return { kind: 'unresolved', reason: 'no-identity', identity }
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const byId =
|
|
279
|
+
identity.sessionId === null
|
|
280
|
+
? undefined
|
|
281
|
+
: sessions.find((session) => session.sessionId === identity.sessionId)
|
|
282
|
+
const byPid =
|
|
283
|
+
identity.pid === null
|
|
284
|
+
? undefined
|
|
285
|
+
: sessions.find((session) => session.pid === identity.pid)
|
|
286
|
+
const match = byId ?? byPid
|
|
287
|
+
|
|
288
|
+
return match === undefined
|
|
289
|
+
? { kind: 'unresolved', reason: 'no-row', identity }
|
|
290
|
+
: { kind: 'self', session: match }
|
|
291
|
+
}
|