@bli-cockpit/cli 0.2.48 → 0.2.50

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 (83) hide show
  1. package/dist/adapters/raw-evidence-attribution-gaps.js +133 -0
  2. package/dist/adapters/raw-evidence-claude-reader.js +108 -0
  3. package/dist/adapters/raw-evidence-codex-reader.js +147 -0
  4. package/dist/adapters/raw-evidence-collection-state.js +199 -0
  5. package/dist/adapters/raw-evidence-facts.js +338 -0
  6. package/dist/adapters/raw-evidence-git-diff-reader.js +187 -0
  7. package/dist/adapters/raw-evidence-image-reader.js +107 -0
  8. package/dist/adapters/raw-evidence-sanitize.js +56 -0
  9. package/dist/adapters/raw-evidence-transcript-file.js +182 -0
  10. package/dist/adapters/raw-evidence.js +94 -1203
  11. package/dist/autostart-contract.js +79 -0
  12. package/dist/autostart-darwin-plist.js +265 -0
  13. package/dist/autostart-darwin.js +171 -0
  14. package/dist/autostart-windows-scripts.js +310 -0
  15. package/dist/autostart-windows-task-xml.js +260 -0
  16. package/dist/autostart-windows.js +237 -0
  17. package/dist/autostart-xml.js +23 -0
  18. package/dist/autostart.js +35 -1148
  19. package/dist/commands/agent-rules-command.js +55 -0
  20. package/dist/commands/agent-session-report.js +290 -0
  21. package/dist/commands/analyze.js +131 -0
  22. package/dist/commands/autostart-command.js +105 -0
  23. package/dist/commands/backfill-batches.js +34 -0
  24. package/dist/commands/backfill-candidates.js +54 -0
  25. package/dist/commands/backfill-checkpoint.js +101 -0
  26. package/dist/commands/backfill-command-line.js +70 -0
  27. package/dist/commands/backfill-evidence-outcomes.js +104 -0
  28. package/dist/commands/backfill-issues.js +265 -0
  29. package/dist/commands/backfill-output.js +75 -0
  30. package/dist/commands/backfill-plan.js +71 -0
  31. package/dist/commands/backfill-reasons.js +107 -0
  32. package/dist/commands/backfill-report.js +298 -0
  33. package/dist/commands/backfill-result.js +150 -0
  34. package/dist/commands/backfill-scan.js +274 -0
  35. package/dist/commands/backfill-scope.js +114 -0
  36. package/dist/commands/backfill-session-report.js +145 -0
  37. package/dist/commands/backfill-types.js +1 -0
  38. package/dist/commands/backfill-upload.js +212 -0
  39. package/dist/commands/backfill.js +58 -1705
  40. package/dist/commands/cli-io.js +13 -0
  41. package/dist/commands/doctor.js +57 -0
  42. package/dist/commands/jarvis-trace.js +184 -0
  43. package/dist/commands/jarvis.js +323 -7
  44. package/dist/commands/local-arg-values.js +169 -0
  45. package/dist/commands/local-args-collector.js +604 -0
  46. package/dist/commands/local-args-tower.js +891 -0
  47. package/dist/commands/local-args.js +10 -1549
  48. package/dist/commands/local-help.js +30 -5
  49. package/dist/commands/local.js +21 -1786
  50. package/dist/commands/login.js +53 -0
  51. package/dist/commands/logout.js +66 -0
  52. package/dist/commands/memory-install-claude.js +294 -0
  53. package/dist/commands/memory-install-codex.js +205 -0
  54. package/dist/commands/memory-install-contract.js +231 -0
  55. package/dist/commands/memory-install-files.js +63 -0
  56. package/dist/commands/memory-install-skills.js +121 -0
  57. package/dist/commands/memory-install-toml.js +265 -0
  58. package/dist/commands/memory-install.js +378 -0
  59. package/dist/commands/onboard-receipts.js +66 -0
  60. package/dist/commands/onboard-report.js +274 -0
  61. package/dist/commands/onboard.js +449 -0
  62. package/dist/commands/ops-render.js +36 -0
  63. package/dist/commands/public-root.js +1 -1
  64. package/dist/commands/serve.js +13 -0
  65. package/dist/commands/session-sync.js +513 -534
  66. package/dist/commands/settings-render.js +28 -0
  67. package/dist/commands/settings.js +66 -2
  68. package/dist/commands/start.js +47 -0
  69. package/dist/commands/sync-followups.js +308 -0
  70. package/dist/commands/sync.js +387 -0
  71. package/dist/local-state-attributed-target.js +75 -0
  72. package/dist/local-state-config.js +147 -0
  73. package/dist/local-state-files.js +59 -0
  74. package/dist/local-state-identity.js +73 -0
  75. package/dist/local-state-pairing.js +263 -0
  76. package/dist/local-state-paths.js +61 -0
  77. package/dist/local-state-session.js +68 -0
  78. package/dist/local-state-status.js +163 -0
  79. package/dist/local-state-work-context.js +190 -0
  80. package/dist/local-state.js +34 -848
  81. package/dist/tower-client.js +3 -2
  82. package/dist/tower-stream.js +76 -6
  83. package/package.json +2 -1
@@ -0,0 +1,190 @@
1
+ import { LocalWorkContextSchema, } from "@bli-cockpit/telemetry-core";
2
+ import crypto from "node:crypto";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { ensureRuntimeDirectories, getCollectorRuntimePaths, workContextFile, } from "./local-state-paths.js";
6
+ import { readJsonFile, writeJsonFile } from "./local-state-files.js";
7
+ import { LOCAL_COLLECTOR_VERSION, readLocalCollectorConfig, } from "./local-state-config.js";
8
+ import { readLocalSessionReference } from "./local-state-session.js";
9
+ import { resolveIdentityOrFallback } from "./local-state-identity.js";
10
+ import { validateAttributedTargetIdentity } from "./local-state-attributed-target.js";
11
+ /** What `cockpit start` binds: the repo, branch and ticket this session's work belongs to. */
12
+ export async function startLocalWorkContext(options = {}) {
13
+ return writeLocalWorkContext(options);
14
+ }
15
+ /**
16
+ * Starts a context for a transcript-attributed sync target that does not exist
17
+ * in the current git inventory, such as an approved wrapper folder or a
18
+ * deleted repo reconstructed from transcript provenance. This internal path
19
+ * validates the exact target identity before writing any context state.
20
+ */
21
+ export async function startLocalWorkContextForAttributedTarget(options, attributedIdentity) {
22
+ const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
23
+ const identity = await validateAttributedTargetIdentity(repoRoot, attributedIdentity);
24
+ return writeLocalWorkContext(options, identity);
25
+ }
26
+ async function writeLocalWorkContext(options, attributedIdentity) {
27
+ if (options.activeTicketId && options.clearTicket) {
28
+ throw new Error("--ticket and --clear-ticket cannot be combined.");
29
+ }
30
+ const now = options.now ?? new Date();
31
+ const homeDir = options.homeDir ?? os.homedir();
32
+ const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
33
+ const paths = getCollectorRuntimePaths(homeDir);
34
+ await ensureRuntimeDirectories(paths);
35
+ const config = await readLocalCollectorConfig(paths).catch(() => null);
36
+ const session = await readLocalSessionReference(paths, {
37
+ operatorId: options.operatorId,
38
+ sessionId: options.sessionId,
39
+ });
40
+ const identity = attributedIdentity ??
41
+ (await resolveIdentityOrFallback(repoRoot, options.branch));
42
+ const branch = attributedIdentity
43
+ ? attributedIdentity.branch
44
+ : (options.branch ?? identity.branch);
45
+ const sessionId = options.sessionId ??
46
+ (session.session_state === "missing" ? `local-${crypto.randomUUID()}` : session.session_id);
47
+ const operatorId = options.operatorId ?? session.operator_id;
48
+ const deviceId = session.device_id ?? config?.device_id ?? "device-unknown";
49
+ const workContextId = stableWorkContextId({
50
+ operatorId,
51
+ deviceId,
52
+ repoFingerprint: identity.repo_fingerprint,
53
+ worktreeFingerprint: identity.worktree_fingerprint,
54
+ });
55
+ const existingContext = await readLocalWorkContextByFingerprint(paths, identity.worktree_fingerprint).catch(() => null);
56
+ const context = buildWorkContext({
57
+ options,
58
+ now,
59
+ identity,
60
+ branch,
61
+ operatorId,
62
+ sessionId,
63
+ workContextId,
64
+ existingContext,
65
+ });
66
+ await writeJsonFile(workContextFile(paths, identity.worktree_fingerprint), context);
67
+ await writeJsonFile(paths.active_work_context_file, context);
68
+ return context;
69
+ }
70
+ /**
71
+ * The context record itself, kept in one piece because it is a schema: every
72
+ * field an ambient envelope will later carry as provenance is decided here.
73
+ */
74
+ function buildWorkContext(input) {
75
+ const { options, now, identity, branch, operatorId, sessionId, workContextId, existingContext } = input;
76
+ const { activeTicketId, ticketBindingCandidates } = resolveTicketBinding(options, existingContext);
77
+ return LocalWorkContextSchema.parse({
78
+ work_context_id: workContextId,
79
+ repo: identity.repo_root,
80
+ branch,
81
+ repo_label: identity.repo_label,
82
+ repo_fingerprint: identity.repo_fingerprint,
83
+ repo_origin_url: identity.repo_origin_url ?? undefined,
84
+ head_sha: identity.head_sha ?? undefined,
85
+ worktree_label: identity.worktree_label,
86
+ worktree_fingerprint: identity.worktree_fingerprint,
87
+ worktree_is_primary: identity.worktree_is_primary,
88
+ operator_id: operatorId,
89
+ session_id: sessionId,
90
+ started_at: existingContext?.started_at ?? now.toISOString(),
91
+ updated_at: now.toISOString(),
92
+ active_ticket_id: activeTicketId,
93
+ ticket_binding_candidates: ticketBindingCandidates,
94
+ topic_label: options.topicLabel,
95
+ topic_summary_redacted: options.topicSummaryRedacted,
96
+ work_intent: options.workIntent,
97
+ work_phase: options.workPhase,
98
+ intent_source: options.intentSource,
99
+ intent_confidence: options.intentConfidence,
100
+ pull_request_url: existingContext?.pull_request_url,
101
+ provenance: {
102
+ capture_source: "collector_runtime",
103
+ capture_adapter_version: LOCAL_COLLECTOR_VERSION,
104
+ collector_version: LOCAL_COLLECTOR_VERSION,
105
+ repo: identity.repo_root,
106
+ branch,
107
+ repo_label: identity.repo_label,
108
+ repo_fingerprint: identity.repo_fingerprint,
109
+ repo_origin_url: identity.repo_origin_url ?? undefined,
110
+ worktree_label: identity.worktree_label,
111
+ worktree_fingerprint: identity.worktree_fingerprint,
112
+ worktree_is_primary: identity.worktree_is_primary,
113
+ operator_id: operatorId,
114
+ session_id: sessionId,
115
+ work_context_id: workContextId,
116
+ },
117
+ });
118
+ }
119
+ /**
120
+ * Three answers, not two: a named ticket binds, `--clear-ticket` unbinds, and
121
+ * saying neither leaves whatever the previous `cockpit start` bound in place.
122
+ */
123
+ // The return type is inferred deliberately: naming it would mean indexing the
124
+ // context schema by field name, and this module keeps its literals to the ones
125
+ // that reach disk.
126
+ function resolveTicketBinding(options, existingContext) {
127
+ const activeTicketId = options.clearTicket
128
+ ? undefined
129
+ : (options.activeTicketId ?? existingContext?.active_ticket_id);
130
+ const ticketBindingCandidates = options.activeTicketId
131
+ ? [
132
+ {
133
+ ticket_id: options.activeTicketId,
134
+ binding_source: "active_work_context",
135
+ confidence: 1,
136
+ evidence_labels: ["cockpit_start_ticket"],
137
+ },
138
+ ]
139
+ : options.clearTicket
140
+ ? []
141
+ : (existingContext?.ticket_binding_candidates ?? []);
142
+ return { activeTicketId, ticketBindingCandidates };
143
+ }
144
+ /** The active context: what the last `cockpit start` on this machine bound, whatever the folder. */
145
+ export async function readLocalWorkContext(paths) {
146
+ return LocalWorkContextSchema.parse(await readJsonFile(paths.active_work_context_file));
147
+ }
148
+ /**
149
+ * The context for ONE repo, because a machine running two checkouts at once
150
+ * would otherwise attribute both to whichever was started last.
151
+ */
152
+ export async function readLocalWorkContextForRepo(paths, repoRoot) {
153
+ const identity = await resolveIdentityOrFallback(repoRoot);
154
+ const context = await readLocalWorkContextByFingerprint(paths, identity.worktree_fingerprint).catch(() => null);
155
+ if (context)
156
+ return context;
157
+ const active = await readLocalWorkContext(paths);
158
+ if (active.worktree_fingerprint === identity.worktree_fingerprint ||
159
+ path.resolve(active.repo) === identity.repo_root) {
160
+ return active;
161
+ }
162
+ throw new Error(`Active work context missing for ${identity.worktree_label}. Run \`cockpit start --workspace "${identity.repo_root}"\`.`);
163
+ }
164
+ async function readLocalWorkContextByFingerprint(paths, worktreeFingerprint) {
165
+ return LocalWorkContextSchema.parse(await readJsonFile(workContextFile(paths, worktreeFingerprint)));
166
+ }
167
+ /**
168
+ * The same operator, device, repo and worktree must produce the same id on
169
+ * every run, because the ambient envelope joins sessions on it.
170
+ */
171
+ function stableWorkContextId(input) {
172
+ return `work-${sha256([
173
+ input.operatorId,
174
+ input.deviceId,
175
+ input.repoFingerprint,
176
+ input.worktreeFingerprint,
177
+ ].join(":")).slice(0, 32)}`;
178
+ }
179
+ function sha256(value) {
180
+ return crypto.createHash("sha256").update(value, "utf8").digest("hex");
181
+ }
182
+ /**
183
+ * The label a person reads for a work context — repo over worktree, so two
184
+ * checkouts of one repo are told apart at a glance.
185
+ */
186
+ export function workDisplayLabel(context) {
187
+ const repoLabel = (context.repo_label ?? path.basename(context.repo)) || "workspace";
188
+ const worktreeLabel = context.worktree_label ?? repoLabel;
189
+ return `${repoLabel}/${worktreeLabel}`;
190
+ }