@primitive.ai/prim 0.1.0-alpha.94 → 0.1.0-alpha.97
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 +7 -4
- package/dist/{chunk-UKUAAAXE.js → chunk-27ADT6FQ.js} +2 -2
- package/dist/{chunk-TYAHC25F.js → chunk-2MBV7ZMV.js} +1 -1
- package/dist/{chunk-OTHKG76J.js → chunk-35FMRWJH.js} +1 -1
- package/dist/{chunk-O7YAW7G6.js → chunk-3I4GEWXQ.js} +9 -11
- package/dist/{chunk-DXJQR4QI.js → chunk-4GHANPWQ.js} +2 -2
- package/dist/{chunk-WUXFLE7X.js → chunk-7KABYYWG.js} +64 -66
- package/dist/{chunk-LFFLHSQO.js → chunk-AJYZB5PF.js} +63 -6
- package/dist/{chunk-H4UNYFUC.js → chunk-DHOQGHKQ.js} +184 -1
- package/dist/{chunk-2GP5UFV7.js → chunk-DWRSEC34.js} +5 -3
- package/dist/{chunk-ZU563PQI.js → chunk-FBPZ4YUD.js} +2 -2
- package/dist/{chunk-G2VMA2QO.js → chunk-LY6NJ7KL.js} +6 -4
- package/dist/{chunk-ZB4F75SZ.js → chunk-MXVCP33E.js} +5 -1
- package/dist/{chunk-ICM2XCXS.js → chunk-OW4GJBLW.js} +2 -2
- package/dist/{chunk-K7D2EYBS.js → chunk-QNPTWTBG.js} +2 -2
- package/dist/{chunk-IMK4JKTA.js → chunk-RK4ZS3HG.js} +2 -2
- package/dist/{chunk-OH3EZXYX.js → chunk-UO2U6IKF.js} +1 -1
- package/dist/{chunk-FXF4JWK2.js → chunk-XEDJ5N3M.js} +17 -2
- package/dist/{chunk-AXQQMX2U.js → chunk-Y5W4TZM7.js} +2 -2
- package/dist/{chunk-DSWT6BCC.js → chunk-ZYK3TBEW.js} +2542 -2250
- package/dist/daemon/server.js +2547 -2119
- package/dist/hook-runtime/daemon/server.js +2547 -2119
- package/dist/hook-runtime/hooks/post-commit.js +2547 -2119
- package/dist/hook-runtime/hooks/post-rewrite.js +2547 -2119
- package/dist/hook-runtime/hooks/post-tool-use.js +2874 -2373
- package/dist/hook-runtime/hooks/pre-tool-use.js +3766 -3325
- package/dist/hook-runtime/hooks/prim-hook.js +2973 -2440
- package/dist/hook-runtime/hooks/session-end.js +179 -129
- package/dist/hook-runtime/hooks/session-start.js +2651 -2221
- package/dist/hook-runtime/index.js +2596 -2126
- package/dist/hooks/post-commit.js +11 -11
- package/dist/hooks/post-rewrite.js +10 -10
- package/dist/hooks/post-tool-use.js +20 -20
- package/dist/hooks/pre-commit.js +4 -4
- package/dist/hooks/pre-tool-use.js +29 -17
- package/dist/hooks/prim-hook.js +22 -18
- package/dist/hooks/session-end.js +11 -5
- package/dist/hooks/session-start.js +26 -22
- package/dist/index.js +79 -60
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,24 +19,25 @@ import {
|
|
|
19
19
|
resolveRepositoryBinding,
|
|
20
20
|
uninstallGitHookAtPath,
|
|
21
21
|
uninstallProjectGitHook
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import {
|
|
24
|
-
POST_COMMIT_GRACE_MS,
|
|
25
|
-
clearHooksWired,
|
|
26
|
-
inspectPostCommitFiring,
|
|
27
|
-
recordHooksWired
|
|
28
|
-
} from "./chunk-FXF4JWK2.js";
|
|
22
|
+
} from "./chunk-7KABYYWG.js";
|
|
29
23
|
import {
|
|
30
24
|
requireDurableIngestAcknowledgement
|
|
31
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-2MBV7ZMV.js";
|
|
32
26
|
import {
|
|
33
27
|
checkAffectedDecisions,
|
|
34
28
|
daemonOrDirectGet,
|
|
35
29
|
formatDecisionsWarning
|
|
36
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-27ADT6FQ.js";
|
|
37
31
|
import {
|
|
38
32
|
fetchFeedbackCapability
|
|
39
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-UO2U6IKF.js";
|
|
34
|
+
import {
|
|
35
|
+
POST_COMMIT_GRACE_MS,
|
|
36
|
+
clearHooksWired,
|
|
37
|
+
inspectPostCommitFiring,
|
|
38
|
+
lastConversationCaptured,
|
|
39
|
+
recordHooksWired
|
|
40
|
+
} from "./chunk-XEDJ5N3M.js";
|
|
40
41
|
import {
|
|
41
42
|
isUnattended,
|
|
42
43
|
unattendedEnv
|
|
@@ -55,7 +56,7 @@ import {
|
|
|
55
56
|
rotationIdentity,
|
|
56
57
|
sweepOrphanedDrainProgress,
|
|
57
58
|
writeDrainCheckpoint
|
|
58
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-4GHANPWQ.js";
|
|
59
60
|
import {
|
|
60
61
|
MS_PER_SECOND,
|
|
61
62
|
deliveryBacklogState,
|
|
@@ -64,13 +65,12 @@ import {
|
|
|
64
65
|
formatStatusline,
|
|
65
66
|
formatTeammates,
|
|
66
67
|
repositoryBindingDiagnosticLabel
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-FBPZ4YUD.js";
|
|
68
69
|
import {
|
|
69
70
|
bold,
|
|
70
71
|
boundedHealthError,
|
|
71
72
|
color,
|
|
72
73
|
colorForArea,
|
|
73
|
-
decisionIngestionStatus,
|
|
74
74
|
dim,
|
|
75
75
|
fetchAndCacheCollectScope,
|
|
76
76
|
isCliErrorResponse,
|
|
@@ -83,14 +83,8 @@ import {
|
|
|
83
83
|
isGitHubInstallIntentStartResponse,
|
|
84
84
|
isGitHubInstallIntentStatusResponse,
|
|
85
85
|
isMoveIngestRequest,
|
|
86
|
-
isRepoActiveForCapture,
|
|
87
|
-
isValidRepoSyncId,
|
|
88
|
-
repoActiveFlag,
|
|
89
|
-
repoSyncId,
|
|
90
|
-
repositoryBindingState,
|
|
91
|
-
setRepoActive,
|
|
92
86
|
stripAnsi
|
|
93
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-ZYK3TBEW.js";
|
|
94
88
|
import {
|
|
95
89
|
CliManagementResponseError,
|
|
96
90
|
HttpError,
|
|
@@ -107,7 +101,7 @@ import {
|
|
|
107
101
|
setStoredToken,
|
|
108
102
|
stripControlChars,
|
|
109
103
|
terminalSafeLine
|
|
110
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-LY6NJ7KL.js";
|
|
111
105
|
import {
|
|
112
106
|
MANAGED_GIT_HOOK_NAMES,
|
|
113
107
|
assertOwnedHookRuntime,
|
|
@@ -139,16 +133,24 @@ import {
|
|
|
139
133
|
stableNodePath,
|
|
140
134
|
stageHookRuntime,
|
|
141
135
|
stripCommand
|
|
142
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-Y5W4TZM7.js";
|
|
143
137
|
import {
|
|
144
138
|
canonicalGitRoot,
|
|
145
139
|
canonicalRepositoryPath,
|
|
146
|
-
|
|
147
|
-
|
|
140
|
+
decisionIngestionStatus,
|
|
141
|
+
gitToplevel,
|
|
142
|
+
isRepoActiveForCapture,
|
|
143
|
+
isValidRepoSyncId,
|
|
144
|
+
mainWorktreeRoot,
|
|
145
|
+
repoActiveFlag,
|
|
146
|
+
repoSyncId,
|
|
147
|
+
repositoryBindingState,
|
|
148
|
+
setRepoActive
|
|
149
|
+
} from "./chunk-DHOQGHKQ.js";
|
|
148
150
|
import {
|
|
149
151
|
daemonIsLive,
|
|
150
152
|
daemonRequest
|
|
151
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-35FMRWJH.js";
|
|
152
154
|
import {
|
|
153
155
|
REFRESH_TOKEN_PATH,
|
|
154
156
|
TOKEN_FILE_PATH,
|
|
@@ -163,7 +165,7 @@ import {
|
|
|
163
165
|
syncDirectory,
|
|
164
166
|
withFileLock,
|
|
165
167
|
withFileLockSync
|
|
166
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-DWRSEC34.js";
|
|
167
169
|
|
|
168
170
|
// src/index.ts
|
|
169
171
|
import { readFileSync as readFileSync10 } from "fs";
|
|
@@ -2221,22 +2223,32 @@ function performStatus3() {
|
|
|
2221
2223
|
};
|
|
2222
2224
|
return { user: statusFor(USER_SCOPE_PATH), project: statusFor(projectScopePath()) };
|
|
2223
2225
|
}
|
|
2226
|
+
function uncoveredWorktreeHooks(status) {
|
|
2227
|
+
if (status.user.present || status.project.present) return null;
|
|
2228
|
+
const main = mainWorktreeRoot();
|
|
2229
|
+
if (main === null) return null;
|
|
2230
|
+
const path = join2(main, ".codex", "hooks.json");
|
|
2231
|
+
return hasAnyHookRegistration(readSettings(path)) ? path : null;
|
|
2232
|
+
}
|
|
2233
|
+
function uncoveredWorktreeAdvice(path) {
|
|
2234
|
+
return `prim Codex hooks in ${path} don't load in this worktree \u2014 run \`prim codex install\`, then \`prim codex uninstall --scope project\` in that checkout`;
|
|
2235
|
+
}
|
|
2224
2236
|
function resolveScope(input) {
|
|
2225
|
-
if (input === void 0 || input === "
|
|
2226
|
-
return "project";
|
|
2227
|
-
}
|
|
2228
|
-
if (input === "user") {
|
|
2237
|
+
if (input === void 0 || input === "user") {
|
|
2229
2238
|
return "user";
|
|
2230
2239
|
}
|
|
2240
|
+
if (input === "project") {
|
|
2241
|
+
return "project";
|
|
2242
|
+
}
|
|
2231
2243
|
console.error(`[prim] unknown --scope "${input}" (expected: user or project)`);
|
|
2232
2244
|
process.exit(1);
|
|
2233
2245
|
}
|
|
2234
2246
|
var TRUST_NOTICE = "[prim] Codex requires hook trust: run `/hooks` in Codex to review and trust these hooks (or start Codex with --dangerously-bypass-hook-trust). Until trusted, the hooks will not fire.";
|
|
2235
2247
|
function registerCodexCommands(program2) {
|
|
2236
2248
|
const codex = program2.command("codex").description("Manage the prim Codex integration (capture, gate, ingest, presence)");
|
|
2237
|
-
codex.command("install").description("Register the prim hooks in Codex's hooks.json (
|
|
2249
|
+
codex.command("install").description("Register the prim hooks in Codex's hooks.json (user scope by default)").option(
|
|
2238
2250
|
"--scope <scope>",
|
|
2239
|
-
"
|
|
2251
|
+
"user (default, ~/.codex/hooks.json) or project (this checkout's .codex/hooks.json)"
|
|
2240
2252
|
).option("--force", "Replace any drifted prim hook entries").action((opts) => {
|
|
2241
2253
|
const scope = resolveScope(opts.scope);
|
|
2242
2254
|
const result = performInstall(scope, opts.force ?? false);
|
|
@@ -2250,7 +2262,7 @@ function registerCodexCommands(program2) {
|
|
|
2250
2262
|
});
|
|
2251
2263
|
codex.command("uninstall").description("Remove all prim hooks from Codex's hooks.json").option(
|
|
2252
2264
|
"--scope <scope>",
|
|
2253
|
-
"
|
|
2265
|
+
"user (default, ~/.codex/hooks.json) or project (this checkout's .codex/hooks.json)"
|
|
2254
2266
|
).action((opts) => {
|
|
2255
2267
|
const scope = resolveScope(opts.scope);
|
|
2256
2268
|
const result = performUninstall(scope);
|
|
@@ -2267,6 +2279,9 @@ function registerCodexCommands(program2) {
|
|
|
2267
2279
|
const line = (label, s) => `[prim] ${label}: gate ${mark(s.gate)} \xB7 capture ${mark(s.capture)} (${s.path})`;
|
|
2268
2280
|
console.error(`${line("user", result.user)}
|
|
2269
2281
|
${line("project", result.project)}`);
|
|
2282
|
+
const uncovered = uncoveredWorktreeHooks(result);
|
|
2283
|
+
if (uncovered !== null)
|
|
2284
|
+
console.error(`[prim] warning: ${uncoveredWorktreeAdvice(uncovered)}`);
|
|
2270
2285
|
console.log(JSON.stringify(result, null, JSON_INDENT));
|
|
2271
2286
|
});
|
|
2272
2287
|
}
|
|
@@ -4879,8 +4894,6 @@ var DECISION_NOT_FOUND_MESSAGE = "Decision not found";
|
|
|
4879
4894
|
var REPLACEMENT_NOT_FOUND_MESSAGE = "Replacement decision not found";
|
|
4880
4895
|
var SELF_REPLACEMENT_MESSAGE = "A decision cannot supersede itself";
|
|
4881
4896
|
var OLD_SERVER_NOT_FOUND_MESSAGE = "Not found";
|
|
4882
|
-
var FEATURE_DISABLED_MESSAGE = "feature_disabled";
|
|
4883
|
-
var FEATURE_CHECK_UNAVAILABLE_MESSAGE = "feature_check_unavailable";
|
|
4884
4897
|
var STAGE_NAME = "(?:draft|provisional|adopted|superseded|abandoned)";
|
|
4885
4898
|
var IMMUTABLE_MESSAGE = new RegExp(
|
|
4886
4899
|
`^An ${STAGE_NAME} decision is immutable \u2014 supersede it to change it$`,
|
|
@@ -4957,12 +4970,6 @@ function classifyHttpError2(error) {
|
|
|
4957
4970
|
if (error.status === 403 && message === NOT_AUTHOR_MESSAGE) {
|
|
4958
4971
|
return failure2("not_author", DECISION_LIFECYCLE_EXIT.rejected, error.status);
|
|
4959
4972
|
}
|
|
4960
|
-
if (error.status === 403 && message === FEATURE_DISABLED_MESSAGE) {
|
|
4961
|
-
return failure2("feature_disabled", DECISION_LIFECYCLE_EXIT.rejected, error.status);
|
|
4962
|
-
}
|
|
4963
|
-
if (error.status === 503 && message === FEATURE_CHECK_UNAVAILABLE_MESSAGE) {
|
|
4964
|
-
return failure2("feature_check_unavailable", DECISION_LIFECYCLE_EXIT.server, error.status);
|
|
4965
|
-
}
|
|
4966
4973
|
if (error.status === 409 && message === AMBIGUOUS_MESSAGE) {
|
|
4967
4974
|
return failure2("ambiguous_identifier", DECISION_LIFECYCLE_EXIT.rejected, error.status);
|
|
4968
4975
|
}
|
|
@@ -5022,10 +5029,6 @@ function formatFailureHuman(operation, result) {
|
|
|
5022
5029
|
return `[prim] ${verb} rejected: Decision not found.`;
|
|
5023
5030
|
case "replacement_not_found":
|
|
5024
5031
|
return "[prim] supersede rejected: replacement Decision not found.";
|
|
5025
|
-
case "feature_disabled":
|
|
5026
|
-
return `[prim] ${verb} rejected: manual lifecycle actions are not enabled for this account.`;
|
|
5027
|
-
case "feature_check_unavailable":
|
|
5028
|
-
return `[prim] ${verb} unavailable: the server could not verify feature availability; retry shortly.`;
|
|
5029
5032
|
case "unsupported_server":
|
|
5030
5033
|
return `[prim] ${verb} unavailable: this Primitive server does not support this Decision lifecycle operation; upgrade the server before retrying.`;
|
|
5031
5034
|
case "rejected":
|
|
@@ -7748,9 +7751,16 @@ function classifyClaudeHooks(statuses) {
|
|
|
7748
7751
|
}
|
|
7749
7752
|
return { name: "feedback-hooks", status: "ok", detail: "complete Claude lifecycle ready" };
|
|
7750
7753
|
}
|
|
7751
|
-
function classifyCodexHooks(statuses) {
|
|
7754
|
+
function classifyCodexHooks(statuses, uncoveredWorktree = null, capturedAt) {
|
|
7752
7755
|
const installed = statuses.filter((status) => status.present);
|
|
7753
7756
|
if (installed.length === 0) {
|
|
7757
|
+
if (uncoveredWorktree !== null) {
|
|
7758
|
+
return {
|
|
7759
|
+
name: "codex-hooks",
|
|
7760
|
+
status: "warn",
|
|
7761
|
+
detail: uncoveredWorktreeAdvice(uncoveredWorktree)
|
|
7762
|
+
};
|
|
7763
|
+
}
|
|
7754
7764
|
return { name: "codex-hooks", status: "ok", detail: "not installed" };
|
|
7755
7765
|
}
|
|
7756
7766
|
if (installed.some((status) => !status.complete)) {
|
|
@@ -7762,8 +7772,8 @@ function classifyCodexHooks(statuses) {
|
|
|
7762
7772
|
}
|
|
7763
7773
|
return {
|
|
7764
7774
|
name: "codex-hooks",
|
|
7765
|
-
status: "warn",
|
|
7766
|
-
detail: "installed; Codex trust
|
|
7775
|
+
status: capturedAt === void 0 ? "warn" : "ok",
|
|
7776
|
+
detail: capturedAt === void 0 ? "installed; conversation capture unverified; Codex trust unknown \u2014 verify with `/hooks`" : `installed; conversation capture observed ${new Date(capturedAt).toISOString()}; current trust unknown`
|
|
7767
7777
|
};
|
|
7768
7778
|
}
|
|
7769
7779
|
function classifyCursorHooks(statuses) {
|
|
@@ -7815,7 +7825,13 @@ function checkAgentHooks() {
|
|
|
7815
7825
|
const checks = [];
|
|
7816
7826
|
try {
|
|
7817
7827
|
const status = performStatus3();
|
|
7818
|
-
checks.push(
|
|
7828
|
+
checks.push(
|
|
7829
|
+
classifyCodexHooks(
|
|
7830
|
+
[status.project, status.user],
|
|
7831
|
+
uncoveredWorktreeHooks(status),
|
|
7832
|
+
lastConversationCaptured(process.cwd(), "codex")
|
|
7833
|
+
)
|
|
7834
|
+
);
|
|
7819
7835
|
} catch (error) {
|
|
7820
7836
|
const detail = boundedHealthError(error instanceof Error ? error.message : String(error));
|
|
7821
7837
|
checks.push({
|
|
@@ -7967,7 +7983,7 @@ function parseMovesStatus(value) {
|
|
|
7967
7983
|
}
|
|
7968
7984
|
const status = value;
|
|
7969
7985
|
const nullableNumber = (candidate) => candidate === null || typeof candidate === "number" && Number.isFinite(candidate);
|
|
7970
|
-
if (status.captureState !== "enabled"
|
|
7986
|
+
if (status.captureState !== "enabled" || !nullableNumber(status.latestIngestAt) || !nullableNumber(status.latestClassificationAt) || !nullableNumber(status.highWaterMark) || typeof status.pendingSessionCount !== "number" || !Number.isInteger(status.pendingSessionCount) || status.pendingSessionCount < 0 || typeof status.sampled !== "boolean") {
|
|
7971
7987
|
throw new Error("moves status returned an invalid response");
|
|
7972
7988
|
}
|
|
7973
7989
|
if (status.oldestPendingAt !== void 0 && !nullableNumber(status.oldestPendingAt) || status.oldestPendingAgeMs !== void 0 && !nullableNumber(status.oldestPendingAgeMs) || typeof status.oldestPendingAgeMs === "number" && status.oldestPendingAgeMs < 0 || status.pendingCommitCorrelationCount !== void 0 && (!Number.isInteger(status.pendingCommitCorrelationCount) || status.pendingCommitCorrelationCount < 0)) {
|
|
@@ -7976,10 +7992,10 @@ function parseMovesStatus(value) {
|
|
|
7976
7992
|
return status;
|
|
7977
7993
|
}
|
|
7978
7994
|
function classifyMovesStatus(status) {
|
|
7979
|
-
const capture =
|
|
7995
|
+
const capture = {
|
|
7980
7996
|
name: "capture",
|
|
7981
|
-
status: "
|
|
7982
|
-
detail: "
|
|
7997
|
+
status: "ok",
|
|
7998
|
+
detail: "enabled; ingest endpoint durable"
|
|
7983
7999
|
};
|
|
7984
8000
|
const correlation = status.pendingCommitCorrelationCount === void 0 ? void 0 : status.pendingCommitCorrelationCount > 0 ? {
|
|
7985
8001
|
name: "commit-correlation",
|
|
@@ -8868,7 +8884,7 @@ var SESSION_LABELS = {
|
|
|
8868
8884
|
};
|
|
8869
8885
|
function planSetupSteps(opts) {
|
|
8870
8886
|
const scopeArgs = opts.scope === "user" ? ["--scope", "user"] : [];
|
|
8871
|
-
const sessionArgs = opts.agent === "hermes" ? [opts.agent, "install"] : [opts.agent, "install",
|
|
8887
|
+
const sessionArgs = opts.agent === "hermes" ? [opts.agent, "install"] : [opts.agent, "install", "--scope", opts.scope];
|
|
8872
8888
|
const steps = [
|
|
8873
8889
|
{
|
|
8874
8890
|
key: "session",
|
|
@@ -9652,14 +9668,17 @@ function startDriftHeal(options) {
|
|
|
9652
9668
|
if (!runsConfigRoot()) return false;
|
|
9653
9669
|
const primEntry = options.primEntry === void 0 ? binFile("prim") : options.primEntry;
|
|
9654
9670
|
if (!primEntry) return false;
|
|
9655
|
-
const attempt = {
|
|
9656
|
-
attemptedAt: (options.nowMs ?? Date.now)(),
|
|
9657
|
-
fromVersion: launcher.runtimeVersion,
|
|
9658
|
-
toVersion
|
|
9659
|
-
};
|
|
9660
9671
|
const claimed = withFileLockSync(
|
|
9661
9672
|
daemonDriftHealClaimPath(paths),
|
|
9662
|
-
() =>
|
|
9673
|
+
() => (
|
|
9674
|
+
// Sample after acquiring the claim: an earlier timestamp from a delayed
|
|
9675
|
+
// command must not make the previous winner look like a clock rollback.
|
|
9676
|
+
claimAttempt(daemonDriftHealMarkerPath(paths), {
|
|
9677
|
+
attemptedAt: (options.nowMs ?? Date.now)(),
|
|
9678
|
+
fromVersion: launcher.runtimeVersion,
|
|
9679
|
+
toVersion
|
|
9680
|
+
})
|
|
9681
|
+
),
|
|
9663
9682
|
{ timeoutMs: 0, sleep: claimHeld }
|
|
9664
9683
|
);
|
|
9665
9684
|
if (!claimed) return false;
|
package/package.json
CHANGED