loadout-ai 0.7.0 → 0.9.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +148 -1
  2. package/README.md +160 -315
  3. package/SECURITY.md +21 -1
  4. package/catalog/discovered.json +31269 -26003
  5. package/catalog/packages.json +4 -4
  6. package/dist/src/cli.js +13 -0
  7. package/dist/src/commands/agents.js +3 -1
  8. package/dist/src/commands/catalog-candidate.js +150 -0
  9. package/dist/src/commands/catalog-workflows.js +147 -0
  10. package/dist/src/commands/catalog.js +9 -367
  11. package/dist/src/commands/coordinate.js +586 -0
  12. package/dist/src/commands/coordination-discussions.js +194 -0
  13. package/dist/src/commands/coordination-sessions.js +197 -0
  14. package/dist/src/commands/inventory.js +4 -2
  15. package/dist/src/core/agents/agent-inspection.js +26 -4
  16. package/dist/src/core/{routing → agents}/model-config.js +7 -2
  17. package/dist/src/core/catalog/catalog.js +1 -0
  18. package/dist/src/core/catalog/registry.js +44 -10
  19. package/dist/src/core/catalog/safety.js +36 -7
  20. package/dist/src/core/coordination/adapters/claude-code.js +154 -0
  21. package/dist/src/core/coordination/adapters/codex.js +137 -0
  22. package/dist/src/core/coordination/adapters/types.js +64 -0
  23. package/dist/src/core/coordination/auth.js +59 -0
  24. package/dist/src/core/coordination/bridge-lease.js +79 -0
  25. package/dist/src/core/coordination/conflict-preview.js +167 -0
  26. package/dist/src/core/coordination/contract-diff.js +106 -0
  27. package/dist/src/core/coordination/coordinator.js +552 -0
  28. package/dist/src/core/coordination/crash-recovery.js +169 -0
  29. package/dist/src/core/coordination/daemon.js +667 -0
  30. package/dist/src/core/coordination/discussion.js +340 -0
  31. package/dist/src/core/coordination/events.js +161 -0
  32. package/dist/src/core/coordination/http-api.js +118 -0
  33. package/dist/src/core/coordination/interrupt-policy.js +89 -0
  34. package/dist/src/core/coordination/lock.js +110 -0
  35. package/dist/src/core/coordination/mcp-server.js +424 -0
  36. package/dist/src/core/coordination/redaction.js +85 -0
  37. package/dist/src/core/coordination/replay.js +188 -0
  38. package/dist/src/core/coordination/retention.js +128 -0
  39. package/dist/src/core/coordination/runtime.js +21 -0
  40. package/dist/src/core/coordination/session-manager.js +366 -0
  41. package/dist/src/core/coordination/watcher.js +128 -0
  42. package/dist/src/core/{routing → delegation}/first-party-skills.js +25 -13
  43. package/dist/src/core/{routing → delegation}/handoff.js +130 -63
  44. package/dist/src/core/discovery/candidate-intelligence-evidence.js +108 -0
  45. package/dist/src/core/discovery/candidate-intelligence-types.js +1 -0
  46. package/dist/src/core/discovery/candidate-intelligence-validation.js +108 -0
  47. package/dist/src/core/discovery/candidate-intelligence.js +3 -214
  48. package/dist/src/core/discovery/community.js +12 -4
  49. package/dist/src/core/discovery/github-discovery.js +6 -2
  50. package/dist/src/core/discovery/private-discovery.js +6 -2
  51. package/dist/src/core/install/reconcile.js +1 -1
  52. package/dist/src/core/install/source.js +21 -7
  53. package/dist/src/core/install/uninstall.js +39 -3
  54. package/dist/src/core/reporting/cli-guide.js +10 -6
  55. package/dist/src/core/reporting/completion.js +61 -109
  56. package/dist/src/core/reporting/doctor.js +4 -6
  57. package/dist/src/core/runtime/bounded-json.js +65 -0
  58. package/dist/src/core/runtime/github.js +30 -16
  59. package/dist/src/core/runtime/mcp-recipes.js +1 -1
  60. package/dist/src/core/workspace/active-policy.js +1 -1
  61. package/docs/CANDIDATE_INTELLIGENCE.md +9 -2
  62. package/docs/CATALOG.md +1 -1
  63. package/docs/CREDENTIAL_AND_UPDATE_POLICY.md +1 -1
  64. package/docs/DEMO_SCRIPT.md +19 -23
  65. package/docs/DISCOVERED.md +251 -250
  66. package/docs/FEATURE_TEST_MATRIX.md +10 -263
  67. package/docs/GITHUB_AUTHORIZATION.md +5 -0
  68. package/docs/LIVE_COLLABORATION.md +234 -0
  69. package/docs/PROVENANCE_AND_COMPARISON.md +1 -1
  70. package/docs/REFERENCE.md +163 -0
  71. package/docs/RELEASE_REVIEW.md +1 -2
  72. package/docs/TESTING.md +17 -1
  73. package/docs/USER_TEST_GUIDE.md +138 -3
  74. package/docs/assets/loadout-discover-activate.webp +0 -0
  75. package/docs/assets/loadout-handoff-coordinate.webp +0 -0
  76. package/docs/assets/loadout-social-preview.png +0 -0
  77. package/docs/decisions/001-coordination-jsonl-locking.md +35 -0
  78. package/docs/decisions/002-local-daemon-authentication.md +32 -0
  79. package/docs/decisions/003-bounded-agent-discussions.md +91 -0
  80. package/docs/specs/BOUNDED_AGENT_DISCUSSIONS.md +169 -0
  81. package/docs/superpowers/plans/2026-09-03-coordination-hardening.md +231 -0
  82. package/docs/superpowers/plans/2026-09-03-release-readiness.md +232 -0
  83. package/docs/superpowers/plans/2026-09-04-bounded-agent-discussions.md +121 -0
  84. package/package.json +18 -7
  85. package/skills/loadout-handoff/SKILL.md +238 -0
  86. package/MASTER_PLAN.md +0 -2207
  87. package/dist/src/core/routing/route.js +0 -539
  88. package/docs/ACTIVE_SET.md +0 -53
  89. package/docs/COMPATIBILITY_POLICY.md +0 -22
  90. package/docs/CONVERSION_AND_SANDBOX.md +0 -27
  91. package/docs/EVALUATION_PROTOCOL_V1.md +0 -300
  92. package/docs/HEAD_TO_HEAD_EVALUATION.md +0 -79
  93. package/docs/PROVIDER_CONFIGURATION.md +0 -45
  94. package/docs/README_RESEARCH.md +0 -36
  95. package/docs/REPOSITORY_STABILIZATION.md +0 -190
  96. package/docs/SAFE_UPDATE_DEMO.md +0 -25
  97. package/docs/SCHEMA_DECISIONS.md +0 -25
  98. package/docs/SUBMISSION_COPY.md +0 -90
  99. package/docs/TEAM_POLICY.md +0 -18
  100. package/docs/assets/loadout-workflow.png +0 -0
  101. package/docs/superpowers/plans/2026-07-19-relatable-readme-hero.md +0 -283
  102. package/docs/superpowers/plans/2026-07-20-loadout-readme-explainer.md +0 -116
  103. package/docs/superpowers/plans/2026-07-20-project-activation-safety.md +0 -469
  104. package/docs/superpowers/specs/2026-07-19-relatable-readme-hero-design.md +0 -80
  105. package/docs/superpowers/specs/2026-07-20-loadout-readme-explainer-design.md +0 -55
  106. package/docs/superpowers/specs/2026-07-20-project-activation-safety-design.md +0 -228
  107. package/skills/loadout-router/SKILL.md +0 -120
  108. /package/dist/src/core/{routing → agents}/credentials.js +0 -0
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Crash recovery for the coordination daemon.
3
+ *
4
+ * - PID file management for singleton daemon
5
+ * - Stale PID detection and cleanup
6
+ * - State persistence and recovery
7
+ * - Kill switch: immediately halt all coordination
8
+ */
9
+ import { readFile, writeFile, unlink, mkdir } from "node:fs/promises";
10
+ import { join } from "node:path";
11
+ const COORD_DIR = ".handoff";
12
+ const PID_FILE = "daemon.pid";
13
+ const KILL_SWITCH_FILE = "KILL_SWITCH";
14
+ /**
15
+ * Write the daemon PID file.
16
+ */
17
+ export async function writePidFile(projectRoot, port) {
18
+ const dir = join(projectRoot, COORD_DIR);
19
+ await mkdir(dir, { recursive: true });
20
+ const info = {
21
+ pid: process.pid,
22
+ port,
23
+ startedAt: new Date().toISOString(),
24
+ projectRoot,
25
+ };
26
+ await writeFile(join(dir, PID_FILE), JSON.stringify(info, null, 2) + "\n", {
27
+ encoding: "utf-8",
28
+ mode: 0o600,
29
+ });
30
+ }
31
+ /**
32
+ * Read the daemon PID file.
33
+ */
34
+ export async function readPidFile(projectRoot) {
35
+ try {
36
+ const raw = await readFile(join(projectRoot, COORD_DIR, PID_FILE), "utf-8");
37
+ return JSON.parse(raw);
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ /**
44
+ * Remove the daemon PID file.
45
+ */
46
+ export async function removePidFile(projectRoot) {
47
+ try {
48
+ await unlink(join(projectRoot, COORD_DIR, PID_FILE));
49
+ }
50
+ catch {
51
+ // Already removed
52
+ }
53
+ }
54
+ /**
55
+ * Check if a daemon process is still running.
56
+ */
57
+ export function isProcessRunning(pid) {
58
+ try {
59
+ process.kill(pid, 0);
60
+ return true;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ /**
67
+ * Check if a daemon is running for this project.
68
+ * If the PID file exists but the process is dead, clean up.
69
+ */
70
+ export async function getDaemonStatus(projectRoot) {
71
+ const info = await readPidFile(projectRoot);
72
+ if (!info) {
73
+ return { running: false, info: null, stale: false };
74
+ }
75
+ if (isProcessRunning(info.pid)) {
76
+ return { running: true, info, stale: false };
77
+ }
78
+ // Stale PID file — process died without cleanup
79
+ await removePidFile(projectRoot);
80
+ return { running: false, info, stale: true };
81
+ }
82
+ /**
83
+ * Stop a running daemon by sending SIGTERM.
84
+ */
85
+ export async function stopDaemon(projectRoot) {
86
+ const status = await getDaemonStatus(projectRoot);
87
+ if (!status.running) {
88
+ if (status.stale) {
89
+ return { stopped: false, pid: status.info.pid, stale: true };
90
+ }
91
+ return { stopped: false };
92
+ }
93
+ try {
94
+ process.kill(status.info.pid, "SIGTERM");
95
+ await removePidFile(projectRoot);
96
+ return { stopped: true, pid: status.info.pid };
97
+ }
98
+ catch {
99
+ return { stopped: false, pid: status.info.pid };
100
+ }
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // Kill switch
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Activate the kill switch — immediately halts all coordination.
107
+ *
108
+ * Creates a KILL_SWITCH file that the daemon, watcher, and adapters
109
+ * check before any operation. While active:
110
+ * - Daemon refuses new events
111
+ * - Watcher stops broadcasting
112
+ * - Adapters refuse to inject
113
+ * - CLI commands print a warning
114
+ */
115
+ export async function activateKillSwitch(projectRoot, reason) {
116
+ const dir = join(projectRoot, COORD_DIR);
117
+ await mkdir(dir, { recursive: true });
118
+ const data = {
119
+ activatedAt: new Date().toISOString(),
120
+ activatedBy: "user",
121
+ reason,
122
+ };
123
+ await writeFile(join(dir, KILL_SWITCH_FILE), JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 0o600 });
124
+ // Also stop the daemon if running
125
+ await stopDaemon(projectRoot);
126
+ }
127
+ /**
128
+ * Deactivate the kill switch — resume coordination.
129
+ */
130
+ export async function deactivateKillSwitch(projectRoot) {
131
+ try {
132
+ await unlink(join(projectRoot, COORD_DIR, KILL_SWITCH_FILE));
133
+ return true;
134
+ }
135
+ catch {
136
+ return false;
137
+ }
138
+ }
139
+ /**
140
+ * Check if the kill switch is active.
141
+ */
142
+ export async function isKillSwitchActive(projectRoot) {
143
+ let raw;
144
+ try {
145
+ raw = await readFile(join(projectRoot, COORD_DIR, KILL_SWITCH_FILE), "utf-8");
146
+ }
147
+ catch (error) {
148
+ if (typeof error === "object" &&
149
+ error !== null &&
150
+ "code" in error &&
151
+ error.code === "ENOENT") {
152
+ return { active: false };
153
+ }
154
+ return { active: true, reason: "Kill-switch file is unreadable" };
155
+ }
156
+ try {
157
+ const data = JSON.parse(raw);
158
+ return {
159
+ active: true,
160
+ ...(typeof data.reason === "string" ? { reason: data.reason } : {}),
161
+ ...(typeof data.activatedAt === "string"
162
+ ? { activatedAt: data.activatedAt }
163
+ : {}),
164
+ };
165
+ }
166
+ catch {
167
+ return { active: true, reason: "Kill-switch file is unreadable" };
168
+ }
169
+ }