@primitive.ai/prim 0.1.0-alpha.64 → 0.1.0-alpha.65
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 +5 -4
- package/dist/{chunk-7X7SFOPJ.js → chunk-5CKL5EYQ.js} +1 -1
- package/dist/{chunk-VYGY3OOX.js → chunk-BDGQEJA5.js} +1 -1
- package/dist/{chunk-MCPHIB4W.js → chunk-CPHJUQNE.js} +22 -8
- package/dist/{chunk-XTNMSS4C.js → chunk-TDRXHBEX.js} +15 -0
- package/dist/hooks/post-commit.js +2 -2
- package/dist/hooks/post-tool-use.js +3 -3
- package/dist/hooks/pre-tool-use.js +1 -1
- package/dist/hooks/prim-hook.js +3 -3
- package/dist/hooks/session-start.js +2 -2
- package/dist/index.js +61 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,12 +71,13 @@ so the agent runs it directly — instead of fetching a doc and executing a comm
|
|
|
71
71
|
it, which an auto-mode safety classifier blocks as untrusted-origin code:
|
|
72
72
|
|
|
73
73
|
```text
|
|
74
|
-
Install the Primitive CLI: run `npx --yes @primitive.ai/prim@latest setup` and surface its output.
|
|
74
|
+
Install the Primitive CLI and activate passive decision capture for this repository: run `npx --yes @primitive.ai/prim@latest setup` and surface its output. Drive it yourself; I'll only click Authorize in the browser. This request authorizes setup's built-in activation of this repository and an idempotent retry of that step, but not activation in another repository or creation of a Decision. If enable or health fails, surface the actual error; do not claim fresh activation approval is required. Then show me the welcome.
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
That single command runs the whole install
|
|
78
|
-
daemon → git hooks → skill → welcome). The detailed
|
|
79
|
-
and the manual fallback — live in
|
|
77
|
+
That single command runs the whole install and current-repository activation in one
|
|
78
|
+
process (auth → session hooks → daemon → git hooks → skill → welcome). The detailed
|
|
79
|
+
step-by-step the agent follows — and the manual fallback — live in
|
|
80
|
+
[`setup.md`](./setup.md).
|
|
80
81
|
|
|
81
82
|
## Commands
|
|
82
83
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
clearRepoSyncId,
|
|
2
3
|
gitToplevel,
|
|
3
4
|
githubRepositoryFullName,
|
|
4
5
|
isValidRepoSyncId,
|
|
5
6
|
setRepoSyncId
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-TDRXHBEX.js";
|
|
7
8
|
import {
|
|
9
|
+
HttpError,
|
|
8
10
|
getClient,
|
|
9
11
|
withFileLock
|
|
10
12
|
} from "./chunk-CPX3BUOC.js";
|
|
@@ -1222,19 +1224,31 @@ async function resolveRepositoryBinding(root, options) {
|
|
|
1222
1224
|
if (!repositoryFullName) {
|
|
1223
1225
|
throw new Error("origin must be a GitHub HTTPS/SSH remote in owner/name form");
|
|
1224
1226
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1227
|
+
let response;
|
|
1228
|
+
try {
|
|
1229
|
+
response = await getClient().post(
|
|
1230
|
+
"/api/cli/repositories/bind",
|
|
1231
|
+
{ repositoryFullName },
|
|
1232
|
+
options
|
|
1233
|
+
);
|
|
1234
|
+
} catch (error) {
|
|
1235
|
+
if (error instanceof HttpError && error.status === 404) {
|
|
1236
|
+
return { status: "pending", repositoryFullName };
|
|
1237
|
+
}
|
|
1238
|
+
throw error;
|
|
1239
|
+
}
|
|
1230
1240
|
if (!isValidRepoSyncId(response.repoSyncId)) {
|
|
1231
1241
|
throw new Error("server returned no repository binding");
|
|
1232
1242
|
}
|
|
1233
|
-
return { repoSyncId: response.repoSyncId, repositoryFullName };
|
|
1243
|
+
return { status: "connected", repoSyncId: response.repoSyncId, repositoryFullName };
|
|
1234
1244
|
}
|
|
1235
1245
|
async function bindRepository(root, options) {
|
|
1236
1246
|
const binding = await resolveRepositoryBinding(root, options);
|
|
1237
|
-
|
|
1247
|
+
if (binding.status === "connected") {
|
|
1248
|
+
setRepoSyncId(root, binding.repoSyncId);
|
|
1249
|
+
} else {
|
|
1250
|
+
clearRepoSyncId(root);
|
|
1251
|
+
}
|
|
1238
1252
|
return binding;
|
|
1239
1253
|
}
|
|
1240
1254
|
|
|
@@ -241,6 +241,20 @@ function setRepoSyncId(cwd, value) {
|
|
|
241
241
|
timeout: GIT_TIMEOUT_MS2
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
|
+
function clearRepoSyncId(cwd) {
|
|
245
|
+
try {
|
|
246
|
+
execFileSync2("git", ["config", "--local", "--unset-all", PRIM_REPO_SYNC_ID_KEY], {
|
|
247
|
+
cwd,
|
|
248
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
249
|
+
timeout: GIT_TIMEOUT_MS2
|
|
250
|
+
});
|
|
251
|
+
} catch (error) {
|
|
252
|
+
if (typeof error === "object" && error !== null && "status" in error && error.status === 5) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
244
258
|
function hasProjectPrimInstall(cwd) {
|
|
245
259
|
const root = gitToplevel(cwd);
|
|
246
260
|
if (root === null || root === homedir()) return false;
|
|
@@ -278,6 +292,7 @@ export {
|
|
|
278
292
|
isValidRepoSyncId,
|
|
279
293
|
repoSyncId,
|
|
280
294
|
setRepoSyncId,
|
|
295
|
+
clearRepoSyncId,
|
|
281
296
|
isRepoActiveForCapture,
|
|
282
297
|
decisionIngestionStatus
|
|
283
298
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
commitAttributionFromEnvironment,
|
|
4
4
|
toCommitMove
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-5CKL5EYQ.js";
|
|
6
6
|
import {
|
|
7
7
|
appendMove,
|
|
8
8
|
resolveOrg
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
isRepoActiveForCapture,
|
|
16
16
|
repoSyncId,
|
|
17
17
|
resolveRepositoryContext
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-TDRXHBEX.js";
|
|
19
19
|
import "../chunk-CPX3BUOC.js";
|
|
20
20
|
|
|
21
21
|
// src/hooks/post-commit.ts
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
enrichHookPayloadWithFileRefs,
|
|
9
9
|
preserveHookFileMetadata
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-BDGQEJA5.js";
|
|
11
11
|
import {
|
|
12
12
|
postToolInvocationId,
|
|
13
13
|
toMove,
|
|
14
14
|
toolOutcomeFor
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-5CKL5EYQ.js";
|
|
16
16
|
import {
|
|
17
17
|
appendMove,
|
|
18
18
|
resolveOrg
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
isRepoActiveForCapture,
|
|
31
31
|
repoSyncId,
|
|
32
32
|
resolveRepositoryContext
|
|
33
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-TDRXHBEX.js";
|
|
34
34
|
import {
|
|
35
35
|
getClient
|
|
36
36
|
} from "../chunk-CPX3BUOC.js";
|
package/dist/hooks/prim-hook.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
enrichHookPayloadWithFileRefs,
|
|
4
4
|
preserveHookFileMetadata
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-BDGQEJA5.js";
|
|
6
6
|
import {
|
|
7
7
|
postToolInvocationId,
|
|
8
8
|
shouldFlushAfter,
|
|
9
9
|
toMove
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-5CKL5EYQ.js";
|
|
11
11
|
import {
|
|
12
12
|
appendMove,
|
|
13
13
|
resolveOrg
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
isRepoActiveForCapture,
|
|
36
36
|
repoSyncId,
|
|
37
37
|
resolveRepositoryContext
|
|
38
|
-
} from "../chunk-
|
|
38
|
+
} from "../chunk-TDRXHBEX.js";
|
|
39
39
|
import "../chunk-CPX3BUOC.js";
|
|
40
40
|
import {
|
|
41
41
|
normalizeEnvelope,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ensureEffectivePostCommitHook,
|
|
5
5
|
hasUsableCodexGuidance,
|
|
6
6
|
refreshClaudePlugins
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-CPHJUQNE.js";
|
|
8
8
|
import {
|
|
9
9
|
buildHookOutput,
|
|
10
10
|
handoffHookOutput
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
isRepoActiveForCapture,
|
|
28
28
|
repoActiveFlag,
|
|
29
29
|
setRepoActive
|
|
30
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-TDRXHBEX.js";
|
|
31
31
|
import {
|
|
32
32
|
getSiteUrl,
|
|
33
33
|
isSessionEnded
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
resolveRepositoryBinding,
|
|
36
36
|
uninstallPostCommitHookAtPath,
|
|
37
37
|
uninstallProjectPostCommitHook
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-CPHJUQNE.js";
|
|
39
39
|
import {
|
|
40
40
|
fetchFeedbackCapability
|
|
41
41
|
} from "./chunk-KHZNYEUV.js";
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
isValidRepoSyncId,
|
|
60
60
|
repoSyncId,
|
|
61
61
|
setRepoActive
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-TDRXHBEX.js";
|
|
63
63
|
import {
|
|
64
64
|
HttpError,
|
|
65
65
|
REFRESH_TOKEN_PATH,
|
|
@@ -97,22 +97,48 @@ async function applyActivation(active) {
|
|
|
97
97
|
);
|
|
98
98
|
process.exit(1);
|
|
99
99
|
}
|
|
100
|
+
let phase = active ? "post-commit hook coverage" : "local deactivation";
|
|
100
101
|
try {
|
|
101
|
-
let
|
|
102
|
+
let binding;
|
|
102
103
|
let postCommitHook;
|
|
103
104
|
if (active) {
|
|
104
105
|
postCommitHook = ensureEffectivePostCommitHook(root).path;
|
|
105
|
-
|
|
106
|
+
phase = "repository binding";
|
|
107
|
+
binding = await bindRepository(root);
|
|
108
|
+
phase = "local activation";
|
|
106
109
|
}
|
|
107
110
|
setRepoActive(root, active);
|
|
108
111
|
await daemonRequest("statusline_invalidate", {}, { timeoutMs: 250 });
|
|
109
|
-
|
|
112
|
+
if (binding?.status === "pending") {
|
|
113
|
+
process.stderr.write(`[prim] Prim is enabled locally in ${root}
|
|
110
114
|
`);
|
|
111
|
-
|
|
115
|
+
process.stderr.write(
|
|
116
|
+
`[prim] repository ${binding.repositoryFullName} is not connected to Primitive; Moves still ingest into the team graph without repository-specific file attribution, Conflict Gate verification, or commit correlation
|
|
117
|
+
`
|
|
118
|
+
);
|
|
119
|
+
process.stderr.write(
|
|
120
|
+
`[prim] ask an organization owner or administrator to grant Primitive's GitHub App access to this repository through Primitive's GitHub App onboarding; binding retries automatically at the next agent SessionStart
|
|
121
|
+
`
|
|
122
|
+
);
|
|
123
|
+
} else {
|
|
124
|
+
process.stderr.write(`[prim] prim ${active ? "enabled" : "disabled"} in ${root}
|
|
125
|
+
`);
|
|
126
|
+
}
|
|
127
|
+
printJson({
|
|
128
|
+
active,
|
|
129
|
+
repo: root,
|
|
130
|
+
...binding ? {
|
|
131
|
+
bindingStatus: binding.status,
|
|
132
|
+
repositoryFullName: binding.repositoryFullName,
|
|
133
|
+
...binding.status === "connected" ? { repoSyncId: binding.repoSyncId } : {}
|
|
134
|
+
} : {},
|
|
135
|
+
...postCommitHook ? { postCommitHook } : {}
|
|
136
|
+
});
|
|
112
137
|
} catch (err) {
|
|
113
138
|
const detail = err instanceof Error ? err.message : String(err);
|
|
114
139
|
process.stderr.write(
|
|
115
|
-
`[prim] failed to
|
|
140
|
+
active ? `[prim] failed to enable prim during ${phase}: ${detail}
|
|
141
|
+
` : `[prim] failed to disable prim: ${detail}
|
|
116
142
|
`
|
|
117
143
|
);
|
|
118
144
|
process.exit(1);
|
|
@@ -3917,7 +3943,28 @@ function checkWorkspaceIdentity() {
|
|
|
3917
3943
|
};
|
|
3918
3944
|
}
|
|
3919
3945
|
}
|
|
3920
|
-
function classifyRepositoryBinding(value,
|
|
3946
|
+
function classifyRepositoryBinding(value, current, active) {
|
|
3947
|
+
if (current.status === "pending") {
|
|
3948
|
+
if (value !== void 0) {
|
|
3949
|
+
return {
|
|
3950
|
+
name: "repo-binding",
|
|
3951
|
+
status: "fail",
|
|
3952
|
+
detail: `local repository binding is stale for ${current.repositoryFullName} \u2014 run \`prim enable\``
|
|
3953
|
+
};
|
|
3954
|
+
}
|
|
3955
|
+
if (!active) {
|
|
3956
|
+
return {
|
|
3957
|
+
name: "repo-binding",
|
|
3958
|
+
status: "fail",
|
|
3959
|
+
detail: "passive capture is inactive \u2014 run `prim enable`"
|
|
3960
|
+
};
|
|
3961
|
+
}
|
|
3962
|
+
return {
|
|
3963
|
+
name: "repo-binding",
|
|
3964
|
+
status: "warn",
|
|
3965
|
+
detail: `${current.repositoryFullName} is not connected to Primitive \u2014 local capture is active, but file scoping, Conflict Gate verification, and commit correlation are unavailable; ask an organization owner/admin to grant the Primitive GitHub App access (retried automatically next SessionStart)`
|
|
3966
|
+
};
|
|
3967
|
+
}
|
|
3921
3968
|
if (!isValidRepoSyncId(value)) {
|
|
3922
3969
|
return {
|
|
3923
3970
|
name: "repo-binding",
|
|
@@ -3925,7 +3972,7 @@ function classifyRepositoryBinding(value, currentServerValue) {
|
|
|
3925
3972
|
detail: "missing or invalid local prim.repoSyncId \u2014 run `prim enable`"
|
|
3926
3973
|
};
|
|
3927
3974
|
}
|
|
3928
|
-
if (
|
|
3975
|
+
if (value !== current.repoSyncId) {
|
|
3929
3976
|
return {
|
|
3930
3977
|
name: "repo-binding",
|
|
3931
3978
|
status: "fail",
|
|
@@ -3935,26 +3982,25 @@ function classifyRepositoryBinding(value, currentServerValue) {
|
|
|
3935
3982
|
return {
|
|
3936
3983
|
name: "repo-binding",
|
|
3937
3984
|
status: "ok",
|
|
3938
|
-
detail:
|
|
3985
|
+
detail: "local repository binding matches the current server binding"
|
|
3939
3986
|
};
|
|
3940
3987
|
}
|
|
3941
3988
|
async function checkRepositoryBinding() {
|
|
3942
3989
|
const root = process.cwd();
|
|
3943
3990
|
const local = repoSyncId(root);
|
|
3944
|
-
const localCheck = classifyRepositoryBinding(local);
|
|
3945
|
-
if (localCheck.status === "fail") return localCheck;
|
|
3946
3991
|
try {
|
|
3947
3992
|
const current = await resolveRepositoryBinding(root, {
|
|
3948
3993
|
signal: AbortSignal.timeout(CONNECTIVITY_TIMEOUT_MS),
|
|
3949
3994
|
quietRefresh: true
|
|
3950
3995
|
});
|
|
3951
|
-
return classifyRepositoryBinding(local, current
|
|
3996
|
+
return classifyRepositoryBinding(local, current, isRepoActiveForCapture(root));
|
|
3952
3997
|
} catch (error) {
|
|
3953
|
-
const
|
|
3998
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3999
|
+
const detail = boundedHealthError(`could not verify the current repository binding \u2014 ${message}`) ?? "could not verify the current repository binding";
|
|
3954
4000
|
return {
|
|
3955
4001
|
name: "repo-binding",
|
|
3956
4002
|
status: "fail",
|
|
3957
|
-
detail
|
|
4003
|
+
detail
|
|
3958
4004
|
};
|
|
3959
4005
|
}
|
|
3960
4006
|
}
|
package/package.json
CHANGED