@primitive.ai/prim 0.1.0-alpha.34 → 0.1.0-alpha.36
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/README.md +29 -11
- package/SKILL.md +16 -12
- package/dist/{chunk-4QJOQIY6.js → chunk-AAGJFO7C.js} +11 -0
- package/dist/chunk-LUPD2JSH.js +78 -0
- package/dist/hooks/post-tool-use.js +8 -1
- package/dist/hooks/pre-tool-use.js +7 -0
- package/dist/hooks/prim-hook.js +11 -6
- package/dist/index.js +803 -168
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
# @primitive.ai/prim
|
|
2
2
|
|
|
3
3
|
The official CLI for [Primitive](https://getprimitive.ai)'s **decision graph**. It
|
|
4
|
-
passively captures the decisions your team makes while coding
|
|
5
|
-
|
|
6
|
-
line and via session + git hooks.
|
|
4
|
+
passively captures the decisions your team makes while coding and reports team
|
|
5
|
+
presence — from the command line and via session + git hooks.
|
|
7
6
|
|
|
8
7
|
> [!WARNING]
|
|
9
8
|
> This project is in **alpha**. Commands and APIs may change between releases.
|
|
10
9
|
|
|
10
|
+
> [!NOTE]
|
|
11
|
+
> **Conflict Gates** check each edit against the decision graph and surface any
|
|
12
|
+
> load-bearing decision it conflicts with; their **Enforcement** tier blocks or pauses
|
|
13
|
+
> a conflicting edit until you reconcile and retry. Conflict Gates are **not currently
|
|
14
|
+
> enabled** — automatic decision capture runs regardless. To enable them for your team,
|
|
15
|
+
> contact **support@getprimitive.ai**.
|
|
16
|
+
|
|
11
17
|
## Installation
|
|
12
18
|
|
|
13
19
|
Requires Node.js 20+.
|
|
@@ -37,7 +43,7 @@ Or run the steps individually:
|
|
|
37
43
|
# 1. Authenticate via browser (WorkOS OAuth)
|
|
38
44
|
prim auth login
|
|
39
45
|
|
|
40
|
-
# 2. Wire the session hooks (decision capture +
|
|
46
|
+
# 2. Wire the session hooks (decision capture + presence)
|
|
41
47
|
prim claude install # or: prim codex install / prim hermes install
|
|
42
48
|
|
|
43
49
|
# 3. Start the companion daemon (latency + team presence)
|
|
@@ -94,7 +100,7 @@ prim auth status # Check authentication status
|
|
|
94
100
|
### Session integration
|
|
95
101
|
|
|
96
102
|
Wires the agent's session hooks so the decisions you make are captured into the
|
|
97
|
-
graph,
|
|
103
|
+
graph, and presence is reported. Each hook
|
|
98
104
|
self-resolves the CLI at run time (PATH, then a local install, then
|
|
99
105
|
`npx --yes @latest`), so it keeps working with no global install.
|
|
100
106
|
|
|
@@ -147,9 +153,12 @@ would create a cycle (exit 2); an unresolved id exits 4.
|
|
|
147
153
|
### Reconcile
|
|
148
154
|
|
|
149
155
|
```bash
|
|
150
|
-
prim reconcile <id> # Mint a single-use bypass for a decision
|
|
156
|
+
prim reconcile <id> # Mint a single-use bypass for a decision Conflict Gates flagged
|
|
151
157
|
```
|
|
152
158
|
|
|
159
|
+
Part of Conflict Gates **Enforcement**, which is not currently enabled (see the note
|
|
160
|
+
at the top). Contact support@getprimitive.ai to enable it.
|
|
161
|
+
|
|
153
162
|
### Hooks
|
|
154
163
|
|
|
155
164
|
```bash
|
|
@@ -192,13 +201,22 @@ prim moves flush # Drain the local journals to the server (also runs fr
|
|
|
192
201
|
### Skill
|
|
193
202
|
|
|
194
203
|
```bash
|
|
195
|
-
prim skill install
|
|
196
|
-
prim skill
|
|
197
|
-
prim skill
|
|
204
|
+
prim skill install --agent claude # Install the decision-graph guide for Claude Code
|
|
205
|
+
prim skill install --agent codex # …or write the guide into another agent's rules file
|
|
206
|
+
prim skill uninstall --agent claude # Remove it
|
|
207
|
+
prim skill status --agent claude # Report whether it's installed
|
|
198
208
|
```
|
|
199
209
|
|
|
200
|
-
|
|
201
|
-
|
|
210
|
+
Teaches your agent how to work with the decision graph. For **Claude Code**
|
|
211
|
+
(`--agent claude`) this installs a skills-directory plugin at
|
|
212
|
+
`<repo>/.claude/skills/prim/` (or `~/.claude/skills/prim/` with `--scope user`)
|
|
213
|
+
— a `.claude-plugin/plugin.json` + `SKILL.md` that auto-loads as the model-invoked
|
|
214
|
+
`prim@skills-dir` skill, no marketplace step; restart Claude Code or run
|
|
215
|
+
`/reload-plugins` after installing. For every other agent it writes a managed
|
|
216
|
+
block into the rules file that agent reads (`--agent codex` → AGENTS.md,
|
|
217
|
+
`--agent hermes` → .hermes.md, or an auto-detected .cursor/rules, …). A bare
|
|
218
|
+
`prim skill install` (no `--agent`) auto-detects a rules file and writes the
|
|
219
|
+
block; pass `--target <path>` for an explicit file.
|
|
202
220
|
|
|
203
221
|
## Development
|
|
204
222
|
|
package/SKILL.md
CHANGED
|
@@ -9,9 +9,9 @@ description: Use the prim CLI for Primitive's decision graph — passive decisio
|
|
|
9
9
|
|
|
10
10
|
## Mental model
|
|
11
11
|
|
|
12
|
-
As your team codes, prim passively captures the **decisions** you make -- which library, which pattern, which config value -- into a queryable graph, and links them: a decision can depend on earlier decisions (auto-linked from shared files, or related by hand — see *Relate decisions*) and reference the files it touched.
|
|
12
|
+
As your team codes, prim passively captures the **decisions** you make -- which library, which pattern, which config value -- into a queryable graph, and links them: a decision can depend on earlier decisions (auto-linked from shared files, or related by hand — see *Relate decisions*) and reference the files it touched. **Conflict Gates** can check a later change against that graph and surface any load-bearing decision it conflicts with; with **Enforcement**, prim blocks the edit until you reconcile the decision and retry. Conflict Gates are **not currently enabled** — capture runs regardless. To enable them for your team, contact support@getprimitive.ai.
|
|
13
13
|
|
|
14
|
-
You never invoke capture. It runs automatically through the session hooks installed by `npx --yes @primitive.ai/prim claude install` (Claude Code), `npx --yes @primitive.ai/prim codex install` (Codex), or `npx --yes @primitive.ai/prim hermes install` (Hermes). Your job is to **
|
|
14
|
+
You never invoke capture. It runs automatically through the session hooks installed by `npx --yes @primitive.ai/prim claude install` (Claude Code), `npx --yes @primitive.ai/prim codex install` (Codex), or `npx --yes @primitive.ai/prim hermes install` (Hermes). Your job is to **read** the graph before load-bearing edits and **answer** the occasional rationale confirmation. (Responding to Conflict Gates applies only once Enforcement is enabled — see below.)
|
|
15
15
|
|
|
16
16
|
## Auth
|
|
17
17
|
|
|
@@ -29,17 +29,19 @@ The CLI auto-refreshes a still-valid session from the stored refresh token (proa
|
|
|
29
29
|
|
|
30
30
|
1. Every command accepts `--help`. When unsure of flags, run `npx --yes @primitive.ai/prim <cmd> --help` rather than guessing.
|
|
31
31
|
2. The CLI prints API errors as one-liners to stderr and exits non-zero. Treat any non-zero exit as actionable. If auth-related, re-check `auth status`.
|
|
32
|
-
3. `<idOrShortId>` arguments accept either a full decision ID or the short ID shown in feeds and gate reasons.
|
|
32
|
+
3. `<idOrShortId>` arguments accept either a full decision ID or the short ID shown in feeds (and gate reasons, when Conflict Gates are enabled).
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## Conflict Gates & Enforcement (not currently enabled)
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
**Conflict Gates** check each edit against the decision graph before it lands and surface any load-bearing decision it conflicts with. Their **Enforcement** tier goes further -- a conflicting edit is blocked (or paused for confirmation) until you reconcile the decision and retry. **Conflict Gates are not currently enabled** — automatic decision capture (above) runs regardless. To enable Conflict Gates and Enforcement for your team, contact support@getprimitive.ai.
|
|
37
|
+
|
|
38
|
+
When Enforcement is enabled, before an edit (Claude Code: Edit/Write/MultiEdit; Codex: apply_patch; Hermes: write_file/patch) a PreToolUse hook scores the target file against the graph:
|
|
37
39
|
|
|
38
40
|
- **deny** -- the edit is blocked: it conflicts with a load-bearing prior decision. Don't fight it. Read the reason line; it names the decision id. If you genuinely intend to override that decision, run `npx --yes @primitive.ai/prim reconcile dec_<shortId>`, then retry the edit once. Otherwise choose an approach that respects the decision.
|
|
39
41
|
- **warn / additional context** -- the edit proceeds, but a relevant prior decision is surfaced. Read it. On Codex a would-be `ask` is delivered as allow-plus-context (Codex can't pause mid-tool), so that context is your only signal -- read it before continuing. Hermes has no soft-confirm tier, so a would-be `ask` arrives as a **deny** carrying the same reconcile directive: reconcile and retry, or set `PRIM_HOOK_MODE=warn` to downgrade it to context-only.
|
|
40
42
|
- **"decision check skipped / not verified" or "... partial / truncated"** -- the check could not fully run. Treat constraints as UNKNOWN, not clear; never read silence as approval.
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
When enabled, the gate fail-opens on its *own* infrastructure errors (no daemon, network blip, org-unbound token) -- a setup problem would not block your edit. That is why an "unavailable" note would matter: it is the honest signal that the check, not your edit, is what failed.
|
|
43
45
|
|
|
44
46
|
## Read the graph before large or load-bearing edits
|
|
45
47
|
|
|
@@ -49,6 +51,8 @@ The gate fail-opens on its *own* infrastructure errors (no daemon, network blip,
|
|
|
49
51
|
|
|
50
52
|
## Reconcile and the verdict footer
|
|
51
53
|
|
|
54
|
+
Reconcile and the verdict footer are part of Conflict Gates **Enforcement**, which is **not currently enabled** (contact support@getprimitive.ai to turn it on); the `reconcile` command stays available regardless. When Enforcement is on:
|
|
55
|
+
|
|
52
56
|
`npx --yes @primitive.ai/prim reconcile <idOrShortId>` mints a single-use bypass for the named decision -- it prints `[prim] reconcile bypass issued for dec_<short> (expires in ...)` to STDERR, with the bypass JSON on STDOUT. Your *next* edit to the governed file then goes through, and on that edit prim prints a verdict footer to STDERR -- confirmation the override was recorded, not silently dropped:
|
|
53
57
|
|
|
54
58
|
```
|
|
@@ -75,7 +79,7 @@ Capture is automatic for the decisions you *make while coding*. When the user in
|
|
|
75
79
|
npx --yes @primitive.ai/prim decisions create --intent "Adopt prosemirror-collab over Yjs" --area data --rationale "Server-authoritative ordering" --alternatives "Yjs,Automerge"
|
|
76
80
|
```
|
|
77
81
|
|
|
78
|
-
Only `--intent` is required. Optional: `--kind` (change|exploration|task_execution|unclear, default change), `--rationale`, `--area`, `--decided`, `--alternatives` (comma-separated), `--confidence` (high|medium|low, default high), `--reversibility` (high|low, default high), and `--files` (comma-separated repo-relative paths the decision governs —
|
|
82
|
+
Only `--intent` is required. Optional: `--kind` (change|exploration|task_execution|unclear, default change), `--rationale`, `--area`, `--decided`, `--alternatives` (comma-separated), `--confidence` (high|medium|low, default high), `--reversibility` (high|low, default high), and `--files` (comma-separated repo-relative paths the decision governs — these are the files Conflict Gates would check on later edits, same path form as `decisions check`; Conflict Gates are not currently enabled). STDOUT is the created identity `{ decisionId, shortId, createdAt }`; STDERR prints `[prim] created dec_<short>.` — pass that `dec_<short>` straight into `decisions show` / `cascade` / `confirm`. Author on the user's behalf only when they ask for a decision to be recorded; don't narrate your own routine edits into the graph (the hooks already do that).
|
|
79
83
|
|
|
80
84
|
## Relate decisions (link / unlink)
|
|
81
85
|
|
|
@@ -116,14 +120,14 @@ npx --yes @primitive.ai/prim hooks uninstall
|
|
|
116
120
|
|
|
117
121
|
Under `CI=1` (or with `--non-interactive`), `hooks install` fails fast in a Husky repo unless `--yes` or `--target` is set; the error names both escapes. `hooks uninstall` only removes the `.git/hooks` copies — if a hook was installed into `.husky/`, remove the prim block from that file manually. To suppress the hooks for one commit, use `git commit --no-verify`.
|
|
118
122
|
|
|
119
|
-
These git hooks are separate from the **session hooks** (`claude install` / `codex install` / `hermes install`) that drive in-session capture and
|
|
123
|
+
These git hooks are separate from the **session hooks** (`claude install` / `codex install` / `hermes install`) that drive in-session capture (and Conflict Gates, when enabled).
|
|
120
124
|
|
|
121
125
|
## Output formats
|
|
122
126
|
|
|
123
127
|
The CLI keeps STDOUT machine-readable and STDERR human-readable. The `decisions` and `reconcile` commands **always** emit a single JSON document on STDOUT — no flag needed; pipe straight to `jq`. The `decisions` commands have **no** `--json` flag and reject one; `reconcile` accepts a reserved no-op `--json`. `auth status` and `skill status` default to human-readable STDOUT and take `--json` to switch to JSON.
|
|
124
128
|
|
|
125
129
|
- **STDOUT is machine-readable** — JSON (one document per invocation). `decisions` reads project lean shapes, not raw rows.
|
|
126
|
-
- **STDERR is human-readable** — a verdict-first line, plus the gate/verdict-footer
|
|
130
|
+
- **STDERR is human-readable** — a verdict-first line, plus presence notes (and, when Conflict Gates are enabled, the gate/verdict-footer notes).
|
|
127
131
|
- **Exit code is authoritative** where it carries meaning — `auth status` exits 0 when authenticated; `decisions show`/`cascade`/`confirm` exit non-zero (e.g. 4 not-found) on a missing or unauthorized id.
|
|
128
132
|
|
|
129
133
|
Examples:
|
|
@@ -135,12 +139,12 @@ Examples:
|
|
|
135
139
|
|
|
136
140
|
## Pitfalls
|
|
137
141
|
|
|
138
|
-
- **An "unavailable" / "not verified"
|
|
139
|
-
- **
|
|
142
|
+
- **An "unavailable" / "not verified" decision check is not an all-clear.** Treat constraints as UNKNOWN and proceed deliberately; never read the silence as approval — the same holds for Conflict Gates once enabled.
|
|
143
|
+
- **When Enforcement is enabled, a `deny` means a real prior decision conflicts.** Reconcile only when you genuinely intend to override it; otherwise pick an approach that respects it.
|
|
140
144
|
- **Reconcile bypasses are single-use and short-lived.** One bypass clears your *next* edit to the governed file; it is not a standing override.
|
|
141
145
|
- **Capture of your coding activity is automatic, never manual.** If decisions aren't showing up, check that the session hooks are installed (`claude status` / `codex status` / `hermes status`) and the daemon is running — don't try to inject moves by hand. (Deliberately *authoring* a decision the user asks you to record is a separate, supported path — `decisions create`, above.)
|
|
142
146
|
- **Don't fabricate rationale on a confirmation.** If you don't know why a decision was made, say so rather than guessing.
|
|
143
147
|
|
|
144
148
|
## After each task
|
|
145
149
|
|
|
146
|
-
If
|
|
150
|
+
If Conflict Gates are enabled and one denied or warned you, report which decision(s) it named and whether you reconciled. If you read the graph before a load-bearing change, note what you found so the user can verify in the dashboard.
|
|
@@ -54,6 +54,16 @@ function colorForArea(area) {
|
|
|
54
54
|
}
|
|
55
55
|
return AREA_COLORS[area] ?? "gray";
|
|
56
56
|
}
|
|
57
|
+
function stripControlChars(text) {
|
|
58
|
+
let out = "";
|
|
59
|
+
for (const ch of text) {
|
|
60
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
61
|
+
if (code > 31 && !(code >= 127 && code <= 159)) {
|
|
62
|
+
out += ch;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
57
67
|
function stripAnsi(text) {
|
|
58
68
|
return text.replace(/\u001b\[[0-9;]*m/g, "");
|
|
59
69
|
}
|
|
@@ -63,5 +73,6 @@ export {
|
|
|
63
73
|
dim,
|
|
64
74
|
bold,
|
|
65
75
|
colorForArea,
|
|
76
|
+
stripControlChars,
|
|
66
77
|
stripAnsi
|
|
67
78
|
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// src/lib/activation.ts
|
|
2
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
|
|
7
|
+
// src/lib/git.ts
|
|
8
|
+
import { execFileSync } from "child_process";
|
|
9
|
+
function gitToplevel(cwd) {
|
|
10
|
+
try {
|
|
11
|
+
return execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
12
|
+
cwd,
|
|
13
|
+
encoding: "utf-8",
|
|
14
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
15
|
+
}).trim();
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/lib/activation.ts
|
|
22
|
+
var PRIM_ACTIVE_KEY = "prim.active";
|
|
23
|
+
var PROJECT_INSTALL_FILES = [".claude/settings.json", ".codex/hooks.json"];
|
|
24
|
+
var PRIM_HOOK_BINS = ["prim-hook", "prim-pre-tool-use", "prim-post-tool-use"];
|
|
25
|
+
function repoActiveFlag(cwd) {
|
|
26
|
+
try {
|
|
27
|
+
const value = execFileSync2("git", ["config", "--get", PRIM_ACTIVE_KEY], {
|
|
28
|
+
cwd,
|
|
29
|
+
encoding: "utf-8",
|
|
30
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
31
|
+
}).trim();
|
|
32
|
+
if (value === "true") return "true";
|
|
33
|
+
if (value === "false") return "false";
|
|
34
|
+
return void 0;
|
|
35
|
+
} catch {
|
|
36
|
+
return void 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function setRepoActive(cwd, active) {
|
|
40
|
+
execFileSync2("git", ["config", "--local", PRIM_ACTIVE_KEY, active ? "true" : "false"], {
|
|
41
|
+
cwd,
|
|
42
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function activateRepoBestEffort(cwd) {
|
|
46
|
+
try {
|
|
47
|
+
setRepoActive(cwd, true);
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function hasProjectPrimInstall(cwd) {
|
|
52
|
+
const root = gitToplevel(cwd);
|
|
53
|
+
if (root === null || root === homedir()) return false;
|
|
54
|
+
for (const rel of PROJECT_INSTALL_FILES) {
|
|
55
|
+
const path = join(root, rel);
|
|
56
|
+
if (existsSync(path)) {
|
|
57
|
+
try {
|
|
58
|
+
const content = readFileSync(path, "utf-8");
|
|
59
|
+
if (PRIM_HOOK_BINS.some((bin) => content.includes(bin))) return true;
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
function isRepoActiveForCapture(cwd) {
|
|
67
|
+
const flag = repoActiveFlag(cwd);
|
|
68
|
+
if (flag === "true") return true;
|
|
69
|
+
if (flag === "false") return false;
|
|
70
|
+
return hasProjectPrimInstall(cwd);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
gitToplevel,
|
|
75
|
+
setRepoActive,
|
|
76
|
+
activateRepoBestEffort,
|
|
77
|
+
isRepoActiveForCapture
|
|
78
|
+
};
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
bold,
|
|
4
4
|
color
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-AAGJFO7C.js";
|
|
6
6
|
import {
|
|
7
7
|
scrubFromCwd
|
|
8
8
|
} from "../chunk-6LAQVM26.js";
|
|
9
9
|
import {
|
|
10
10
|
toMove
|
|
11
11
|
} from "../chunk-S2O4P4A3.js";
|
|
12
|
+
import {
|
|
13
|
+
isRepoActiveForCapture
|
|
14
|
+
} from "../chunk-LUPD2JSH.js";
|
|
12
15
|
import {
|
|
13
16
|
getClient
|
|
14
17
|
} from "../chunk-26VA3ADF.js";
|
|
@@ -128,6 +131,10 @@ async function main() {
|
|
|
128
131
|
return;
|
|
129
132
|
}
|
|
130
133
|
const cwd = parsed.cwd ?? process.cwd();
|
|
134
|
+
if (!isRepoActiveForCapture(cwd)) {
|
|
135
|
+
emit();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
131
138
|
const base = toMove(parsed, resolveCliVersion(), agent);
|
|
132
139
|
const move = { ...base, payload: scrubFromCwd(parsed, cwd) };
|
|
133
140
|
try {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isRepoActiveForCapture
|
|
4
|
+
} from "../chunk-LUPD2JSH.js";
|
|
2
5
|
import {
|
|
3
6
|
getClient,
|
|
4
7
|
getSiteUrl
|
|
@@ -295,6 +298,10 @@ async function main() {
|
|
|
295
298
|
emit(failOpen());
|
|
296
299
|
return;
|
|
297
300
|
}
|
|
301
|
+
if (!isRepoActiveForCapture(cwd)) {
|
|
302
|
+
emit(failOpen());
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
298
305
|
let results;
|
|
299
306
|
try {
|
|
300
307
|
results = await Promise.all(files.map((f) => checkOneFile(f)));
|
package/dist/hooks/prim-hook.js
CHANGED
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
shouldFlushAfter,
|
|
11
11
|
toMove
|
|
12
12
|
} from "../chunk-S2O4P4A3.js";
|
|
13
|
+
import {
|
|
14
|
+
isRepoActiveForCapture
|
|
15
|
+
} from "../chunk-LUPD2JSH.js";
|
|
13
16
|
import "../chunk-26VA3ADF.js";
|
|
14
17
|
import {
|
|
15
18
|
normalizeEnvelope,
|
|
@@ -42,12 +45,14 @@ try {
|
|
|
42
45
|
const raw = readFileSync(0, "utf-8");
|
|
43
46
|
const parsed = normalizeEnvelope(JSON.parse(raw), agent);
|
|
44
47
|
const cwd = parsed.cwd ?? process.cwd();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
if (isRepoActiveForCapture(cwd)) {
|
|
49
|
+
const base = toMove(parsed, resolveCliVersion(), agent);
|
|
50
|
+
const move = { ...base, payload: scrubFromCwd(parsed, cwd) };
|
|
51
|
+
const { orgId } = resolveOrg({ sessionId: move.sessionId, cwd: move.env.cwd });
|
|
52
|
+
appendMove(move, orgId);
|
|
53
|
+
if (shouldFlushAfter(move.eventType)) {
|
|
54
|
+
spawnBackgroundFlush();
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
} catch (err) {
|
|
53
58
|
if (process.env.PRIM_HOOK_DEBUG) {
|