sneakoscope 0.7.6 → 0.7.13
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 +31 -27
- package/package.json +2 -2
- package/src/cli/context7-command.mjs +163 -0
- package/src/cli/install-helpers.mjs +325 -0
- package/src/cli/main.mjs +245 -509
- package/src/cli/maintenance-commands.mjs +31 -31
- package/src/core/artifact-schemas.mjs +6 -6
- package/src/core/codex-app.mjs +1 -1
- package/src/core/db-safety.mjs +1 -1
- package/src/core/evaluation.mjs +3 -3
- package/src/core/fsx.mjs +1 -1
- package/src/core/init.mjs +20 -14
- package/src/core/pipeline.mjs +14 -3
- package/src/core/ppt.mjs +694 -0
- package/src/core/questions.mjs +51 -7
- package/src/core/routes.mjs +60 -10
- package/src/core/team-live.mjs +8 -8
- package/src/core/tmux-ui.mjs +447 -0
- package/src/core/warp-ui.mjs +0 -557
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
Sneakoscope Codex (`sks`, displayed as `ㅅㅋㅅ`) is a Codex CLI/App harness for repeatable agent workflows. It adds terminal commands, Codex App `$` prompt commands,
|
|
5
|
+
Sneakoscope Codex (`sks`, displayed as `ㅅㅋㅅ`) is a Codex CLI/App harness for repeatable agent workflows. It adds terminal commands, Codex App `$` prompt commands, tmux-native CLI workspaces, Team/QA/Research routes, inspectable pipeline plans, a maximum-speed Computer Use lane, a fast Goal bridge for native `/goal` persistence, Context7 evidence checks, DB safety, TriWiki context tracking, lightweight skill dreaming, Honest Mode, and release-readiness gates.
|
|
6
6
|
|
|
7
7
|
## Quick Start
|
|
8
8
|
|
|
@@ -43,17 +43,19 @@ sks selftest --mock
|
|
|
43
43
|
|
|
44
44
|
| Area | What it does |
|
|
45
45
|
| --- | --- |
|
|
46
|
-
| CLI runtime | `sks
|
|
47
|
-
| Codex App commands | Installs generated skills so `$Team`, `$From-Chat-IMG`, `$DFix`, `$QA-LOOP`, `$Goal`, `$DB`, `$Wiki`, `$Help`, and related routes are visible in prompt workflows. |
|
|
46
|
+
| CLI runtime | `sks tmux open` and `sks --mad` explicitly launch Codex CLI with tmux; bare `sks` only prints help/readiness surfaces. |
|
|
47
|
+
| Codex App commands | Installs generated skills so `$Team`, `$From-Chat-IMG`, `$DFix`, `$QA-LOOP`, `$PPT`, `$Goal`, `$DB`, `$Wiki`, `$Help`, and related routes are visible in prompt workflows. |
|
|
48
48
|
| Pipeline plans | Writes `pipeline-plan.json` for stateful routes so the runtime lane, kept stages, skipped stages, verification commands, and no-unrequested-fallback invariant are visible with `sks pipeline plan`. |
|
|
49
49
|
| Team orchestration | Runs substantial work through ambiguity handling, scouts, TriWiki refresh, debate, runtime task graphs, worker inboxes, implementation, review, cleanup, reflection, and Honest Mode; narrow work should use Proof Field evidence to skip unrelated pipeline work instead of expanding Team. |
|
|
50
50
|
| Skill dreaming | Records cheap generated-skill usage counters in JSON and only periodically scans `.agents/skills` for keep, merge, prune, and improvement candidates. Reports are recommendation-only and never delete skills automatically. |
|
|
51
51
|
| From-Chat-IMG | Turns chat screenshots plus original attachments into source-bound work orders, then requires scoped QA evidence before completion. |
|
|
52
52
|
| QA loop | Dogfoods UI/API behavior with safety gates, Codex Computer Use-only UI evidence, safe fixes, and rechecks. |
|
|
53
|
+
| PPT pipeline | Uses `$PPT` for simple, restrained, information-first HTML/PDF presentation artifacts, first asking delivery context, audience profile, STP strategy, decision context, and 3+ pain-point to solution/aha mappings before source research, design-system work, HTML/PDF export, and render QA. Independent strategy/render/file-write phases run in parallel where inputs allow and are recorded in `ppt-parallel-report.json`; editable source HTML is preserved under `source-html/`, PPT-only temporary build files are cleaned after completion, and generated image assets must prefer Codex App built-in image generation through `$imagegen`. |
|
|
53
54
|
| Computer Use fast lane | Uses `$Computer-Use` / `$CU` for UI/browser/visual work that needs maximum speed: skip Team debate and upfront TriWiki loops, use Codex Computer Use directly, then refresh/validate TriWiki and run Honest Mode at final closeout. |
|
|
54
55
|
| Goal | Provides a fast SKS bridge overlay for Codex native persisted `/goal` create, pause, resume, and clear controls; implementation continues through the selected SKS execution route. |
|
|
55
56
|
| TriWiki voxels | Maintains `.sneakoscope/wiki/context-pack.json` as the context SSOT with coordinate anchors, voxel metadata, `attention.use_first`, and `attention.hydrate_first`. |
|
|
56
57
|
| Context7 | Requires current docs for external packages, APIs, MCPs, SDKs, and framework/runtime behavior when correctness depends on current guidance. |
|
|
58
|
+
| getdesign.md | Grounds `design.md`, UI/UX design systems, and presentation-like HTML/PDF artifacts in the official getdesign.md reference and Codex skill path. |
|
|
57
59
|
| DB safety | Treats SQL, migrations, Supabase, RLS, and destructive operations as high risk. |
|
|
58
60
|
| Release hygiene | Checks versioning, changelog, package contents, tarball size, syntax, selftests, and dry-run publishing. |
|
|
59
61
|
|
|
@@ -63,21 +65,21 @@ sks selftest --mock
|
|
|
63
65
|
- npm
|
|
64
66
|
- Codex CLI for terminal workflows
|
|
65
67
|
- Codex App for app-facing workflows, with Codex Computer Use required for UI/browser evidence
|
|
66
|
-
-
|
|
68
|
+
- tmux for the CLI-first runtime
|
|
67
69
|
- Context7 MCP for current-docs-gated routes
|
|
68
70
|
|
|
69
|
-
Install
|
|
71
|
+
Install tmux from [tmux.dev/download](https://www.tmux.dev/download). On macOS, Homebrew users can also install it with:
|
|
70
72
|
|
|
71
73
|
```sh
|
|
72
|
-
brew install
|
|
74
|
+
brew install tmux
|
|
73
75
|
```
|
|
74
76
|
|
|
75
77
|
`sks --mad` is stricter than the normal runtime path:
|
|
76
78
|
|
|
77
79
|
- Checks npm for a newer `sneakoscope` before launch and asks whether to update when the terminal can answer y/n.
|
|
78
80
|
- Installs the latest Codex CLI with `npm i -g @openai/codex@latest` when it is missing and you approve or pass `--yes`.
|
|
79
|
-
- Requires
|
|
80
|
-
-
|
|
81
|
+
- Requires tmux 3.x or newer before opening the session.
|
|
82
|
+
- Creates or reuses a named detached tmux session, splits panes, and prints the attach command.
|
|
81
83
|
|
|
82
84
|
## Installation
|
|
83
85
|
|
|
@@ -95,6 +97,8 @@ sks bootstrap
|
|
|
95
97
|
|
|
96
98
|
Project setup writes shared `.gitignore` entries for generated SKS files: `.sneakoscope/`, `.codex/`, `.agents/`, and managed `AGENTS.md`. Use `sks setup --local-only` when you want those excludes kept only in `.git/info/exclude`.
|
|
97
99
|
|
|
100
|
+
During npm postinstall, SKS also installs generated Codex App skills and tries the official getdesign Codex skill command, `skills add MohtashamMurshid/getdesign`, when the `skills` CLI is available. If that CLI is missing, setup still installs the generated `getdesign-reference` skill so UI/UX and presentation design-system work keeps using [getdesign.md](https://getdesign.md/) as a required reference.
|
|
101
|
+
|
|
98
102
|
### One-Shot Install
|
|
99
103
|
|
|
100
104
|
Use this when you do not want to keep a global install:
|
|
@@ -148,30 +152,30 @@ sks --version
|
|
|
148
152
|
```sh
|
|
149
153
|
sks bootstrap
|
|
150
154
|
sks deps check
|
|
151
|
-
sks deps install
|
|
155
|
+
sks deps install tmux
|
|
152
156
|
sks codex-app check
|
|
153
157
|
sks doctor --fix
|
|
154
158
|
sks fix-path
|
|
155
159
|
```
|
|
156
160
|
|
|
157
|
-
### Open Codex CLI With
|
|
161
|
+
### Open Codex CLI With tmux
|
|
158
162
|
|
|
159
163
|
```sh
|
|
160
|
-
sks
|
|
161
|
-
sks
|
|
162
|
-
sks
|
|
164
|
+
sks tmux open
|
|
165
|
+
sks tmux check
|
|
166
|
+
sks tmux status --once
|
|
163
167
|
```
|
|
164
168
|
|
|
165
|
-
`sks
|
|
169
|
+
`sks tmux open` creates or reuses a named tmux session for Codex CLI only when that is explicitly requested. `sks` and `sks tmux check` are diagnostic/help surfaces and do not start a workspace.
|
|
166
170
|
|
|
167
|
-
### MAD
|
|
171
|
+
### MAD tmux Launch
|
|
168
172
|
|
|
169
173
|
```sh
|
|
170
174
|
sks --mad
|
|
171
175
|
sks --mad --yes
|
|
172
176
|
```
|
|
173
177
|
|
|
174
|
-
This creates/uses the `sks-mad-high` Codex profile for a one-shot full-access, high-reasoning
|
|
178
|
+
This creates/uses the `sks-mad-high` Codex profile for a one-shot full-access, high-reasoning tmux session with `approval_policy = "on-request"` and `approvals_reviewer = "auto_review"`. It is scoped to that explicit command and does not change normal SKS/DB safety defaults. Repeat launches reuse the same named SKS MAD tmux session.
|
|
175
179
|
|
|
176
180
|
MAD does not disable the pipeline contract: stages, executors, reviewers, and auto-review policy still must not invent unrequested fallback implementation code. If the requested path cannot be implemented, SKS should block with evidence rather than add substitute behavior.
|
|
177
181
|
|
|
@@ -190,19 +194,19 @@ sks team "implement this feature" executor:3 reviewer:1
|
|
|
190
194
|
sks team watch latest
|
|
191
195
|
sks team lane latest --agent analysis_scout_1 --follow
|
|
192
196
|
sks team message latest --from analysis_scout_1 --to executor_1 --message "handoff note"
|
|
193
|
-
sks team cleanup-
|
|
197
|
+
sks team cleanup-tmux latest
|
|
194
198
|
sks team status latest
|
|
195
199
|
sks team dashboard latest
|
|
196
200
|
sks team log latest
|
|
197
201
|
```
|
|
198
202
|
|
|
199
|
-
Team mode prepares the mission, records live events, compiles runtime tasks and worker inboxes, writes schema-backed effort/work-order/dashboard artifacts, and opens a named
|
|
203
|
+
Team mode prepares the mission, records live events, compiles runtime tasks and worker inboxes, writes schema-backed effort/work-order/dashboard artifacts, and opens a named tmux Team session with split live lanes when tmux is available. `sks team dashboard` renders the cockpit panes for mission overview, agent lanes, task DAG, QA/dogfood, artifacts/evidence, and performance.
|
|
200
204
|
|
|
201
|
-
The
|
|
205
|
+
The tmux Team launch is a live orchestration screen: the first pane follows `sks team watch <mission-id> --follow` as the mission overview, and neighboring split panes follow individual `sks team lane <mission-id> --agent <name> --follow` views. SKS gives lanes role-specific colors, labels, and terminal titles, so scouts, planning/debate voices, executors, reviewers, and safety lanes are visually distinct while the same evidence is mirrored into `team-transcript.jsonl`, `team-live.md`, and `team-dashboard.json`.
|
|
202
206
|
|
|
203
207
|
Agent sessions communicate through the bounded Team transcript. Use `sks team message <mission-id|latest> --from <agent> --to <agent|all> --message "..."` to add direct or broadcast messages; lane panes show messages addressed to that agent plus the fallback global tail.
|
|
204
208
|
|
|
205
|
-
When the Team route reaches `session_cleanup`, SKS marks the
|
|
209
|
+
When the Team route reaches `session_cleanup`, SKS marks the tmux session record complete and asks `watch --follow` / `lane --follow` panes to show a cleanup summary and stop. You can also run `sks team cleanup-tmux <mission-id|latest>` manually, or `sks team cleanup-tmux latest --close` to kill the recorded tmux session.
|
|
206
210
|
|
|
207
211
|
### QA, Computer Use, Goal, Research, DB, Wiki, GX
|
|
208
212
|
|
|
@@ -278,7 +282,7 @@ Default setup adds these generated SKS paths to the project `.gitignore`; `--loc
|
|
|
278
282
|
|
|
279
283
|
Use `sks dollar-commands` to confirm that terminal discovery and Codex App prompt commands agree.
|
|
280
284
|
|
|
281
|
-
TriWiki is intentionally sparse: `sks wiki sweep` records demote, soft-forget, archive, delete, promote-to-skill, and promote-to-rule candidates instead of injecting every old claim into future prompts. `sks harness fixture` validates the broader Harness Growth Factory contract: deliberate forgetting fixtures, skill card metadata, experiment schema, tool-error taxonomy, permission profiles, MultiAgentV2 defaults, and
|
|
285
|
+
TriWiki is intentionally sparse: `sks wiki sweep` records demote, soft-forget, archive, delete, promote-to-skill, and promote-to-rule candidates instead of injecting every old claim into future prompts. `sks harness fixture` validates the broader Harness Growth Factory contract: deliberate forgetting fixtures, skill card metadata, experiment schema, tool-error taxonomy, permission profiles, MultiAgentV2 defaults, and tmux cockpit view coverage. `sks code-structure scan` flags handwritten files above 1000/2000/3000-line thresholds so new logic can be extracted before command files become harder to maintain.
|
|
282
286
|
|
|
283
287
|
## Prompt `$` Commands
|
|
284
288
|
|
|
@@ -318,8 +322,8 @@ sks selftest --mock
|
|
|
318
322
|
### Start A CLI Workspace
|
|
319
323
|
|
|
320
324
|
```sh
|
|
321
|
-
sks
|
|
322
|
-
sks
|
|
325
|
+
sks tmux check
|
|
326
|
+
sks tmux open
|
|
323
327
|
```
|
|
324
328
|
|
|
325
329
|
For the high-reasoning full-access profile:
|
|
@@ -381,14 +385,14 @@ npm install -g .
|
|
|
381
385
|
|
|
382
386
|
If the global command is stale, reinstall globally from the repo or from npm.
|
|
383
387
|
|
|
384
|
-
###
|
|
388
|
+
### tmux is missing
|
|
385
389
|
|
|
386
390
|
```sh
|
|
387
|
-
sks deps install
|
|
388
|
-
sks
|
|
391
|
+
sks deps install tmux
|
|
392
|
+
sks tmux check
|
|
389
393
|
```
|
|
390
394
|
|
|
391
|
-
Install
|
|
395
|
+
Install tmux from [tmux.dev/download](https://www.tmux.dev/download) or run `brew install tmux` on macOS, then re-run `sks tmux check`.
|
|
392
396
|
|
|
393
397
|
### Codex App tools are missing
|
|
394
398
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.13",
|
|
5
5
|
"description": "Sneakoscope Codex: database-safe Codex CLI/App harness with Team, Goal, AutoResearch, TriWiki, and Honest Mode.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"harness",
|
|
58
58
|
"codex-cli",
|
|
59
59
|
"codex-app",
|
|
60
|
-
"
|
|
60
|
+
"tmux",
|
|
61
61
|
"auto-review",
|
|
62
62
|
"browser-use",
|
|
63
63
|
"computer-use",
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { projectRoot, readJson, runProcess, sksRoot } from '../core/fsx.mjs';
|
|
2
|
+
import { getCodexInfo } from '../core/codex-adapter.mjs';
|
|
3
|
+
import { context7Docs, context7Resolve, context7Text, context7Tools } from '../core/context7-client.mjs';
|
|
4
|
+
import { context7Evidence, recordContext7Evidence } from '../core/pipeline.mjs';
|
|
5
|
+
import { stateFile } from '../core/mission.mjs';
|
|
6
|
+
import { checkContext7, ensureProjectContext7Config } from './install-helpers.mjs';
|
|
7
|
+
|
|
8
|
+
const flag = (args, name) => args.includes(name);
|
|
9
|
+
|
|
10
|
+
export async function context7Command(sub = 'check', args = []) {
|
|
11
|
+
const action = sub || 'check';
|
|
12
|
+
const setupScope = action === 'setup' ? readOption(args, '--scope', flag(args, '--global') ? 'global' : 'project') : null;
|
|
13
|
+
const root = action === 'setup' && setupScope === 'project' ? await projectRoot() : await sksRoot();
|
|
14
|
+
if (action === 'check') {
|
|
15
|
+
const result = await checkContext7(root);
|
|
16
|
+
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
17
|
+
console.log('SKS Context7 MCP\n');
|
|
18
|
+
console.log(`Project config: ${result.project.ok ? 'ok' : 'missing'} ${result.project.path}`);
|
|
19
|
+
console.log(`Global config: ${result.global.ok ? 'ok' : 'missing'} ${result.global.path}`);
|
|
20
|
+
console.log(`Codex mcp list: ${result.codex_mcp_list.ok ? 'ok' : result.codex_mcp_list.checked ? 'missing' : 'not checked'}`);
|
|
21
|
+
console.log(`Ready: ${result.ok ? 'yes' : 'no'}`);
|
|
22
|
+
if (!result.ok) console.log('\nRun: sks context7 setup --scope project');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (action === 'tools') {
|
|
26
|
+
const result = await context7Tools({ timeoutMs: readNumberOption(args, '--timeout-ms', 30000) });
|
|
27
|
+
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
28
|
+
console.log('SKS Context7 Local MCP Tools\n');
|
|
29
|
+
console.log(`Server: ${result.server.info?.name || 'context7'} ${result.server.info?.version || ''}`.trim());
|
|
30
|
+
console.log(`Command: ${result.server.command} ${result.server.args.join(' ')}`);
|
|
31
|
+
console.log(`Tools: ${result.tool_names.join(', ') || 'none'}`);
|
|
32
|
+
if (!result.tool_names.includes('resolve-library-id') || !result.tool_names.some((name) => name === 'query-docs' || name === 'get-library-docs')) {
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
console.log('\nContext7 local MCP is missing the required resolve/docs tools.');
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (action === 'resolve') {
|
|
39
|
+
const positional = positionalArgs(args);
|
|
40
|
+
const libraryName = positional.join(' ').trim();
|
|
41
|
+
if (!libraryName) throw new Error('Usage: sks context7 resolve <library-name> [--query "..."] [--json]');
|
|
42
|
+
const result = await context7Resolve(libraryName, {
|
|
43
|
+
query: readOption(args, '--query', libraryName),
|
|
44
|
+
timeoutMs: readNumberOption(args, '--timeout-ms', 30000)
|
|
45
|
+
});
|
|
46
|
+
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
47
|
+
console.log('SKS Context7 Resolve\n');
|
|
48
|
+
console.log(`Library: ${libraryName}`);
|
|
49
|
+
console.log(`ID: ${result.library_id || 'not resolved'}`);
|
|
50
|
+
console.log(`Server: ${result.server.info?.name || 'context7'} ${result.server.info?.version || ''}`.trim());
|
|
51
|
+
const text = context7Text(result.result).split(/\n/).slice(0, 24).join('\n').trim();
|
|
52
|
+
if (text) console.log(`\n${text}`);
|
|
53
|
+
if (!result.ok || !result.library_id) process.exitCode = 1;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (action === 'docs') {
|
|
57
|
+
const positional = positionalArgs(args);
|
|
58
|
+
const libraryNameOrId = positional.join(' ').trim();
|
|
59
|
+
if (!libraryNameOrId) throw new Error('Usage: sks context7 docs <library-name|/org/project> [--query "..."] [--topic "..."] [--tokens N] [--json]');
|
|
60
|
+
const result = await context7Docs(libraryNameOrId, {
|
|
61
|
+
query: readOption(args, '--query', readOption(args, '--topic', libraryNameOrId)),
|
|
62
|
+
topic: readOption(args, '--topic', libraryNameOrId),
|
|
63
|
+
tokens: readNumberOption(args, '--tokens', 2000),
|
|
64
|
+
timeoutMs: readNumberOption(args, '--timeout-ms', 30000)
|
|
65
|
+
});
|
|
66
|
+
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
67
|
+
printContext7DocsResult(result, { title: 'SKS Context7 Docs' });
|
|
68
|
+
if (!result.ok) process.exitCode = 1;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (action === 'evidence') {
|
|
72
|
+
const positional = positionalArgs(args);
|
|
73
|
+
const missionArg = positional.shift();
|
|
74
|
+
const libraryNameOrId = positional.join(' ').trim();
|
|
75
|
+
if (!missionArg || !libraryNameOrId) throw new Error('Usage: sks context7 evidence <mission-id|latest> <library-name|/org/project> [--query "..."] [--topic "..."] [--tokens N] [--json]');
|
|
76
|
+
const missionId = await resolveMissionId(root, missionArg);
|
|
77
|
+
if (!missionId) throw new Error('No mission found for Context7 evidence.');
|
|
78
|
+
const result = await context7Docs(libraryNameOrId, {
|
|
79
|
+
query: readOption(args, '--query', readOption(args, '--topic', libraryNameOrId)),
|
|
80
|
+
topic: readOption(args, '--topic', libraryNameOrId),
|
|
81
|
+
tokens: readNumberOption(args, '--tokens', 2000),
|
|
82
|
+
timeoutMs: readNumberOption(args, '--timeout-ms', 30000)
|
|
83
|
+
});
|
|
84
|
+
const state = { ...(await readJson(stateFile(root), {})), mission_id: missionId };
|
|
85
|
+
await recordContext7Evidence(root, state, { tool_name: 'resolve-library-id', library: libraryNameOrId, library_id: result.library_id, source: result.resolve ? 'sks context7 evidence' : 'sks context7 evidence explicit-library-id' });
|
|
86
|
+
if (result.docs_tool) {
|
|
87
|
+
await recordContext7Evidence(root, state, { tool_name: result.docs_tool, library_id: result.library_id, source: 'sks context7 evidence' });
|
|
88
|
+
}
|
|
89
|
+
const evidence = await context7Evidence(root, state);
|
|
90
|
+
const out = { ...result, mission_id: missionId, evidence };
|
|
91
|
+
if (flag(args, '--json')) return console.log(JSON.stringify(out, null, 2));
|
|
92
|
+
printContext7DocsResult(result, { title: 'SKS Context7 Evidence' });
|
|
93
|
+
console.log(`\nMission: ${missionId}`);
|
|
94
|
+
console.log(`Evidence: ${evidence.ok ? 'ok' : 'missing'} resolve=${evidence.resolve ? 'yes' : 'no'} docs=${evidence.docs ? 'yes' : 'no'} events=${evidence.count}`);
|
|
95
|
+
if (!result.ok || !evidence.ok) process.exitCode = 1;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (action === 'setup') {
|
|
99
|
+
const scope = setupScope;
|
|
100
|
+
const transport = readOption(args, '--transport', flag(args, '--remote') ? 'remote' : 'local');
|
|
101
|
+
if (!['project', 'global'].includes(scope)) throw new Error('Invalid Context7 scope. Use project or global.');
|
|
102
|
+
if (!['local', 'remote'].includes(transport)) throw new Error('Invalid Context7 transport. Use local or remote.');
|
|
103
|
+
if (scope === 'project') {
|
|
104
|
+
const changed = await ensureProjectContext7Config(root, transport);
|
|
105
|
+
const result = await checkContext7(root);
|
|
106
|
+
if (flag(args, '--json')) return console.log(JSON.stringify({ changed, ...result }, null, 2));
|
|
107
|
+
console.log(`Context7 project MCP ${changed ? 'configured' : 'already configured'} in .codex/config.toml`);
|
|
108
|
+
console.log(`Ready: ${result.ok ? 'yes' : 'no'}`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const codex = await getCodexInfo();
|
|
112
|
+
if (!codex.bin) throw new Error('Codex CLI missing. Install separately: npm i -g @openai/codex, or set SKS_CODEX_BIN.');
|
|
113
|
+
const cmdArgs = transport === 'remote'
|
|
114
|
+
? ['mcp', 'add', 'context7', '--url', 'https://mcp.context7.com/mcp']
|
|
115
|
+
: ['mcp', 'add', 'context7', '--', 'npx', '-y', '@upstash/context7-mcp@latest'];
|
|
116
|
+
const result = await runProcess(codex.bin, cmdArgs, { timeoutMs: 30000, maxOutputBytes: 64 * 1024 });
|
|
117
|
+
if (flag(args, '--json')) return console.log(JSON.stringify({ command: `${codex.bin} ${cmdArgs.join(' ')}`, result }, null, 2));
|
|
118
|
+
if (result.code !== 0) throw new Error(result.stderr || result.stdout || 'codex mcp add failed');
|
|
119
|
+
console.log('Context7 global MCP configured.');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
throw new Error(`Unknown context7 command: ${action}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function printContext7DocsResult(result, opts = {}) {
|
|
126
|
+
console.log(`${opts.title || 'SKS Context7 Docs'}\n`);
|
|
127
|
+
console.log(`Library ID: ${result.library_id || 'not resolved'}`);
|
|
128
|
+
console.log(`Docs tool: ${result.docs_tool || 'missing'}`);
|
|
129
|
+
console.log(`Server: ${result.server?.info?.name || 'context7'} ${result.server?.info?.version || ''}`.trim());
|
|
130
|
+
const text = context7Text(result.docs).split(/\n/).slice(0, 48).join('\n').trim();
|
|
131
|
+
if (text) console.log(`\n${text}`);
|
|
132
|
+
if (result.error) console.log(`\nError: ${result.error}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function readOption(args, name, fallback) {
|
|
136
|
+
const i = args.indexOf(name);
|
|
137
|
+
return i >= 0 && args[i + 1] ? args[i + 1] : fallback;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function readNumberOption(args, name, fallback) {
|
|
141
|
+
const raw = readOption(args, name, null);
|
|
142
|
+
if (raw == null) return fallback;
|
|
143
|
+
const n = Number(raw);
|
|
144
|
+
return Number.isFinite(n) ? n : fallback;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function positionalArgs(args = []) {
|
|
148
|
+
const out = [];
|
|
149
|
+
for (let i = 0; i < args.length; i++) {
|
|
150
|
+
const arg = args[i];
|
|
151
|
+
if (String(arg).startsWith('--')) {
|
|
152
|
+
if (args[i + 1] && !String(args[i + 1]).startsWith('--')) i++;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
out.push(arg);
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function resolveMissionId(root, arg) {
|
|
161
|
+
const { findLatestMission } = await import('../core/mission.mjs');
|
|
162
|
+
return (!arg || arg === 'latest') ? findLatestMission(root) : arg;
|
|
163
|
+
}
|