@astrosheep/square 0.3.65 → 0.3.67
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-plugin/.claude-plugin/plugin.json +1 -1
- package/claude-plugin/hooks/register.js +29 -2
- package/claude-plugin/skills/square/SKILL.md +2 -0
- package/claude-plugin/types.d.ts +1 -0
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/automatic-session.js +13 -11
- package/dist/claude-delivery.js +3 -3
- package/dist/claude-mod.js +2 -2
- package/dist/harness-claude.js +2 -2
- package/dist/harness-links.js +3 -3
- package/dist/help.js +1 -1
- package/dist/mcp.js +24 -12
- package/dist/wake-eligibility.js +2 -1
- package/guides/claude-native.md +4 -4
- package/package.json +1 -1
- package/skills/square/SKILL.md +2 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Claude Code
|
|
1
|
+
// Claude Code mod. No Node imports, shell interpolation, or child credentials.
|
|
2
2
|
const hasToken = (text) => typeof text === 'string' && /(?:^|\n)\[square-inbox:[a-zA-Z0-9-]+\](?:\n|$)/.test(text);
|
|
3
3
|
|
|
4
4
|
async function coordinate($) {
|
|
@@ -55,6 +55,15 @@ async function cancel($) {
|
|
|
55
55
|
|
|
56
56
|
export function register(on) {
|
|
57
57
|
on('session.start', async ($, e, next) => {
|
|
58
|
+
// Claude refuses plugin tools in sessions started without built-in tools; the inbox must still reconcile.
|
|
59
|
+
try {
|
|
60
|
+
await $.tool.register({
|
|
61
|
+
name: 'square',
|
|
62
|
+
description: "Run the square CLI. args are exactly the words after `square` in the square skill's commands.",
|
|
63
|
+
inputSchema: { type: 'object', properties: { args: { type: 'array', items: { type: 'string' } }, stdin: { type: 'string' } }, required: ['args'] },
|
|
64
|
+
isDeferred: false,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) { await $.ui.log(`Square tool unavailable: ${error?.message ?? error}`); }
|
|
58
67
|
await reconcile($).catch(() => undefined);
|
|
59
68
|
return next(e);
|
|
60
69
|
});
|
|
@@ -63,7 +72,25 @@ export function register(on) {
|
|
|
63
72
|
return next(e);
|
|
64
73
|
});
|
|
65
74
|
on('tool.call', async ($, e, next) => {
|
|
66
|
-
try {
|
|
75
|
+
try {
|
|
76
|
+
if (e.tool !== 'mcp__square__square') return await next(e);
|
|
77
|
+
const sessionId = await $.session.id();
|
|
78
|
+
const cwd = await $.session.cwd();
|
|
79
|
+
// process.run has no signal option; it belongs to this cancellable dispatch.
|
|
80
|
+
next.signal.throwIfAborted();
|
|
81
|
+
const result = await $.process.run(['square', ...e.args], {
|
|
82
|
+
cwd, stdin: e.stdin,
|
|
83
|
+
env: { CLAUDE_CODE_SESSION_ID: sessionId, CLAUDE_CODE_CHILD_SESSION: e.agentId ? '1' : '' },
|
|
84
|
+
timeoutMs: 600_000,
|
|
85
|
+
});
|
|
86
|
+
let text = result.stdout;
|
|
87
|
+
if (result.stderr) text += `${text && !text.endsWith('\n') ? '\n' : ''}${result.stderr}`;
|
|
88
|
+
if (result.exitCode !== 0) {
|
|
89
|
+
text += `${text && !text.endsWith('\n') ? '\n' : ''}Exit code: ${result.exitCode}`;
|
|
90
|
+
return { deny: text };
|
|
91
|
+
}
|
|
92
|
+
return { result: text };
|
|
93
|
+
}
|
|
67
94
|
finally { if (!e.agentId) await reconcile($, undefined, 'reconcile').catch(() => undefined); }
|
|
68
95
|
});
|
|
69
96
|
on('turn.start', async ($, e, next) => {
|
|
@@ -6,6 +6,8 @@ allowed-tools: Bash(square *)
|
|
|
6
6
|
|
|
7
7
|
# Square
|
|
8
8
|
|
|
9
|
+
When a `square` tool is available, call it with the same arguments instead of the shell; pass any `-` body as `stdin`.
|
|
10
|
+
|
|
9
11
|
Don't treat Square as a public dumping ground. Speak here only when you genuinely think someone else needs to know; otherwise you are needlessly interrupting them.
|
|
10
12
|
|
|
11
13
|
A square is a physical place where participants catch up and express thoughts or actions. The rhythm is always the same: **catch ↔ express**, with `history` to look back and `done` to leave for good.
|
package/claude-plugin/types.d.ts
CHANGED
|
@@ -3,5 +3,6 @@ export type SquareInboxCoordinate = { sessionId: string; cwd: string; version: s
|
|
|
3
3
|
export type SquareInboxCancellation = { at: number; bindings?: SquareInboxBinding[] };
|
|
4
4
|
export type SquareInboxState = { coordinate: SquareInboxCoordinate; bindings?: SquareInboxBinding[] };
|
|
5
5
|
declare module 'claude-code' {
|
|
6
|
+
interface McpToolInputs { mcp__square__square: { args: string[]; stdin?: string } }
|
|
6
7
|
interface PluginState { square: { inbox: StateFamily<SquareInboxState>; cancelAt: StateFamily<SquareInboxCancellation> } }
|
|
7
8
|
}
|
|
@@ -109,25 +109,27 @@ export async function automaticSessionEnd(provider, sessionId, cwd, env = proces
|
|
|
109
109
|
const scopedEnv = operationEnv(provider, sessionId, env);
|
|
110
110
|
const hostLedger = hostLedgerForEnv(scopedEnv);
|
|
111
111
|
const probe = await openSquare(squarePath, { hostLedger, env: scopedEnv });
|
|
112
|
-
const
|
|
112
|
+
const bindings = await projectSessionBindings({
|
|
113
113
|
hostLedger,
|
|
114
114
|
sessionId,
|
|
115
115
|
location: probe.location,
|
|
116
|
-
})
|
|
117
|
-
const expectedEpoch = binding === undefined
|
|
118
|
-
? undefined
|
|
119
|
-
: (await readParticipantOwner(squarePath, binding.participant, hostLedger))?.epoch;
|
|
116
|
+
});
|
|
120
117
|
await closeOpenSquare(probe);
|
|
121
118
|
const square = await Square.at({ path: squarePath, hostLedger, env: scopedEnv });
|
|
122
119
|
try {
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
|
|
120
|
+
// A harness session may own several names in the same square, so every binding is
|
|
121
|
+
// ended, not just the first. Each ended owner's done, routes, and presence settle
|
|
122
|
+
// inside the ownership claim lock, fenced by its own epoch. A same-session rejoin or
|
|
123
|
+
// takeover that lands afterwards claims only after that cleanup, so this call never
|
|
124
|
+
// performs post-return ledger or route cleanup that could remove the replacement
|
|
125
|
+
// owner's fresh rows.
|
|
126
|
+
if (bindings.length === 0)
|
|
128
127
|
await square.retireEndedSessionRoutes(sessionId);
|
|
129
128
|
else
|
|
130
|
-
|
|
129
|
+
for (const binding of bindings) {
|
|
130
|
+
const expectedEpoch = (await readParticipantOwner(squarePath, binding.participant, hostLedger))?.epoch;
|
|
131
|
+
await square.endOwnedSession(binding.participant, sessionId, expectedEpoch);
|
|
132
|
+
}
|
|
131
133
|
}
|
|
132
134
|
finally {
|
|
133
135
|
await square.close();
|
package/dist/claude-delivery.js
CHANGED
|
@@ -10,7 +10,7 @@ import { DeliveryError, connect } from './packages/agent-delivery/src/index.js';
|
|
|
10
10
|
const marker = /(?:^|\n)\[square-inbox:([a-zA-Z0-9-]+)\](?:\n|$)/g;
|
|
11
11
|
export function nativeTokens(text) { return [...text.matchAll(marker)].map((match) => match[1]); }
|
|
12
12
|
export function nativePayload(token, preview) { return `[square-inbox:${token}]\n${preview}\n[/square-inbox:${token}]`; }
|
|
13
|
-
function nativeSupported(route) { return route.address.
|
|
13
|
+
function nativeSupported(route) { return route.address.loaded === 'true' && !!route.address.endpoint; }
|
|
14
14
|
/**
|
|
15
15
|
* The shared entry owns platform policy, token resolution and frame shape; Square
|
|
16
16
|
* owns the payload, the correlation and the evidence. A local write is never proof
|
|
@@ -33,7 +33,7 @@ export function createClaudeWakeTransport(hostLedger, env = process.env) {
|
|
|
33
33
|
return {
|
|
34
34
|
async probe(route) {
|
|
35
35
|
if (!nativeSupported(route))
|
|
36
|
-
return { outcome: 'not-capable', diagnostic: 'Claude native inbox unavailable:
|
|
36
|
+
return { outcome: 'not-capable', diagnostic: 'Claude native inbox unavailable: a loaded interactive Square mod is required.' };
|
|
37
37
|
try {
|
|
38
38
|
return (await stat(route.address.endpoint)).isSocket() || { outcome: 'not-capable', diagnostic: 'Claude native inbox endpoint is not a socket.' };
|
|
39
39
|
}
|
|
@@ -69,7 +69,7 @@ async function dispatchClaude(request, hostLedger, timeoutMs, beforeSend, env =
|
|
|
69
69
|
request = { ...request, location: await canonicalPath(request.location) };
|
|
70
70
|
const signal = AbortSignal.timeout(timeoutMs);
|
|
71
71
|
if (!nativeSupported(request.route))
|
|
72
|
-
return { outcome: 'not-capable', diagnostic: 'Claude native inbox requires
|
|
72
|
+
return { outcome: 'not-capable', diagnostic: 'Claude native inbox requires a loaded interactive Square mod.' };
|
|
73
73
|
return hostLedger.withClaimLock(async () => {
|
|
74
74
|
if (signal.aborted)
|
|
75
75
|
return { outcome: 'not-capable', diagnostic: 'Native dispatch deadline elapsed before send.' };
|
package/dist/claude-mod.js
CHANGED
|
@@ -17,7 +17,7 @@ export async function runClaudeMod(inputText, env = process.env) {
|
|
|
17
17
|
const scoped = operationEnv('claude', input.sessionId, env);
|
|
18
18
|
const ledger = hostLedgerForEnv(env);
|
|
19
19
|
const signal = AbortSignal.timeout(2500);
|
|
20
|
-
const supported = process.platform === 'darwin' &&
|
|
20
|
+
const supported = process.platform === 'darwin' && typeof input.endpoint === 'string' && input.endpoint.startsWith('/');
|
|
21
21
|
if (input.operation === 'end') {
|
|
22
22
|
const retired = [];
|
|
23
23
|
const captured = [...input.bindings ?? []];
|
|
@@ -156,7 +156,7 @@ export async function runClaudeMod(inputText, env = process.env) {
|
|
|
156
156
|
await processActNotificationsOnce(binding.location, index, { env: { ...env, SQUARE_NOTIFY_DELIVERY_WAIT_MS: '200' } });
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
return `${JSON.stringify({ available: supported, diagnostic: supported ? undefined : 'Native inbox unavailable: requires macOS Claude
|
|
159
|
+
return `${JSON.stringify({ available: supported, diagnostic: supported ? undefined : 'Native inbox unavailable: requires macOS Claude with an interactive loaded mod and its real endpoint.', bindings, cancelledBindings })}\n`;
|
|
160
160
|
}
|
|
161
161
|
if (!['guard', 'admitted', 'stored'].includes(input.operation) || typeof input.text !== 'string')
|
|
162
162
|
throw new Error('Unknown Claude bridge operation.');
|
package/dist/harness-claude.js
CHANGED
|
@@ -71,8 +71,8 @@ export async function doctorClaudePlugin(homeDir, run = runClaude) {
|
|
|
71
71
|
return [
|
|
72
72
|
fs.existsSync(bundle) ? `✓ Square Claude plugin bundle ${root}` : `○ Square Claude plugin bundle missing ${root}`,
|
|
73
73
|
installed ? `✓ ${CLAUDE_PLUGIN_ID} installed` : `○ ${CLAUDE_PLUGIN_ID} unavailable`,
|
|
74
|
-
`Claude native inbox:
|
|
75
|
-
`Installation or a socket alone does not prove receiver availability; absent/disabled mods, headless unapproved mods, other
|
|
74
|
+
`Claude native inbox: requires macOS Claude Code with a trusted, approved interactive mod.`,
|
|
75
|
+
`Installation or a socket alone does not prove receiver availability; absent/disabled mods, headless unapproved mods, other platforms are unavailable.`,
|
|
76
76
|
`Queue admission is not model processing. Queued or held native messages cannot be retracted by Square cancellation.`,
|
|
77
77
|
`Live routes and admission/presentation evidence: square harness doctor delivery. No legacy fallback.`,
|
|
78
78
|
];
|
package/dist/harness-links.js
CHANGED
|
@@ -94,9 +94,9 @@ function runOpenCode(homeDir, args) {
|
|
|
94
94
|
return { status: result.status ?? 1, stdout: result.stdout || '', stderr: result.stderr || '' };
|
|
95
95
|
}
|
|
96
96
|
export function installOpenCodePlugin(homeDir, force = false, run = runOpenCode) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
// OpenCode v2's `plugin add` is idempotent and has no --global/--force flags.
|
|
98
|
+
void force;
|
|
99
|
+
const args = ['plugin', 'add', SQUARE_IDENTITY.packageName];
|
|
100
100
|
const result = run(homeDir, args);
|
|
101
101
|
if (result.status !== 0)
|
|
102
102
|
throw new Error(`OpenCode plugin install failed: ${result.stderr.trim() || result.stdout.trim() || `exit ${result.status}`}`);
|
package/dist/help.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const COMMANDS = [
|
|
2
2
|
{ names: ['help'], usage: 'help [command]', summary: 'Show the command index or help for one command.' },
|
|
3
3
|
{ names: ['version'], usage: 'version', summary: 'Print the installed version.', hiddenFromIndex: true },
|
|
4
|
-
{ names: ['mcp-server'], usage: 'mcp-server', summary: 'Start the MCP stdio server.', usesSquare: true, hiddenFromIndex: true, details: ['Set SQUARE_LOCATION
|
|
4
|
+
{ names: ['mcp-server'], usage: 'mcp-server', summary: 'Start the MCP stdio server.', usesSquare: true, hiddenFromIndex: true, details: ['Set SQUARE_LOCATION or pass --location before the command.', 'Participant tools accept as on each call. Set the default with SQUARE_PARTICIPANT_NAME or --as.', 'Session identity comes from request _meta.threadId (Codex) or _meta["ai.opencode/sessionID"] (OpenCode), falling back to the startup environment.'] },
|
|
5
5
|
{
|
|
6
6
|
names: ['build'], usage: 'build [--cap <N|unlimited>] [--template <name>] [--throttle N] [-f] < body.md', usesSquare: true, group: 'host',
|
|
7
7
|
summary: 'Create a square from Markdown on stdin.',
|
package/dist/mcp.js
CHANGED
|
@@ -2,21 +2,24 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
4
|
import { SquareError, isSquareError } from './model.js';
|
|
5
|
+
import { operationEnv } from './automatic-session.js';
|
|
6
|
+
import { SQUARE_IDENTITY } from './identity.js';
|
|
5
7
|
import { createSquareApplication } from './square-application.js';
|
|
6
8
|
import { toPublicActivity } from './views.js';
|
|
7
9
|
const activityId = z.string().regex(/^act\/(0|[1-9][0-9]*)$/);
|
|
8
10
|
const stringArray = z.array(z.string());
|
|
11
|
+
const participantName = z.string().optional().describe("Participant name, same as --as. Defaults to the server's configured participant.");
|
|
9
12
|
const TOOL_DEFINITIONS = [
|
|
10
|
-
{ name: 'join', description: 'Join the square as
|
|
11
|
-
{ name: 'express', description: 'Express a message or embodied action in the square.', inputSchema: z.object({ body: z.string(), mentions: stringArray.optional(), reach: z.enum(['bell']).optional(), reply: activityId.optional(), force: z.boolean().optional(), noWait: z.boolean().optional() }).strict() },
|
|
12
|
-
{ name: 'catch', description: 'Catch and consume activities perceptible to the
|
|
13
|
+
{ name: 'join', description: 'Join the square as a participant.', inputSchema: z.object({ as: participantName, takeover: z.boolean().optional() }).strict() },
|
|
14
|
+
{ name: 'express', description: 'Express a message or embodied action in the square.', inputSchema: z.object({ as: participantName, body: z.string(), mentions: stringArray.optional(), reach: z.enum(['bell']).optional(), reply: activityId.optional(), force: z.boolean().optional(), noWait: z.boolean().optional() }).strict() },
|
|
15
|
+
{ name: 'catch', description: 'Catch and consume activities perceptible to the participant.', inputSchema: z.object({ as: participantName, id: activityId.optional(), idle: z.number().finite().min(0).optional(), from: stringArray.optional(), mention: z.boolean().optional(), limit: z.number().int().min(1).optional() }).strict() },
|
|
13
16
|
{ name: 'history', description: 'Read the activity stream using stable activity-id cursors.', inputSchema: z.object({ limit: z.number().int().min(1).optional(), order: z.enum(['asc', 'desc']).optional(), before: activityId.optional(), after: activityId.optional(), grep: z.string().optional(), fixed: z.string().optional(), from: stringArray.optional(), mention: z.string().optional() }).strict() },
|
|
14
|
-
{ name: 'listen', description: 'Listen for future activity from a participant.', inputSchema: z.object({ target: z.string() }).strict() },
|
|
15
|
-
{ name: 'ignore', description: 'Stop listening for future activity from a participant.', inputSchema: z.object({ target: z.string() }).strict() },
|
|
16
|
-
{ name: 'listening', description: 'List participants this participant is listening to.', inputSchema: z.object({}).strict() },
|
|
17
|
-
{ name: 'hold', description: 'Raise a hand to hold the square.', inputSchema: z.object({ reason: z.string().optional() }).strict() },
|
|
18
|
-
{ name: 'resume', description: 'Release the current hold.', inputSchema: z.object({}).strict() },
|
|
19
|
-
{ name: 'done', description: 'Leave the square without adding a message.', inputSchema: z.object({}).strict() },
|
|
17
|
+
{ name: 'listen', description: 'Listen for future activity from a participant.', inputSchema: z.object({ as: participantName, target: z.string() }).strict() },
|
|
18
|
+
{ name: 'ignore', description: 'Stop listening for future activity from a participant.', inputSchema: z.object({ as: participantName, target: z.string() }).strict() },
|
|
19
|
+
{ name: 'listening', description: 'List participants this participant is listening to.', inputSchema: z.object({ as: participantName }).strict() },
|
|
20
|
+
{ name: 'hold', description: 'Raise a hand to hold the square.', inputSchema: z.object({ as: participantName, reason: z.string().optional() }).strict() },
|
|
21
|
+
{ name: 'resume', description: 'Release the current hold.', inputSchema: z.object({ as: participantName }).strict() },
|
|
22
|
+
{ name: 'done', description: 'Leave the square without adding a message.', inputSchema: z.object({ as: participantName }).strict() },
|
|
20
23
|
{ name: 'status', description: 'Read the public status of the square.', inputSchema: z.object({}).strict() },
|
|
21
24
|
{ name: 'participants', description: 'List participants standing in or done with the square.', inputSchema: z.object({}).strict() },
|
|
22
25
|
];
|
|
@@ -71,14 +74,23 @@ function operation(app, name, args, control) {
|
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
export function createSquareMcpServer(options) {
|
|
74
|
-
const
|
|
75
|
-
const server = new McpServer({ name: 'square', version:
|
|
77
|
+
const baseEnv = { ...options.env };
|
|
78
|
+
const server = new McpServer({ name: 'square', version: SQUARE_IDENTITY.packageVersion }, {
|
|
76
79
|
instructions: 'The catch tool consumes activities. Use history with act/<index> cursors for read-only archive access.',
|
|
77
80
|
});
|
|
78
81
|
for (const tool of TOOL_DEFINITIONS) {
|
|
79
82
|
server.registerTool(tool.name, { description: tool.description, inputSchema: tool.inputSchema }, async (args, extra) => {
|
|
80
83
|
try {
|
|
81
|
-
const
|
|
84
|
+
const { as: participant, ...operationArgs } = args;
|
|
85
|
+
const threadId = extra._meta?.threadId;
|
|
86
|
+
const opencodeSessionId = extra._meta?.['ai.opencode/sessionID'];
|
|
87
|
+
const env = typeof threadId === 'string' && threadId.trim()
|
|
88
|
+
? operationEnv('codex', threadId, baseEnv)
|
|
89
|
+
: typeof opencodeSessionId === 'string' && opencodeSessionId.trim()
|
|
90
|
+
? operationEnv('opencode', opencodeSessionId, baseEnv)
|
|
91
|
+
: baseEnv;
|
|
92
|
+
const app = createSquareApplication({ ...options, env, participant: participant ?? options.participant });
|
|
93
|
+
const value = await operation(app, tool.name, operationArgs, { signal: extra.signal });
|
|
82
94
|
const projected = publicResult(tool.name, value);
|
|
83
95
|
const structuredContent = isObject(projected) ? projected : { result: projected };
|
|
84
96
|
return { content: [{ type: 'text', text: JSON.stringify(structuredContent) }], structuredContent };
|
package/dist/wake-eligibility.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { nameKey } from './model.js';
|
|
2
2
|
import { deriveDeliveryModel } from './delivery.js';
|
|
3
3
|
import { formatActivityId, parseActivityId } from './square-core.js';
|
|
4
|
+
import { presenceEpoch } from './registry.js';
|
|
4
5
|
import { decodeWakeEvidence } from './wake-evidence.js';
|
|
5
6
|
function identity(...parts) { return JSON.stringify(parts); }
|
|
6
7
|
/** One strict ownership join, latest selection, and request fence over primary evidence only. */
|
|
@@ -16,7 +17,7 @@ export function projectWakeEligibility(input) {
|
|
|
16
17
|
ownersBySession.set(key, rows);
|
|
17
18
|
}
|
|
18
19
|
const ownerFor = (route) => route.location !== input.location ? undefined
|
|
19
|
-
: ownersBySession.get(identity(nameKey(route.participant), route.sessionId))?.find((row) => route.epoch === undefined || row
|
|
20
|
+
: ownersBySession.get(identity(nameKey(route.participant), route.sessionId))?.find((row) => route.epoch === undefined || presenceEpoch(row) === route.epoch);
|
|
20
21
|
const ownedRoutes = [];
|
|
21
22
|
const latest = new Map();
|
|
22
23
|
for (const route of input.state.routes ?? []) {
|
package/guides/claude-native.md
CHANGED
|
@@ -7,11 +7,11 @@ not evidence of a live receiver.
|
|
|
7
7
|
|
|
8
8
|
## Validated capability
|
|
9
9
|
|
|
10
|
-
The supported baseline is **macOS Claude Code
|
|
11
|
-
|
|
10
|
+
The supported baseline is **macOS Claude Code with the mod actually loaded**;
|
|
11
|
+
no build number is pinned. The receiver reads its real session ID, cwd, version, and
|
|
12
12
|
`CLAUDE_CODE_MESSAGING_SOCKET`. A session ID or socket alone is not capability.
|
|
13
13
|
Missing/disabled/unapproved mods, the normal unapproved headless `-p` path,
|
|
14
|
-
|
|
14
|
+
and other platforms are unavailable. No legacy fallback exists.
|
|
15
15
|
Square never changes inbound policy, forwards a child token, or impersonates a
|
|
16
16
|
peer/plugin authority. Native OS-user socket permissions and Claude policy apply.
|
|
17
17
|
|
|
@@ -32,7 +32,7 @@ only sends previously unsent eligible attention, never unknown/admitted attempts
|
|
|
32
32
|
Initial activation and hot reload use `session.start`. New conversations use
|
|
33
33
|
`classic.SessionStart`: clear reads the new API coordinate; **resume's event
|
|
34
34
|
`session_id` is already the resumed coordinate while `$.session.id()` still reads
|
|
35
|
-
the ending one in 2.1.295**. The event coordinate is used at that boundary, with
|
|
35
|
+
the ending one (observed in 2.1.295)**. The event coordinate is used at that boundary, with
|
|
36
36
|
API cwd/version/socket. Modern `session.end` retires only its pinned `e.sessionId`
|
|
37
37
|
and captured ownership epochs, within the event budget. Late committed joins
|
|
38
38
|
are discovered at the pinned end timestamp. A process crash can omit end.
|
package/package.json
CHANGED
package/skills/square/SKILL.md
CHANGED
|
@@ -6,6 +6,8 @@ allowed-tools: Bash(square *)
|
|
|
6
6
|
|
|
7
7
|
# Square
|
|
8
8
|
|
|
9
|
+
When a `square` tool is available, call it with the same arguments instead of the shell; pass any `-` body as `stdin`.
|
|
10
|
+
|
|
9
11
|
Don't treat Square as a public dumping ground. Speak here only when you genuinely think someone else needs to know; otherwise you are needlessly interrupting them.
|
|
10
12
|
|
|
11
13
|
A square is a physical place where participants catch up and express thoughts or actions. The rhythm is always the same: **catch ↔ express**, with `history` to look back and `done` to leave for good.
|