@jentrix/cli 0.5.19 → 0.5.20
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/codex-plugin/plugins/jentrix/.codex-plugin/plugin.json +3 -3
- package/codex-plugin/plugins/jentrix/hooks/hooks.json +17 -10
- package/codex-plugin/plugins/jentrix/skills/jentrix-align/SKILL.md +7 -0
- package/codex-plugin/plugins/jentrix/skills/jentrix-connect/SKILL.md +7 -2
- package/codex-plugin/plugins/jentrix/skills/jentrix-status/SKILL.md +5 -1
- package/dist/main.js +27 -6
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jentrix",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Connect Codex tasks to Jentrix
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "Connect Codex tasks to Jentrix with trusted lifecycle hooks, exact-rollout telemetry recovery, typed artifacts, and operator-confirmed alignment.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Jentrix",
|
|
7
7
|
"url": "https://github.com/jentrix-au"
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"interface": {
|
|
15
15
|
"displayName": "Jentrix",
|
|
16
16
|
"shortDescription": "Connect this Codex task to Jentrix.",
|
|
17
|
-
"longDescription": "Align a Codex task to a Jentrix project and task, preserve typed checkpoints,
|
|
17
|
+
"longDescription": "Align a Codex task to a Jentrix project and task, preserve typed artifacts and checkpoints, capture supported lifecycle evidence through trusted hooks, and recover provider-reported usage from the exact task rollout when hooks are unavailable.",
|
|
18
18
|
"developerName": "Jentrix",
|
|
19
19
|
"category": "Productivity",
|
|
20
20
|
"capabilities": ["Interactive", "Write"],
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Trusted Codex lifecycle bridge.
|
|
2
|
+
"description": "Trusted Codex lifecycle bridge. Structured hook stdin is appended locally; credentials and transcript content never enter argv. Hooks remain inactive until the operator reviews and trusts them. PreCompact/PostCompact additionally preserve the approved capture boundary; capture off records only the boundary, never transcript content.",
|
|
3
3
|
"hooks": {
|
|
4
4
|
"SessionStart": [
|
|
5
5
|
{
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "stacks-runner session-hook --provider codex --event SessionStart"
|
|
9
|
+
"command": "stacks-runner session-hook --provider codex --event SessionStart",
|
|
10
|
+
"timeout": 3
|
|
10
11
|
}
|
|
11
12
|
]
|
|
12
13
|
}
|
|
@@ -16,7 +17,8 @@
|
|
|
16
17
|
"hooks": [
|
|
17
18
|
{
|
|
18
19
|
"type": "command",
|
|
19
|
-
"command": "stacks-runner session-hook --provider codex --event UserPromptSubmit"
|
|
20
|
+
"command": "stacks-runner session-hook --provider codex --event UserPromptSubmit",
|
|
21
|
+
"timeout": 3
|
|
20
22
|
}
|
|
21
23
|
]
|
|
22
24
|
}
|
|
@@ -26,7 +28,8 @@
|
|
|
26
28
|
"hooks": [
|
|
27
29
|
{
|
|
28
30
|
"type": "command",
|
|
29
|
-
"command": "stacks-runner session-hook --provider codex --event PostToolUse"
|
|
31
|
+
"command": "stacks-runner session-hook --provider codex --event PostToolUse",
|
|
32
|
+
"timeout": 3
|
|
30
33
|
}
|
|
31
34
|
]
|
|
32
35
|
}
|
|
@@ -36,7 +39,8 @@
|
|
|
36
39
|
"hooks": [
|
|
37
40
|
{
|
|
38
41
|
"type": "command",
|
|
39
|
-
"command": "stacks-runner session-hook --provider codex --event Stop"
|
|
42
|
+
"command": "stacks-runner session-hook --provider codex --event Stop",
|
|
43
|
+
"timeout": 3
|
|
40
44
|
}
|
|
41
45
|
]
|
|
42
46
|
}
|
|
@@ -47,12 +51,13 @@
|
|
|
47
51
|
{
|
|
48
52
|
"type": "command",
|
|
49
53
|
"command": "stacks-runner session-hook --provider codex --event PreCompact",
|
|
50
|
-
"timeout":
|
|
54
|
+
"timeout": 3
|
|
51
55
|
},
|
|
52
56
|
{
|
|
53
57
|
"type": "command",
|
|
54
58
|
"command": "jentrix session snapshot --event PreCompact",
|
|
55
|
-
"timeout": 10
|
|
59
|
+
"timeout": 10,
|
|
60
|
+
"statusMessage": "Preserving the Jentrix capture boundary"
|
|
56
61
|
}
|
|
57
62
|
]
|
|
58
63
|
}
|
|
@@ -63,12 +68,13 @@
|
|
|
63
68
|
{
|
|
64
69
|
"type": "command",
|
|
65
70
|
"command": "stacks-runner session-hook --provider codex --event PostCompact",
|
|
66
|
-
"timeout":
|
|
71
|
+
"timeout": 3
|
|
67
72
|
},
|
|
68
73
|
{
|
|
69
74
|
"type": "command",
|
|
70
75
|
"command": "jentrix session snapshot --event PostCompact",
|
|
71
|
-
"timeout": 10
|
|
76
|
+
"timeout": 10,
|
|
77
|
+
"statusMessage": "Recording the Jentrix compaction boundary"
|
|
72
78
|
}
|
|
73
79
|
]
|
|
74
80
|
}
|
|
@@ -78,7 +84,8 @@
|
|
|
78
84
|
"hooks": [
|
|
79
85
|
{
|
|
80
86
|
"type": "command",
|
|
81
|
-
"command": "stacks-runner session-hook --provider codex --event SessionEnd"
|
|
87
|
+
"command": "stacks-runner session-hook --provider codex --event SessionEnd",
|
|
88
|
+
"timeout": 3
|
|
82
89
|
}
|
|
83
90
|
]
|
|
84
91
|
}
|
|
@@ -34,6 +34,13 @@ description: Align the current Codex task to a Jentrix workspace, project, work
|
|
|
34
34
|
8. Echo the returned server alignment snapshot verbatim. If `.mcp.json` changed,
|
|
35
35
|
explain that the current task must reconnect MCP or restart before using it.
|
|
36
36
|
|
|
37
|
+
If detection names an exact Codex rollout fallback instead of a lifecycle-hook
|
|
38
|
+
record, say what that means: provider token receipts and the opening prompt remain
|
|
39
|
+
collectable, but prompt/tool/assistant lifecycle events are not. Direct the operator
|
|
40
|
+
to review and trust the plugin hooks with `/hooks`, then start a new Codex task for
|
|
41
|
+
full lifecycle coverage. Never claim `coverage: COMPLETE` for token receipts proves
|
|
42
|
+
that hooks ran.
|
|
43
|
+
|
|
37
44
|
TRACE capture is off by default. Pass `--capture` only when the operator explicitly
|
|
38
45
|
approved full hook-derived trace capture. Same-project re-alignment converges;
|
|
39
46
|
different-project re-alignment must be refused until `jentrix session end`.
|
|
@@ -18,5 +18,10 @@ trusted environment and lifecycle-hook context. Relay the command output or erro
|
|
|
18
18
|
verbatim. The command starts the hook-watching host in the background and prints
|
|
19
19
|
its pid; do not start a second host. Never put credentials on the command line.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
When lifecycle hooks are unavailable, the CLI may recover telemetry only from the
|
|
22
|
+
exact `rollout-*-${CODEX_THREAD_ID}.jsonl` under the trusted Codex home. Accept that
|
|
23
|
+
exact match; never choose the newest session file. Explain that the fallback keeps
|
|
24
|
+
provider token receipts and opening-prompt provenance, but not prompt/tool/assistant
|
|
25
|
+
lifecycle events. Direct the operator to review and trust the plugin hooks with
|
|
26
|
+
`/hooks`, then start a new Codex task for full lifecycle coverage. If trusted task
|
|
27
|
+
identity or the exact rollout is unavailable, relay the refusal and do not guess.
|
|
@@ -8,4 +8,8 @@ description: Show the connected Jentrix session, alignment, capture health, and
|
|
|
8
8
|
|
|
9
9
|
Run `jentrix session status` and append the session id when the user supplied one.
|
|
10
10
|
Relay stdout and stderr verbatim, including capture or telemetry warnings. Never turn
|
|
11
|
-
null token values into zero or infer provider usage that
|
|
11
|
+
null token values into zero or infer provider usage that Codex did not report.
|
|
12
|
+
`coverage: COMPLETE` describes provider token-receipt coverage only; it does not prove
|
|
13
|
+
the lifecycle hooks ran. If the session uses the exact-rollout fallback, report that
|
|
14
|
+
prompt/tool/assistant lifecycle evidence is unavailable and point to `/hooks` plus a
|
|
15
|
+
new Codex task for future full coverage.
|
package/dist/main.js
CHANGED
|
@@ -20966,7 +20966,7 @@ function refreshAccessToken(input) {
|
|
|
20966
20966
|
|
|
20967
20967
|
// src/client.ts
|
|
20968
20968
|
var CLI_NAME = "stacks-cli";
|
|
20969
|
-
var CLI_VERSION = "0.5.
|
|
20969
|
+
var CLI_VERSION = "0.5.20";
|
|
20970
20970
|
var DEAD_TOKEN_MESSAGE = "authentication failed (HTTP 401): the token is dead or expired \u2014 mint a new PAT at /account/tokens on your Jentrix server and update STACKS_TOKEN (or --token / the config file).";
|
|
20971
20971
|
var RELOGIN_MESSAGE = "OAuth session expired and could not be refreshed \u2014 run `jentrix login` to sign in again.";
|
|
20972
20972
|
function originOf2(url2) {
|
|
@@ -22663,6 +22663,23 @@ function hooksDir(deps2, provider) {
|
|
|
22663
22663
|
function codexHooksDir(deps2) {
|
|
22664
22664
|
return hooksDir(deps2, "codex");
|
|
22665
22665
|
}
|
|
22666
|
+
function readCodexRolloutPath(deps2, sessionId) {
|
|
22667
|
+
const configuredHome = deps2.env.CODEX_HOME?.trim() || null;
|
|
22668
|
+
const userHome = deps2.env.HOME ?? deps2.env.USERPROFILE;
|
|
22669
|
+
const home = configuredHome ?? (userHome ? join2(userHome, ".codex") : null);
|
|
22670
|
+
if (!home) return null;
|
|
22671
|
+
const root = join2(home, "sessions");
|
|
22672
|
+
const suffix = `-${sessionId}.jsonl`;
|
|
22673
|
+
try {
|
|
22674
|
+
const relative = readdirSync(root, {
|
|
22675
|
+
encoding: "utf8",
|
|
22676
|
+
recursive: true
|
|
22677
|
+
}).find((path) => path.endsWith(suffix));
|
|
22678
|
+
return relative ? join2(root, relative) : null;
|
|
22679
|
+
} catch {
|
|
22680
|
+
return null;
|
|
22681
|
+
}
|
|
22682
|
+
}
|
|
22666
22683
|
function readClaudeHookContext(deps2, readFile = (path) => readFileSync2(path, "utf8"), mtimeOf = transcriptMtime, now = Date.now) {
|
|
22667
22684
|
const own = deps2.env[CLAUDE_SESSION_ENV]?.trim() || null;
|
|
22668
22685
|
const home = deps2.env.HOME ?? deps2.env.USERPROFILE;
|
|
@@ -22744,11 +22761,12 @@ function readCodexHookContext(deps2, readFile = (path) => readFileSync2(path, "u
|
|
|
22744
22761
|
const { starts, endedAt } = ledger;
|
|
22745
22762
|
if (own) {
|
|
22746
22763
|
const source = threadId ? CODEX_THREAD_ENV : CODEX_SESSION_ENV;
|
|
22747
|
-
const
|
|
22764
|
+
const hookTranscript = transcriptForSessionIn(ledger, own);
|
|
22765
|
+
const transcriptPath = hookTranscript ?? readCodexRolloutPath(deps2, own);
|
|
22748
22766
|
return {
|
|
22749
22767
|
sessionId: own,
|
|
22750
22768
|
transcriptPath,
|
|
22751
|
-
basis: `${source}=${own} \u2014 this Codex task's own id${
|
|
22769
|
+
basis: `${source}=${own} \u2014 this Codex task's own id${hookTranscript ? " (rollout from its hook record)" : transcriptPath ? " (rollout resolved from Codex sessions)" : ""}`,
|
|
22752
22770
|
newerElsewhere: null
|
|
22753
22771
|
};
|
|
22754
22772
|
}
|
|
@@ -22771,7 +22789,7 @@ function readCodexHookContext(deps2, readFile = (path) => readFileSync2(path, "u
|
|
|
22771
22789
|
const match = matches[0];
|
|
22772
22790
|
return match ? {
|
|
22773
22791
|
sessionId: match.sessionId,
|
|
22774
|
-
transcriptPath: transcriptForSessionIn(ledger, match.sessionId),
|
|
22792
|
+
transcriptPath: transcriptForSessionIn(ledger, match.sessionId) ?? readCodexRolloutPath(deps2, match.sessionId),
|
|
22775
22793
|
basis: `unambiguous SessionStart${match.at ? ` at ${match.at}` : ""} in ${match.cwd}`,
|
|
22776
22794
|
newerElsewhere: null
|
|
22777
22795
|
} : null;
|
|
@@ -22861,6 +22879,8 @@ async function runSessionAttach(flags, deps2) {
|
|
|
22861
22879
|
}
|
|
22862
22880
|
} else if (flags.provider === "claude" && flags.providerSession && !flags.transcriptPath) {
|
|
22863
22881
|
flags.transcriptPath = readClaudeHookTranscript(deps2, flags.providerSession) ?? void 0;
|
|
22882
|
+
} else if (flags.provider === "codex" && flags.providerSession && !flags.transcriptPath) {
|
|
22883
|
+
flags.transcriptPath = readCodexRolloutPath(deps2, flags.providerSession) ?? void 0;
|
|
22864
22884
|
}
|
|
22865
22885
|
if (flags.provider === "codex") hookDir = codexHooksDir(deps2);
|
|
22866
22886
|
if (!flags.providerSession) {
|
|
@@ -23890,10 +23910,11 @@ function sessionBindingCheck(detected) {
|
|
|
23890
23910
|
function detectProvider(flags, deps2) {
|
|
23891
23911
|
if (flags.provider === "codex") {
|
|
23892
23912
|
const hook2 = flags.providerSession ? null : readCodexHookContext(deps2);
|
|
23913
|
+
const providerSessionId = flags.providerSession ?? hook2?.sessionId ?? null;
|
|
23893
23914
|
return {
|
|
23894
23915
|
provider: "codex",
|
|
23895
|
-
providerSessionId
|
|
23896
|
-
transcriptPath: flags.transcriptPath ?? hook2?.transcriptPath ?? null,
|
|
23916
|
+
providerSessionId,
|
|
23917
|
+
transcriptPath: flags.transcriptPath ?? hook2?.transcriptPath ?? (providerSessionId ? readCodexRolloutPath(deps2, providerSessionId) : null),
|
|
23897
23918
|
basis: flags.providerSession ? `codex thread ${flags.providerSession} (explicit)` : hook2?.basis ?? null,
|
|
23898
23919
|
newerElsewhere: null,
|
|
23899
23920
|
transcriptGap: null,
|