@primitive.ai/prim 0.1.0-alpha.56 → 0.1.0-alpha.57
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/dist/{chunk-ROL7SDXX.js → chunk-GQURYENF.js} +1 -1
- package/dist/{chunk-6LAQVM26.js → chunk-GUXBUBQ7.js} +2 -0
- package/dist/chunk-LDQZASIF.js +166 -0
- package/dist/chunk-SWWBK4MP.js +424 -0
- package/dist/{chunk-F5QCFBJ6.js → chunk-TNNHR3EZ.js} +8 -18
- package/dist/{chunk-HSZPTVKU.js → chunk-YIMUIPMD.js} +20 -15
- package/dist/daemon/server.js +7 -0
- package/dist/hooks/post-commit.js +2 -2
- package/dist/hooks/post-tool-use.js +26 -9
- package/dist/hooks/pre-tool-use.js +89 -230
- package/dist/hooks/prim-hook.js +10 -7
- package/dist/hooks/session-start.js +3 -3
- package/dist/index.js +99 -63
- package/dist/statusline-main.js +10 -8
- package/package.json +2 -1
- package/dist/chunk-R5ZJRSLV.js +0 -82
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
import {
|
|
26
26
|
printJson,
|
|
27
27
|
registerSkillCommands
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-GQURYENF.js";
|
|
29
29
|
import {
|
|
30
30
|
fetchFeedbackCapability
|
|
31
31
|
} from "./chunk-WELBNODJ.js";
|
|
@@ -36,16 +36,21 @@ import {
|
|
|
36
36
|
binFile,
|
|
37
37
|
commandMatchesBin,
|
|
38
38
|
detachedHookShimCommand,
|
|
39
|
-
|
|
39
|
+
packageVersion,
|
|
40
|
+
pinnedHookCommand,
|
|
40
41
|
warmBinCache
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-YIMUIPMD.js";
|
|
42
43
|
import {
|
|
43
|
-
|
|
44
|
+
canonicalGitRoot,
|
|
45
|
+
canonicalRepositoryPath,
|
|
44
46
|
decisionIngestionStatus,
|
|
45
47
|
gitToplevel,
|
|
48
|
+
githubRepositoryFullName,
|
|
46
49
|
isRepoActiveForCapture,
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
repoSyncId,
|
|
51
|
+
setRepoActive,
|
|
52
|
+
setRepoSyncId
|
|
53
|
+
} from "./chunk-LDQZASIF.js";
|
|
49
54
|
import {
|
|
50
55
|
HttpError,
|
|
51
56
|
REFRESH_TOKEN_PATH,
|
|
@@ -74,7 +79,7 @@ import { Command } from "commander";
|
|
|
74
79
|
import updateNotifier from "update-notifier";
|
|
75
80
|
|
|
76
81
|
// src/commands/activation.ts
|
|
77
|
-
function applyActivation(active) {
|
|
82
|
+
async function applyActivation(active) {
|
|
78
83
|
const root = gitToplevel();
|
|
79
84
|
if (!root) {
|
|
80
85
|
process.stderr.write(
|
|
@@ -84,16 +89,33 @@ function applyActivation(active) {
|
|
|
84
89
|
process.exit(1);
|
|
85
90
|
}
|
|
86
91
|
try {
|
|
87
|
-
|
|
92
|
+
let bound;
|
|
93
|
+
if (active) {
|
|
94
|
+
const repositoryFullName = githubRepositoryFullName(root);
|
|
95
|
+
if (!repositoryFullName) {
|
|
96
|
+
throw new Error("origin must be a GitHub HTTPS/SSH remote in owner/name form");
|
|
97
|
+
}
|
|
98
|
+
const response = await getClient().post("/api/cli/repositories/bind", {
|
|
99
|
+
repositoryFullName
|
|
100
|
+
});
|
|
101
|
+
if (typeof response.repoSyncId !== "string" || response.repoSyncId.length === 0) {
|
|
102
|
+
throw new Error("server returned no repository binding");
|
|
103
|
+
}
|
|
104
|
+
setRepoSyncId(root, response.repoSyncId);
|
|
105
|
+
bound = { repoSyncId: response.repoSyncId, repositoryFullName };
|
|
106
|
+
}
|
|
107
|
+
setRepoActive(root, active);
|
|
108
|
+
process.stderr.write(`[prim] prim ${active ? "enabled" : "disabled"} in ${root}
|
|
109
|
+
`);
|
|
110
|
+
printJson({ active, repo: root, ...bound });
|
|
88
111
|
} catch (err) {
|
|
89
112
|
const detail = err instanceof Error ? err.message : String(err);
|
|
90
|
-
process.stderr.write(
|
|
91
|
-
`
|
|
113
|
+
process.stderr.write(
|
|
114
|
+
`[prim] failed to ${active ? "bind and enable" : "disable"} prim: ${detail}
|
|
115
|
+
`
|
|
116
|
+
);
|
|
92
117
|
process.exit(1);
|
|
93
118
|
}
|
|
94
|
-
process.stderr.write(`[prim] prim ${active ? "enabled" : "disabled"} in ${root}
|
|
95
|
-
`);
|
|
96
|
-
printJson({ active, repo: root });
|
|
97
119
|
}
|
|
98
120
|
function registerActivationCommands(program2) {
|
|
99
121
|
program2.command("enable").description("Activate prim's hooks in this repo (git config prim.active=true)").action(() => applyActivation(true));
|
|
@@ -1068,7 +1090,7 @@ var SESSION_START_BIN = "prim-session-start";
|
|
|
1068
1090
|
var SESSION_END_BIN = "prim-session-end";
|
|
1069
1091
|
var STATUSLINE_BIN = "prim";
|
|
1070
1092
|
var STATUSLINE_ARGS = "statusline";
|
|
1071
|
-
var STATUSLINE_COMMAND =
|
|
1093
|
+
var STATUSLINE_COMMAND = pinnedHookCommand(STATUSLINE_BIN, STATUSLINE_ARGS);
|
|
1072
1094
|
var STATUSLINE_REFRESH_SECONDS = 5;
|
|
1073
1095
|
var PRIM_BINS = [
|
|
1074
1096
|
CAPTURE_BIN,
|
|
@@ -1092,8 +1114,13 @@ var CAPTURE_EVENTS = [
|
|
|
1092
1114
|
"SessionEnd",
|
|
1093
1115
|
"SubagentStop"
|
|
1094
1116
|
];
|
|
1095
|
-
function makeRegistration(event, matcher, bin, args = ""
|
|
1096
|
-
return {
|
|
1117
|
+
function makeRegistration(event, matcher, bin, args = "") {
|
|
1118
|
+
return {
|
|
1119
|
+
event,
|
|
1120
|
+
matcher,
|
|
1121
|
+
bin,
|
|
1122
|
+
command: pinnedHookCommand(bin, args)
|
|
1123
|
+
};
|
|
1097
1124
|
}
|
|
1098
1125
|
function makeDetachedRegistration(event, matcher, bin, args = "") {
|
|
1099
1126
|
return { event, matcher, bin, command: detachedHookShimCommand(bin, args) };
|
|
@@ -1102,11 +1129,9 @@ var REGISTRATIONS = [
|
|
|
1102
1129
|
...CAPTURE_EVENTS.map(
|
|
1103
1130
|
(event) => event === "SessionEnd" ? makeDetachedRegistration(event, "*", CAPTURE_BIN) : makeRegistration(event, "*", CAPTURE_BIN)
|
|
1104
1131
|
),
|
|
1105
|
-
makeRegistration("PreToolUse", "Edit|Write|MultiEdit", GATE_BIN),
|
|
1106
|
-
makeRegistration("PostToolUse", "Edit|Write|MultiEdit", POST_TOOL_USE_BIN),
|
|
1107
|
-
|
|
1108
|
-
// to refresh the bin cache the other hooks read. See lib/bin-cache.ts.
|
|
1109
|
-
makeRegistration("SessionStart", "*", SESSION_START_BIN, "", { cacheRead: false }),
|
|
1132
|
+
makeRegistration("PreToolUse", "Edit|Write|MultiEdit|NotebookEdit|Bash", GATE_BIN),
|
|
1133
|
+
makeRegistration("PostToolUse", "Edit|Write|MultiEdit|NotebookEdit|Bash", POST_TOOL_USE_BIN),
|
|
1134
|
+
makeRegistration("SessionStart", "*", SESSION_START_BIN),
|
|
1110
1135
|
makeDetachedRegistration("SessionEnd", "*", SESSION_END_BIN)
|
|
1111
1136
|
];
|
|
1112
1137
|
var PRIM_PERMISSION_RULE = "Bash(npx --yes @primitive.ai/prim*)";
|
|
@@ -1347,9 +1372,6 @@ function performInstall(scope, force) {
|
|
|
1347
1372
|
if (changed) {
|
|
1348
1373
|
atomicWrite2(path, after);
|
|
1349
1374
|
}
|
|
1350
|
-
if (scope === "project") {
|
|
1351
|
-
activateRepoBestEffort(process.cwd());
|
|
1352
|
-
}
|
|
1353
1375
|
return {
|
|
1354
1376
|
scope,
|
|
1355
1377
|
path,
|
|
@@ -1507,9 +1529,7 @@ var CODEX_REGISTRATIONS = [
|
|
|
1507
1529
|
...CODEX_CAPTURE_EVENTS.map((event) => makeRegistration(event, "*", CAPTURE_BIN2, CODEX_ARGS)),
|
|
1508
1530
|
makeRegistration("PreToolUse", "apply_patch", GATE_BIN2, CODEX_ARGS),
|
|
1509
1531
|
makeRegistration("PostToolUse", "apply_patch", POST_TOOL_USE_BIN2, CODEX_ARGS),
|
|
1510
|
-
|
|
1511
|
-
// refresh the bin cache the other hooks read. See lib/bin-cache.ts.
|
|
1512
|
-
makeRegistration("SessionStart", "*", SESSION_START_BIN2, CODEX_ARGS, { cacheRead: false })
|
|
1532
|
+
makeRegistration("SessionStart", "*", SESSION_START_BIN2, CODEX_ARGS)
|
|
1513
1533
|
];
|
|
1514
1534
|
var USER_SCOPE_PATH2 = join3(homedir3(), ".codex", "hooks.json");
|
|
1515
1535
|
var projectScopePath2 = () => join3(projectRoot(), ".codex", "hooks.json");
|
|
@@ -1562,9 +1582,6 @@ function performInstall2(scope, force) {
|
|
|
1562
1582
|
if (changed) {
|
|
1563
1583
|
atomicWrite2(path, after);
|
|
1564
1584
|
}
|
|
1565
|
-
if (scope === "project") {
|
|
1566
|
-
activateRepoBestEffort(process.cwd());
|
|
1567
|
-
}
|
|
1568
1585
|
return resultFor(scope, path, after, changed);
|
|
1569
1586
|
}
|
|
1570
1587
|
function performUninstall2(scope) {
|
|
@@ -2775,7 +2792,9 @@ function toRequestBody(request) {
|
|
|
2775
2792
|
alternatives: request.alternatives,
|
|
2776
2793
|
confidence: request.confidence,
|
|
2777
2794
|
reversibility: request.reversibility,
|
|
2778
|
-
files: request.files
|
|
2795
|
+
files: request.files,
|
|
2796
|
+
protocolVersion: request.protocolVersion,
|
|
2797
|
+
repoSyncId: request.repoSyncId
|
|
2779
2798
|
};
|
|
2780
2799
|
const body = {};
|
|
2781
2800
|
for (const [key, value] of Object.entries(candidate)) {
|
|
@@ -3115,10 +3134,29 @@ function registerDecisionsCommands(program2) {
|
|
|
3115
3134
|
).option("--kind <kind>", "change | exploration | task_execution | unclear (default change)").option("--rationale <text>", "Why the decision was made").option(
|
|
3116
3135
|
"--area <area>",
|
|
3117
3136
|
"Functional area (auth, data, infra, ui, api, billing, mobile, docs, testing)"
|
|
3118
|
-
).option("--decided <items>", "Comma-separated option(s) chosen").option("--alternatives <items>", "Comma-separated options considered but rejected").option("--confidence <level>", "high | medium | low (default high)").option("--reversibility <level>", "high | low (default high)").option(
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3137
|
+
).option("--decided <items>", "Comma-separated option(s) chosen").option("--alternatives <items>", "Comma-separated options considered but rejected").option("--confidence <level>", "high | medium | low (default high)").option("--reversibility <level>", "high | low (default high)").option("--files <paths>", "Comma-separated exact repo-relative paths this decision governs").action(async (opts, command) => {
|
|
3138
|
+
const requestedFiles = splitList(opts.files);
|
|
3139
|
+
let explicitScope = {};
|
|
3140
|
+
if (requestedFiles.length > 0) {
|
|
3141
|
+
const binding = repoSyncId(process.cwd());
|
|
3142
|
+
const root = canonicalGitRoot(process.cwd());
|
|
3143
|
+
const canonical = requestedFiles.map(
|
|
3144
|
+
(path) => canonicalRepositoryPath(path, root ?? process.cwd(), root)
|
|
3145
|
+
);
|
|
3146
|
+
if (!binding || canonical.some((path) => !path)) {
|
|
3147
|
+
console.error(
|
|
3148
|
+
"[prim] scoped decision rejected: run `prim enable` and provide exact in-repository file paths"
|
|
3149
|
+
);
|
|
3150
|
+
console.log(JSON.stringify({ ok: false, error: "invalid_repository_scope" }, null, 2));
|
|
3151
|
+
process.exitCode = EXIT_USAGE;
|
|
3152
|
+
return;
|
|
3153
|
+
}
|
|
3154
|
+
explicitScope = {
|
|
3155
|
+
protocolVersion: 3,
|
|
3156
|
+
repoSyncId: binding,
|
|
3157
|
+
files: canonical
|
|
3158
|
+
};
|
|
3159
|
+
}
|
|
3122
3160
|
if (!isRepoActiveForCapture(process.cwd())) {
|
|
3123
3161
|
const globals = command.optsWithGlobals();
|
|
3124
3162
|
const nonInteractive = isNonInteractive(globals);
|
|
@@ -3141,7 +3179,7 @@ function registerDecisionsCommands(program2) {
|
|
|
3141
3179
|
alternatives: splitList(opts.alternatives),
|
|
3142
3180
|
confidence: opts.confidence,
|
|
3143
3181
|
reversibility: opts.reversibility,
|
|
3144
|
-
|
|
3182
|
+
...explicitScope
|
|
3145
3183
|
};
|
|
3146
3184
|
try {
|
|
3147
3185
|
const outcome = await fetchCreate(request);
|
|
@@ -3562,13 +3600,19 @@ var HERMES_ARGS = "--agent hermes";
|
|
|
3562
3600
|
var EDIT_MATCHER = "write_file|patch";
|
|
3563
3601
|
var JSON_INDENT3 = 2;
|
|
3564
3602
|
var SHIM_MODE = 493;
|
|
3565
|
-
var PRIM_BINS3 = [
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3603
|
+
var PRIM_BINS3 = [CAPTURE_BIN3, GATE_BIN3, POST_TOOL_USE_BIN3, SESSION_START_BIN3, SESSION_END_BIN2];
|
|
3604
|
+
var PINNED_VERSION = packageVersion();
|
|
3605
|
+
if (!PINNED_VERSION) throw new Error("cannot determine Primitive package version");
|
|
3606
|
+
var sh = (value) => `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
3607
|
+
var PINNED_NODE = sh(process.execPath);
|
|
3608
|
+
var PINNED_CASES = PRIM_BINS3.map((bin) => {
|
|
3609
|
+
const file = binFile(bin);
|
|
3610
|
+
if (!file) throw new Error(`cannot locate Primitive hook binary: ${bin}`);
|
|
3611
|
+
return ` ${bin})
|
|
3612
|
+
if [ -x ${PINNED_NODE} ] && [ -f ${sh(file)} ]; then exec ${PINNED_NODE} ${sh(file)} "$@"; fi
|
|
3613
|
+
exec npx --yes -p @primitive.ai/prim@${PINNED_VERSION} "$bin" "$@"
|
|
3614
|
+
;;`;
|
|
3615
|
+
}).join("\n");
|
|
3572
3616
|
function hermesHome() {
|
|
3573
3617
|
return process.env.HERMES_HOME ?? join5(homedir5(), ".hermes");
|
|
3574
3618
|
}
|
|
@@ -3580,17 +3624,13 @@ function shimPath() {
|
|
|
3580
3624
|
}
|
|
3581
3625
|
var SHIM_SCRIPT = `#!/bin/sh
|
|
3582
3626
|
# prim Hermes hook shim \u2014 managed by \`prim hermes install\`. Hermes runs hooks
|
|
3583
|
-
# with shell=False, so
|
|
3584
|
-
# shell does for the Claude Code / Codex installs lives here instead.
|
|
3627
|
+
# with shell=False, so exact package entrypoints are selected here.
|
|
3585
3628
|
bin="$1"
|
|
3586
3629
|
shift
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
exec "./node_modules/.bin/$bin" "$@"
|
|
3592
|
-
fi
|
|
3593
|
-
exec npx --yes -p @primitive.ai/prim@latest "$bin" "$@"
|
|
3630
|
+
case "$bin" in
|
|
3631
|
+
${PINNED_CASES}
|
|
3632
|
+
esac
|
|
3633
|
+
exit 64
|
|
3594
3634
|
`;
|
|
3595
3635
|
function commandFor(bin) {
|
|
3596
3636
|
return `"${shimPath()}" ${bin} ${HERMES_ARGS}`;
|
|
@@ -3899,13 +3939,7 @@ var PRIM_BLOCK_END = blockMarkers(PRE_COMMIT).end;
|
|
|
3899
3939
|
var PRIM_MANAGED_MARK = "prim-managed-hook";
|
|
3900
3940
|
var PRIM_CREATED_MARK = "prim-created-hook";
|
|
3901
3941
|
function hookShim(binName) {
|
|
3902
|
-
return `
|
|
3903
|
-
${binName} || true
|
|
3904
|
-
elif [ -f "./node_modules/.bin/${binName}" ]; then
|
|
3905
|
-
./node_modules/.bin/${binName} || true
|
|
3906
|
-
else
|
|
3907
|
-
npx --yes -p @primitive.ai/prim ${binName} 2>/dev/null || true
|
|
3908
|
-
fi`;
|
|
3942
|
+
return `{ ${pinnedHookCommand(binName)}; } || true`;
|
|
3909
3943
|
}
|
|
3910
3944
|
function gatedShim(binName) {
|
|
3911
3945
|
return `if [ "$(git config --get prim.active 2>/dev/null)" = "true" ]; then
|
|
@@ -4170,7 +4204,6 @@ function installHooks(gitRoot, target) {
|
|
|
4170
4204
|
installToDotGit(gitRoot, spec);
|
|
4171
4205
|
}
|
|
4172
4206
|
}
|
|
4173
|
-
activateRepoBestEffort(gitRoot);
|
|
4174
4207
|
}
|
|
4175
4208
|
function registerHooksCommands(program2) {
|
|
4176
4209
|
const hooks = program2.command("hooks").description("Manage git hooks");
|
|
@@ -4712,9 +4745,12 @@ function planSetupSteps(opts) {
|
|
|
4712
4745
|
});
|
|
4713
4746
|
const skillArgs = ["skill", "install", "--agent", opts.agent, ...scopeArgs];
|
|
4714
4747
|
steps.push({ key: "skill", label: "Agent skill", args: skillArgs, required: true });
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4748
|
+
steps.push({
|
|
4749
|
+
key: "enable",
|
|
4750
|
+
label: "Bind and activate this repo",
|
|
4751
|
+
args: ["enable"],
|
|
4752
|
+
required: true
|
|
4753
|
+
});
|
|
4718
4754
|
return steps;
|
|
4719
4755
|
}
|
|
4720
4756
|
var CONFLICT_SESSION = "session";
|
package/dist/statusline-main.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/commands/statusline.ts
|
|
4
4
|
import { readFileSync as readFileSync5 } from "fs";
|
|
5
|
-
import { dirname as
|
|
5
|
+
import { dirname as dirname5, resolve as resolve3 } from "path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7
7
|
|
|
8
8
|
// src/client.ts
|
|
@@ -63,7 +63,7 @@ function daemonRequest(method, params = {}, opts = {}) {
|
|
|
63
63
|
const id = nextRequestId++;
|
|
64
64
|
const request = { id, method, params };
|
|
65
65
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
66
|
-
return new Promise((
|
|
66
|
+
return new Promise((resolve4) => {
|
|
67
67
|
let settled = false;
|
|
68
68
|
let socket;
|
|
69
69
|
let buffer = "";
|
|
@@ -78,7 +78,7 @@ function daemonRequest(method, params = {}, opts = {}) {
|
|
|
78
78
|
} catch {
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
|
|
81
|
+
resolve4(value);
|
|
82
82
|
};
|
|
83
83
|
const timer = setTimeout(() => settle(null), timeoutMs);
|
|
84
84
|
timer.unref();
|
|
@@ -140,6 +140,8 @@ import { join as join4 } from "path";
|
|
|
140
140
|
|
|
141
141
|
// src/lib/git.ts
|
|
142
142
|
import { execFileSync } from "child_process";
|
|
143
|
+
import { lstatSync, realpathSync } from "fs";
|
|
144
|
+
import { basename, dirname as dirname3, isAbsolute, relative, resolve as resolve2, sep } from "path";
|
|
143
145
|
function gitToplevel(cwd) {
|
|
144
146
|
try {
|
|
145
147
|
return execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
@@ -202,7 +204,7 @@ import { join as join6 } from "path";
|
|
|
202
204
|
|
|
203
205
|
// src/lib/bin-path.ts
|
|
204
206
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
205
|
-
import { dirname as
|
|
207
|
+
import { dirname as dirname4, isAbsolute as isAbsolute2, join as join5 } from "path";
|
|
206
208
|
import { fileURLToPath } from "url";
|
|
207
209
|
var PKG_NAME = "@primitive.ai/prim";
|
|
208
210
|
var NPX_FALLBACK = `npx --yes -p ${PKG_NAME}@latest`;
|
|
@@ -271,13 +273,13 @@ var STATUSLINE_TIMEOUT_MS = 200;
|
|
|
271
273
|
var STATUSLINE_NAME_CAP = 3;
|
|
272
274
|
function readPackageVersion() {
|
|
273
275
|
try {
|
|
274
|
-
const here =
|
|
276
|
+
const here = dirname5(fileURLToPath2(import.meta.url));
|
|
275
277
|
const candidates = [
|
|
276
278
|
// The supervised runtime stages a tiny manifest beside the standalone
|
|
277
279
|
// statusline bundle, so it remains versioned without loading the package.
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
280
|
+
resolve3(here, "manifest.json"),
|
|
281
|
+
resolve3(here, "../../package.json"),
|
|
282
|
+
resolve3(here, "../package.json")
|
|
281
283
|
];
|
|
282
284
|
for (const path of candidates) {
|
|
283
285
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primitive.ai/prim",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.57",
|
|
4
4
|
"description": "CLI for Primitive's decision graph — passive decision capture, conflict gate, and team presence",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"commander": "^12.1.0",
|
|
64
64
|
"diff": "^5.2.0",
|
|
65
|
+
"unbash": "4.0.3",
|
|
65
66
|
"update-notifier": "^7.3.1",
|
|
66
67
|
"yaml": "^2.9.0"
|
|
67
68
|
},
|
package/dist/chunk-R5ZJRSLV.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
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
|
-
function decisionIngestionStatus(cwd) {
|
|
73
|
-
return isRepoActiveForCapture(cwd) ? "enabled" : "disabled";
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export {
|
|
77
|
-
gitToplevel,
|
|
78
|
-
setRepoActive,
|
|
79
|
-
activateRepoBestEffort,
|
|
80
|
-
isRepoActiveForCapture,
|
|
81
|
-
decisionIngestionStatus
|
|
82
|
-
};
|