sphinx-understand 0.1.1 → 0.1.3
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/package.json +4 -2
- package/scripts/postinstall.js +23 -0
- package/src/agent-settings.js +3 -5
- package/src/agent.js +11 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sphinx-understand",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Outsource your thinking, not your understanding. A comprehension checkpoint for agent-assisted development.",
|
|
5
5
|
"homepage": "https://github.com/parthh01/sphinx#readme",
|
|
6
6
|
"repository": {
|
|
@@ -21,11 +21,13 @@
|
|
|
21
21
|
"test": "node scripts/run-suite.mjs",
|
|
22
22
|
"check": "node --check bin/sphinx.js && node scripts/run-suite.mjs",
|
|
23
23
|
"start": "node bin/sphinx.js",
|
|
24
|
-
"eval": "node eval/run.js"
|
|
24
|
+
"eval": "node eval/run.js",
|
|
25
|
+
"postinstall": "node scripts/postinstall.js"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
27
28
|
"bin",
|
|
28
29
|
"src",
|
|
30
|
+
"scripts/postinstall.js",
|
|
29
31
|
"docs",
|
|
30
32
|
"eval/RESULTS.md",
|
|
31
33
|
"eval/fixtures/known-false-negatives.json",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Prints a setup hint after `npm install -g`. It changes nothing on the machine.
|
|
2
|
+
// npm 7+ hides lifecycle output, so write to the terminal device directly and
|
|
3
|
+
// stay silent when there is none (CI, Docker, IDEs).
|
|
4
|
+
import { openSync, writeSync, closeSync, existsSync } from 'node:fs';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
|
|
8
|
+
const env = process.env;
|
|
9
|
+
const global = env.npm_config_global === 'true' || env.npm_config_location === 'global';
|
|
10
|
+
if (global && !(env.CI && !['false', '0'].includes(env.CI))) {
|
|
11
|
+
const home = env.SPHINX_HOME || path.join(env.SPHINX_USER_HOME || homedir(), '.config', 'sphinx');
|
|
12
|
+
const setUp = existsSync(path.join(home, 'install.json'));
|
|
13
|
+
const color = !env.NO_COLOR && env.TERM !== 'dumb';
|
|
14
|
+
const amber = text => color ? `\x1b[38;5;179m${text}\x1b[0m` : text;
|
|
15
|
+
const bold = text => color ? `\x1b[1m${text}\x1b[0m` : text;
|
|
16
|
+
const message = setUp
|
|
17
|
+
? `\n ${amber('sphinx')} updated. Apply it to your Git and agent hooks (your settings are kept):\n\n ${bold('sphinx install')}\n\n`
|
|
18
|
+
: `\n ${amber('sphinx')} is installed. Finish setup to connect Git and your coding agents:\n\n ${bold('sphinx install')}\n\n`;
|
|
19
|
+
try {
|
|
20
|
+
const tty = openSync(process.platform === 'win32' ? 'CON' : '/dev/tty', 'w');
|
|
21
|
+
try { writeSync(tty, message); } finally { closeSync(tty); }
|
|
22
|
+
} catch { /* No terminal: nothing to show. */ }
|
|
23
|
+
}
|
package/src/agent-settings.js
CHANGED
|
@@ -99,11 +99,9 @@ function assertNoCodexConflict(text, file) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export function nativeHookSpecs(name, sessionHandler) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
timeout: 1800, statusMessage: 'Sphinx understanding check',
|
|
106
|
-
};
|
|
102
|
+
// A plain command, not an MCP tool call: it needs no MCP connection, so it works
|
|
103
|
+
// in sessions opened before installation and exits silently when nothing is queued.
|
|
104
|
+
const handler = { type: 'command', command: sessionHandler.command, timeout: 1800, statusMessage: 'Sphinx understanding check' };
|
|
107
105
|
return [
|
|
108
106
|
// Codex uses the handler's statusMessage as its /hooks display name too.
|
|
109
107
|
{ event: 'SessionStart', group: { hooks: [{ ...sessionHandler, statusMessage: 'Sphinx session setup' }] } },
|
package/src/agent.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { constants } from 'node:fs';
|
|
2
|
+
import { browserHandoff } from './lifecycle-integrations.js';
|
|
2
3
|
import { open } from 'node:fs/promises';
|
|
3
4
|
|
|
4
5
|
/** Session setup only. Git and native lifecycle hooks control the actual checkpoint. */
|
|
@@ -12,6 +13,15 @@ export async function agentHook({ agent, event, input = '', env = process.env })
|
|
|
12
13
|
throw new Error('Agent hook input must be valid JSON.');
|
|
13
14
|
}
|
|
14
15
|
const name = payload?.hook_event_name || event;
|
|
16
|
+
if (['PostToolUse', 'PostToolUseFailure'].includes(name)) {
|
|
17
|
+
// Fallback only: Git normally waits in its own hook. Open the browser for a
|
|
18
|
+
// checkpoint queued by Git, and stay silent when nothing is queued.
|
|
19
|
+
let notice;
|
|
20
|
+
try {
|
|
21
|
+
notice = await browserHandoff({ cwd: typeof payload.cwd === 'string' ? payload.cwd : undefined, host: agent, hostSession: /^[A-Za-z0-9_-]{1,200}$/.test(payload?.session_id || '') ? payload.session_id : undefined, env });
|
|
22
|
+
} catch { notice = 'Sphinx could not inspect its checkpoint queue. The human can run sphinx doctor and sphinx check in their own terminal. Do not answer for them.'; }
|
|
23
|
+
return notice ? { exitCode: 0, output: { hookSpecificOutput: { hookEventName: name, additionalContext: notice } } } : { output: null, exitCode: 0 };
|
|
24
|
+
}
|
|
15
25
|
if (name !== 'SessionStart') return { output: null, exitCode: 0 };
|
|
16
26
|
if (agent === 'claude' && env.CLAUDE_ENV_FILE && /^[A-Za-z0-9_-]{1,200}$/.test(payload?.session_id || '')) {
|
|
17
27
|
// Claude's documented SessionStart environment channel tags later Bash calls,
|
|
@@ -30,7 +40,7 @@ export async function agentHook({ agent, event, input = '', env = process.env })
|
|
|
30
40
|
'Repository branch and event policy lives in .sphinxconfig (with .sphinx.json as a legacy fallback). Use `sphinx status --json` to inspect effective policy and pending assessments; do not change policy to avoid a checkpoint.',
|
|
31
41
|
'Git deterministically requires a checkpoint when repository policy matches a push or commit. For blocking checkpoints it serves a local browser questionnaire and keeps the original Git operation waiting. On macOS the page opens in the background without activating or minimizing the coding window; other environments print the local URL. After the human passes and Git verifies the exact change and policy, that same operation continues automatically. Do not start a duplicate Git operation while it waits.',
|
|
32
42
|
'Allow enough shell execution time for the human questionnaire. Sphinx waits up to 25 minutes, but the host may cancel the shell sooner. Keep the original process running using the host\'s supported yielding or background execution; do not terminate or duplicate it while the human answers.',
|
|
33
|
-
'If
|
|
43
|
+
'If Git could not keep a questionnaire open, the installed PostToolUse hook opens the same local browser questionnaire after the shell command exits. This fallback does not resume an exited Git process; you do not initiate or conduct the interview.',
|
|
34
44
|
'Sphinx collects the human\'s answers directly in its local browser page, explicit terminal check, or fallback native forms and grades them using an independent evaluator. Only the outcome is returned to you. Do not relay questions through chat, call sphinx answer/explain/dispute for the human, or open its local URL or automate the questionnaire UI.',
|
|
35
45
|
'Never answer on the human\'s behalf, fabricate a response, read private Sphinx session files or answer keys, or bypass the Git hook to finish the task.',
|
|
36
46
|
'Respect .sphinxignore and configured exclusions: do not read excluded files to supplement an assessment or send them to the evaluator.',
|