@alphazede/bearing-lite 0.1.0 → 0.1.8

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.
Files changed (34) hide show
  1. package/README.md +97 -67
  2. package/hooks/activation.cjs +2 -1
  3. package/hooks/com.anthropic.claude-code/host.cjs +437 -0
  4. package/hooks/com.anthropic.claude-code/mapping.md +69 -0
  5. package/hooks/com.cursor/hooks.json +15 -0
  6. package/hooks/hooks.json +35 -0
  7. package/package.json +7 -4
  8. package/plugin.json +34 -2
  9. package/skills/bearing-lite/SKILL.md +43 -36
  10. package/skills/bearing-lite/agents/openai.yaml +7 -0
  11. package/skills/bearing-lite/references/peer-synthesis.md +19 -0
  12. package/skills/bearing-lite/references/role-routing.mmd +19 -32
  13. package/skills/bearing-lite/references/task-state.md +19 -1
  14. package/skills/bearing-lite/references/task-state.mmd +1 -1
  15. package/skills/bearing-lite/templates/default-role-lineup.md +24 -0
  16. package/skills/bearing-lite/templates/task.md +56 -0
  17. package/skills/crewmate/SKILL.md +42 -30
  18. package/skills/explorer/SKILL.md +50 -31
  19. package/skills/gather-supplies/SKILL.md +46 -26
  20. package/skills/map-the-route/SKILL.md +39 -26
  21. package/skills/map-the-route/references/artifact-grammar.md +10 -10
  22. package/skills/navigator/SKILL.md +51 -37
  23. package/skills/park-ranger/SKILL.md +29 -24
  24. package/skills/repository-fit/SKILL.md +26 -19
  25. package/skills/set-bearings/SKILL.md +25 -19
  26. package/skills/surveyor/SKILL.md +26 -24
  27. package/skills/validator/SKILL.md +28 -27
  28. package/guide/migration.md +0 -168
  29. package/skills/bearing-lite/assets/role-routing.png +0 -0
  30. package/skills/bearing-lite/assets/task-state.png +0 -0
  31. package/skills/delegate-authority/SKILL.md +0 -38
  32. package/skills/sub-explorer/SKILL.md +0 -37
  33. package/skills/trail-boss/SKILL.md +0 -38
  34. package/skills/trail-boss/agents/openai.yaml +0 -4
@@ -0,0 +1,437 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ /**
5
+ * Verified host adapter (CONTRACT-HOOK-01, CONTRACT-CLIENT-01).
6
+ *
7
+ * Claude Code, Codex, Grok Build, Cursor, and Kimi Code deliver session
8
+ * events. This adapter derives only the Bearing fields that are visible in
9
+ * the project plan, then calls the portable class evaluators. It never
10
+ * fabricates BLOCK from a missing field.
11
+ *
12
+ * Coverage is partial: activation and closeout are executable; transition and
13
+ * protected_action stay procedural. Always exit 0 (RISK-12 / RISK-20). Host
14
+ * blocking, if ever required, is JSON-only — never process status.
15
+ */
16
+
17
+ const fs = require("node:fs");
18
+ const path = require("node:path");
19
+
20
+ const activation = require("../activation.cjs");
21
+ const closeout = require("../closeout.cjs");
22
+
23
+ const HOST = "com.anthropic.claude-code";
24
+ const COVERAGE = Object.freeze({
25
+ activation: Object.freeze({ executable: true, procedural: true }),
26
+ closeout: Object.freeze({ executable: true, procedural: true }),
27
+ transition: Object.freeze({ executable: false, procedural: true }),
28
+ protected_action: Object.freeze({ executable: false, procedural: true }),
29
+ });
30
+
31
+ const MAX_FILES = 20;
32
+ const MAX_BYTES = 256 * 1024;
33
+ const MAX_DEPTH = 3;
34
+ const SKIP_DIRS = new Set([
35
+ "node_modules",
36
+ ".git",
37
+ "dist",
38
+ "coverage",
39
+ ".next",
40
+ ".cache",
41
+ "target",
42
+ "vendor",
43
+ ".venv",
44
+ "venv",
45
+ "skills",
46
+ "hooks",
47
+ "test",
48
+ "tests",
49
+ "templates",
50
+ ]);
51
+
52
+ const TASK_MARK = /(?:^|\n)###\s*task_id:\s*\S+/;
53
+ const TASK_LINE = /^###\s*task_id:\s*(\S+)\s*$/;
54
+ const FIELD_LINE =
55
+ /^-\s*(assigned_role|next_action|status|required_assurance|blocker|evidence|candidate_ref|scope|authority|outcome|depends_on|receiving_role|plan_ref|role|subject):\s*(.*)$/;
56
+ const JOURNEY_LINE = /^\s*-\s*journey:\s*(.+)$/i;
57
+ const LEASE_MARK = /^\s*-\s*checkout_lease:/m;
58
+
59
+ const ACTIVATION_EVENTS = new Set([
60
+ "SessionStart",
61
+ "UserPromptSubmit",
62
+ "UserPromptExpansion",
63
+ "CwdChanged",
64
+ "SubagentStart",
65
+ ]);
66
+ const CLOSEOUT_EVENTS = new Set(["Stop", "SubagentStop", "SessionEnd"]);
67
+ const STOP_CONTINUATION_EVENTS = new Set(["Stop", "SubagentStop"]);
68
+
69
+ const EVENT_ALIASES = Object.freeze({
70
+ sessionstart: "SessionStart",
71
+ userpromptsubmit: "UserPromptSubmit",
72
+ beforesubmitprompt: "UserPromptSubmit",
73
+ userpromptexpansion: "UserPromptExpansion",
74
+ cwdchanged: "CwdChanged",
75
+ subagentstart: "SubagentStart",
76
+ stop: "Stop",
77
+ subagentstop: "SubagentStop",
78
+ sessionend: "SessionEnd",
79
+ pretooluse: "PreToolUse",
80
+ posttooluse: "PostToolUse",
81
+ beforeshellexecution: "PreToolUse",
82
+ afterfileedit: "PostToolUse",
83
+ });
84
+
85
+ /**
86
+ * Normalize Claude, Codex, Grok, Cursor, and Kimi event names.
87
+ * @param {unknown} name
88
+ */
89
+ function canonicalizeEvent(name) {
90
+ if (typeof name !== "string" || !name.trim()) return "";
91
+ const compact = name.trim().replace(/[_-]/g, "").toLowerCase();
92
+ return EVENT_ALIASES[compact] || name.trim();
93
+ }
94
+
95
+ function isPlainObject(value) {
96
+ return value !== null && typeof value === "object" && !Array.isArray(value);
97
+ }
98
+
99
+ function isPlaceholder(value) {
100
+ if (typeof value !== "string") return false;
101
+ const trimmed = value.trim();
102
+ return trimmed === "" || trimmed === "unassigned" || /^<[^>]+>$/.test(trimmed);
103
+ }
104
+
105
+ function presentString(value) {
106
+ if (typeof value !== "string") return undefined;
107
+ const trimmed = value.trim();
108
+ if (!trimmed || isPlaceholder(trimmed)) return undefined;
109
+ return trimmed;
110
+ }
111
+
112
+ function readStdinSync() {
113
+ try {
114
+ return fs.readFileSync(0, "utf8");
115
+ } catch (err) {
116
+ const code = err && err.code;
117
+ if (code === "EAGAIN" || code === "EOF") return "";
118
+ throw err;
119
+ }
120
+ }
121
+
122
+ function rankMarkdown(name) {
123
+ const n = name.toLowerCase();
124
+ if (n === "plan.md" || n === "progress.md") return 0;
125
+ if (n.includes("plan")) return 1;
126
+ if (n.includes("implementation") || n.includes("progress")) return 2;
127
+ return 5;
128
+ }
129
+
130
+ function walkMarkdown(root) {
131
+ const out = [];
132
+ function walk(dir, depth) {
133
+ if (out.length >= MAX_FILES || depth > MAX_DEPTH) return;
134
+ let entries;
135
+ try {
136
+ entries = fs.readdirSync(dir, { withFileTypes: true });
137
+ } catch {
138
+ return;
139
+ }
140
+ const files = [];
141
+ const dirs = [];
142
+ for (const entry of entries) {
143
+ if (entry.isSymbolicLink()) continue;
144
+ if (entry.name.startsWith(".") && entry.name !== ".agents") continue;
145
+ if (entry.isDirectory()) {
146
+ if (!SKIP_DIRS.has(entry.name)) dirs.push(entry.name);
147
+ } else if (entry.isFile() && /\.(md|markdown)$/i.test(entry.name)) {
148
+ files.push(entry.name);
149
+ }
150
+ }
151
+ files.sort((a, b) => rankMarkdown(a) - rankMarkdown(b) || a.localeCompare(b));
152
+ for (const name of files) {
153
+ if (out.length >= MAX_FILES) return;
154
+ out.push(path.join(dir, name));
155
+ }
156
+ dirs.sort((a, b) => {
157
+ if (a === "docs") return -1;
158
+ if (b === "docs") return 1;
159
+ if (a === "plans") return -1;
160
+ if (b === "plans") return 1;
161
+ return a.localeCompare(b);
162
+ });
163
+ for (const name of dirs) {
164
+ walk(path.join(dir, name), depth + 1);
165
+ }
166
+ }
167
+ walk(root, 0);
168
+ return out;
169
+ }
170
+
171
+ function parsePlanMarkdown(text) {
172
+ const tasks = [];
173
+ let journey = null;
174
+ let current = null;
175
+ for (const line of String(text).split(/\r?\n/)) {
176
+ const journeyMatch = line.match(JOURNEY_LINE);
177
+ if (journeyMatch) {
178
+ const value = presentString(journeyMatch[1]);
179
+ if (value) journey = value;
180
+ }
181
+ const taskMatch = line.match(TASK_LINE);
182
+ if (taskMatch) {
183
+ if (current) tasks.push(current);
184
+ current = { task_id: taskMatch[1] };
185
+ continue;
186
+ }
187
+ if (!current) continue;
188
+ const fieldMatch = line.match(FIELD_LINE);
189
+ if (fieldMatch) {
190
+ const value = presentString(fieldMatch[2]);
191
+ if (value !== undefined) current[fieldMatch[1]] = value;
192
+ }
193
+ }
194
+ if (current) tasks.push(current);
195
+ return { tasks, journey };
196
+ }
197
+
198
+ /**
199
+ * Derive Bearing domain fields from visible Markdown in cwd.
200
+ * Does not invent router_invoked, assigned_role, or next_action.
201
+ * @param {string} cwd
202
+ */
203
+ function deriveContext(cwd) {
204
+ const files = walkMarkdown(cwd);
205
+ const allTasks = [];
206
+ let journey = null;
207
+ let planPresent = false;
208
+ for (const file of files) {
209
+ let text;
210
+ try {
211
+ const st = fs.statSync(file);
212
+ if (!st.isFile() || st.size > MAX_BYTES) continue;
213
+ text = fs.readFileSync(file, "utf8");
214
+ } catch {
215
+ continue;
216
+ }
217
+ const parsed = parsePlanMarkdown(text);
218
+ const hasAssignedRole = /^-\s*assigned_role:/m.test(text);
219
+ const hasLease = LEASE_MARK.test(text);
220
+ if (!TASK_MARK.test(text) && !hasAssignedRole && !parsed.journey && !hasLease) {
221
+ continue;
222
+ }
223
+ planPresent = true;
224
+ if (parsed.journey) journey = parsed.journey;
225
+ for (const task of parsed.tasks) allTasks.push(task);
226
+ }
227
+
228
+ const active =
229
+ allTasks.find((task) => {
230
+ const status = presentString(task.status);
231
+ return status && status !== "COMPLETE" && status !== "CANCELLED";
232
+ }) ||
233
+ allTasks[0] ||
234
+ null;
235
+
236
+ const assignedRole = active ? presentString(active.assigned_role) : undefined;
237
+ const nextAction = active ? presentString(active.next_action) : undefined;
238
+
239
+ return {
240
+ plan_present: planPresent,
241
+ router_invoked: Boolean(journey),
242
+ assigned_role: assignedRole,
243
+ next_action: nextAction,
244
+ next_action_known: Boolean(nextAction),
245
+ active_task: active,
246
+ journey,
247
+ };
248
+ }
249
+
250
+ function classForEvent(eventName) {
251
+ const canonical = canonicalizeEvent(eventName);
252
+ if (ACTIVATION_EVENTS.has(canonical)) return "activation";
253
+ if (CLOSEOUT_EVENTS.has(canonical)) return "closeout";
254
+ return null;
255
+ }
256
+
257
+ function isTruthyFlag(value) {
258
+ return value === true || value === "true";
259
+ }
260
+
261
+ function isStopReentry(input, eventName) {
262
+ if (!STOP_CONTINUATION_EVENTS.has(eventName)) return false;
263
+ return isTruthyFlag(input.stop_hook_active) || isTruthyFlag(input.stopHookActive);
264
+ }
265
+
266
+ function hasDiscoverableJourney(derived) {
267
+ return (
268
+ derived.plan_present === true ||
269
+ derived.router_invoked === true ||
270
+ Boolean(derived.assigned_role) ||
271
+ derived.active_task != null
272
+ );
273
+ }
274
+
275
+ function quietSuccess() {
276
+ return {};
277
+ }
278
+
279
+ function formatAdvice(verdict) {
280
+ const lines = [
281
+ "Bearing Lite " + verdict.hook_class + ": " + verdict.outcome,
282
+ verdict.reason ? "reason: " + verdict.reason : "",
283
+ verdict.recovery ? "recovery: " + verdict.recovery : "",
284
+ "Coverage: this host mapping is partial. activation and closeout are executable; transition and protected_action remain procedural.",
285
+ ].filter(Boolean);
286
+ return lines.join("\n").slice(0, 4000);
287
+ }
288
+
289
+ function unavailableHost(eventName, reason) {
290
+ const event = eventName || "SessionStart";
291
+ return {
292
+ hookSpecificOutput: {
293
+ hookEventName: event,
294
+ additionalContext:
295
+ "Bearing Lite UNAVAILABLE: " +
296
+ reason +
297
+ ". Invoke the bearing-lite router manually and continue after context is loaded.",
298
+ },
299
+ };
300
+ }
301
+
302
+ /**
303
+ * Translate a portable verdict into Claude Code / Codex JSON.
304
+ * Exit status is never used for policy (RISK-12 / RISK-20).
305
+ */
306
+ function toHostResponse(eventName, verdict) {
307
+ const event = eventName || "SessionStart";
308
+ const text = formatAdvice(verdict);
309
+ const body = {
310
+ hookSpecificOutput: {
311
+ hookEventName: event,
312
+ additionalContext: text,
313
+ },
314
+ };
315
+ // This mapping never requests protected_completion, so BLOCK should not
316
+ // appear. If a future caller passes a BLOCK verdict, use JSON only.
317
+ if (verdict.outcome === "BLOCK") {
318
+ body.decision = "block";
319
+ body.reason = text;
320
+ }
321
+ return body;
322
+ }
323
+
324
+ function evaluateForHost(eventName, derived) {
325
+ if (classForEvent(eventName) === "closeout") {
326
+ const task = derived.active_task || {};
327
+ return closeout.evaluate({
328
+ plan_ref: derived.plan_present ? "project-plan" : undefined,
329
+ role: presentString(task.assigned_role) || presentString(task.role),
330
+ subject: presentString(task.task_id) || presentString(task.subject),
331
+ depends_on: task.depends_on,
332
+ scope: presentString(task.scope),
333
+ authority: presentString(task.authority),
334
+ outcome: presentString(task.outcome),
335
+ evidence: presentString(task.evidence),
336
+ blocker: presentString(task.blocker) || "none",
337
+ next_action: presentString(task.next_action),
338
+ receiving_role: presentString(task.receiving_role),
339
+ required_assurance: task.required_assurance,
340
+ });
341
+ }
342
+ return activation.evaluate({
343
+ plan_present: derived.plan_present === true,
344
+ next_action_known: derived.next_action_known === true,
345
+ next_action: derived.next_action,
346
+ assigned_role: derived.assigned_role,
347
+ router_invoked: derived.router_invoked === true,
348
+ });
349
+ }
350
+
351
+ /**
352
+ * @param {unknown} input
353
+ */
354
+ function handle(input) {
355
+ let parsed = input;
356
+ if (typeof parsed === "string") {
357
+ try {
358
+ parsed = JSON.parse(parsed);
359
+ } catch {
360
+ return unavailableHost("SessionStart", "malformed_input");
361
+ }
362
+ }
363
+ if (parsed === undefined || parsed === null) {
364
+ return unavailableHost("SessionStart", "missing_input");
365
+ }
366
+ if (!isPlainObject(parsed)) {
367
+ return unavailableHost("SessionStart", "malformed_input");
368
+ }
369
+
370
+ const eventName = canonicalizeEvent(
371
+ parsed.hook_event_name || parsed.hookEventName
372
+ );
373
+ if (!classForEvent(eventName)) {
374
+ return unavailableHost(eventName || "SessionStart", "unmapped_host_event");
375
+ }
376
+
377
+ if (isStopReentry(parsed, eventName)) {
378
+ return quietSuccess();
379
+ }
380
+
381
+ const cwd =
382
+ presentString(parsed.cwd) ||
383
+ presentString(parsed.workspaceRoot) ||
384
+ process.cwd();
385
+
386
+ let derived;
387
+ try {
388
+ derived = deriveContext(cwd);
389
+ } catch {
390
+ return toHostResponse(
391
+ eventName,
392
+ activation.evaluate({ infrastructure_failure: "permission_error" })
393
+ );
394
+ }
395
+
396
+ if (STOP_CONTINUATION_EVENTS.has(eventName) && !hasDiscoverableJourney(derived)) {
397
+ return quietSuccess();
398
+ }
399
+
400
+ return toHostResponse(eventName, evaluateForHost(eventName, derived));
401
+ }
402
+
403
+ function main() {
404
+ let raw = "";
405
+ try {
406
+ raw = readStdinSync();
407
+ } catch {
408
+ process.stdout.write(JSON.stringify(unavailableHost("SessionStart", "stdin_read_failure")) + "\n");
409
+ process.exit(0);
410
+ return;
411
+ }
412
+
413
+ const trimmed = raw.trim();
414
+ if (!trimmed) {
415
+ process.stdout.write(JSON.stringify(unavailableHost("SessionStart", "missing_input")) + "\n");
416
+ process.exit(0);
417
+ return;
418
+ }
419
+
420
+ process.stdout.write(JSON.stringify(handle(trimmed)) + "\n");
421
+ process.exit(0);
422
+ }
423
+
424
+ module.exports = {
425
+ HOST,
426
+ COVERAGE,
427
+ canonicalizeEvent,
428
+ classForEvent,
429
+ deriveContext,
430
+ evaluateForHost,
431
+ handle,
432
+ toHostResponse,
433
+ };
434
+
435
+ if (require.main === module) {
436
+ main();
437
+ }
@@ -0,0 +1,69 @@
1
+ # Verified host mapping
2
+
3
+ This adapter is the verified native mapping for hosts that share a
4
+ session-start / stop command hook. Coverage is **partial**: activation and
5
+ closeout are executable; transition-order and protected-action stay
6
+ procedural.
7
+
8
+ ## Hosts
9
+
10
+ | Host | Plugin install | Hooks | Coverage |
11
+ |---|---|---|---|
12
+ | Claude Code | `.claude-plugin/` marketplace | `hooks/hooks.json` | partial |
13
+ | Codex | `.codex-plugin/` + `.agents/plugins/` | `hooks/hooks.json` | partial |
14
+ | Grok Build | `.grok-plugin/` marketplace | `hooks/hooks.json` | partial |
15
+ | Cursor | `.cursor-plugin/` | `hooks/com.cursor/hooks.json` (`sessionStart`, `stop`) | partial |
16
+ | Kimi Code | `.kimi-plugin/plugin.json` | manifest `hooks` array | partial |
17
+ | AGY | `.agy/` (strict `plugin.json`) | none | skills-only |
18
+ | Pi | `package.json` `"pi"` + `pi-package` | none (TypeScript extensions, not command hooks) | skills-only |
19
+
20
+ Do **not** set `hooks` on Claude, Codex, or Grok host manifests. Those hosts
21
+ auto-load `hooks/hooks.json`; declaring both is a duplicate-file error.
22
+
23
+ Skill-copy into a host skills directory does **not** register hooks. Plugin
24
+ install or disable uses the host's native controls. Bearing Lite never copies
25
+ adapters into global hook configuration.
26
+
27
+ ## Event map
28
+
29
+ | Host event names | Bearing class | Executable? |
30
+ |---|---|---|
31
+ | `SessionStart`, `sessionStart`, `session_start` | activation | yes, advisory |
32
+ | `Stop`, `stop` | closeout | yes, advisory only |
33
+ | any other host event | none | unmapped; fail open as `UNAVAILABLE` |
34
+
35
+ The adapter accepts snake_case and camelCase (`hook_event_name` /
36
+ `hookEventName`, `cwd` / `workspaceRoot`).
37
+
38
+ ## Derived fields
39
+
40
+ The host event supplies session metadata. The adapter reads visible Markdown
41
+ under `cwd` (bounded; skips `skills/`, `hooks/`, `test/`, and dependency
42
+ trees) and sets only:
43
+
44
+ | Bearing field | Source |
45
+ |---|---|
46
+ | `plan_present` | a Markdown file contains a `task_id`, `assigned_role`, non-placeholder journey marker, or `checkout_lease` block |
47
+ | `router_invoked` | a `- journey:` setting is present and not a placeholder |
48
+ | `assigned_role` | active task `assigned_role` when not `unassigned` or `<…>` |
49
+ | `next_action` / `next_action_known` | active task `next_action` when not a placeholder |
50
+ | closeout handoff fields | matching task-record keys when present |
51
+
52
+ `assigned_role` and `router_invoked` are **not** inferred from the tool-call
53
+ payload. Missing values stay missing, so activation advises the router instead
54
+ of inventing context.
55
+
56
+ ## Outcome translation
57
+
58
+ | Outcome | Host JSON | Process exit |
59
+ |---|---|---|
60
+ | `ADVISE`, `REROUTE`, `UNAVAILABLE` on activation or a discoverable-Journey first-pass Stop | `hookSpecificOutput.additionalContext` | always `0` |
61
+ | Stop/SubagentStop re-entry (`stop_hook_active`) | quiet success (empty JSON; no `additionalContext`) | always `0` |
62
+ | Stop/SubagentStop with no discoverable Journey | quiet success (empty JSON; no `additionalContext`) | always `0` |
63
+ | first-pass Stop/SubagentStop with a discoverable Journey | `hookSpecificOutput.additionalContext` | always `0` |
64
+ | `BLOCK` | JSON `decision: "block"` only; this mapping never requests protected completion | always `0` |
65
+
66
+ A discoverable Journey is a visible plan with a `task_id`, `assigned_role`,
67
+ non-placeholder journey marker, or `checkout_lease` block. Empty cwd and
68
+ `stop_hook_active` re-entry stay quiet. Never map policy or infrastructure to
69
+ a non-zero exit.
@@ -0,0 +1,15 @@
1
+ {
2
+ "description": "Bearing Lite Cursor mapping. Partial coverage: sessionStart activation, stop closeout. Transition-order and protected-action remain procedural.",
3
+ "hooks": {
4
+ "sessionStart": [
5
+ {
6
+ "command": "node ./hooks/com.anthropic.claude-code/host.cjs"
7
+ }
8
+ ],
9
+ "stop": [
10
+ {
11
+ "command": "node ./hooks/com.anthropic.claude-code/host.cjs"
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "description": "Bearing Lite verified Claude Code and Codex mapping. Partial coverage: activation on SessionStart, closeout on Stop. Transition-order and protected-action remain procedural.",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node",
10
+ "args": [
11
+ "${CLAUDE_PLUGIN_ROOT}/hooks/com.anthropic.claude-code/host.cjs"
12
+ ],
13
+ "timeout": 15,
14
+ "statusMessage": "Bearing Lite activation"
15
+ }
16
+ ]
17
+ }
18
+ ],
19
+ "Stop": [
20
+ {
21
+ "hooks": [
22
+ {
23
+ "type": "command",
24
+ "command": "node",
25
+ "args": [
26
+ "${CLAUDE_PLUGIN_ROOT}/hooks/com.anthropic.claude-code/host.cjs"
27
+ ],
28
+ "timeout": 15,
29
+ "statusMessage": "Bearing Lite closeout"
30
+ }
31
+ ]
32
+ }
33
+ ]
34
+ }
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alphazede/bearing-lite",
3
- "version": "0.1.0",
3
+ "version": "0.1.8",
4
4
  "description": "Skills-first Agent Plugin for planning, routing, bounded execution, and independent review of repository work—without CLI, MCP, server, or hidden runtime state.",
5
5
  "keywords": [
6
6
  "agent-plugins",
@@ -11,8 +11,12 @@
11
11
  "developer-tools",
12
12
  "skills-first",
13
13
  "evidence",
14
- "code-review"
14
+ "code-review",
15
+ "pi-package"
15
16
  ],
17
+ "pi": {
18
+ "skills": ["./skills"]
19
+ },
16
20
  "author": "William Rumph / AlphaZede",
17
21
  "license": "Apache-2.0",
18
22
  "repository": {
@@ -31,7 +35,6 @@
31
35
  "CODE_OF_CONDUCT.md",
32
36
  "CONTRIBUTING.md",
33
37
  "SECURITY.md",
34
- "LICENSE-APACHE",
35
- "guide/migration.md"
38
+ "LICENSE-APACHE"
36
39
  ]
37
40
  }
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "bearing-lite",
4
- "version": "0.1.0",
4
+ "version": "0.1.8",
5
5
  "description": "Skills-first portable plugin that routes repository work through the smallest valid planning stages and agent roles, using project Markdown as the only task record.",
6
6
  "author": {
7
7
  "name": "William Rumph / AlphaZede",
@@ -18,5 +18,37 @@
18
18
  "routing",
19
19
  "developer-tools",
20
20
  "skills-first"
21
- ]
21
+ ],
22
+ "hooks": {
23
+ "com.anthropic.claude-code.activation": {
24
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
25
+ },
26
+ "com.anthropic.claude-code.closeout": {
27
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
28
+ },
29
+ "com.openai.codex.activation": {
30
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
31
+ },
32
+ "com.openai.codex.closeout": {
33
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
34
+ },
35
+ "com.xai.grok-build.activation": {
36
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
37
+ },
38
+ "com.xai.grok-build.closeout": {
39
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
40
+ },
41
+ "com.cursor.ide.activation": {
42
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
43
+ },
44
+ "com.cursor.ide.closeout": {
45
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
46
+ },
47
+ "com.moonshotai.kimi-code.activation": {
48
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
49
+ },
50
+ "com.moonshotai.kimi-code.closeout": {
51
+ "path": "./hooks/com.anthropic.claude-code/host.cjs"
52
+ }
53
+ }
22
54
  }