sneakoscope 0.5.0 → 0.6.0
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 +236 -7
- package/docs/PERFORMANCE.md +1 -1
- package/package.json +12 -4
- package/src/cli/main.mjs +530 -11
- package/src/core/fsx.mjs +1 -1
- package/src/core/hooks-runtime.mjs +34 -1
- package/src/core/init.mjs +146 -21
package/README.md
CHANGED
|
@@ -10,11 +10,187 @@ Sneakoscope Codex is a zero-runtime-dependency Node.js harness for running Codex
|
|
|
10
10
|
npm i -g sneakoscope
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The npm package name is `sneakoscope`; the command is branded as SKS and exposed as lowercase `sks` for shell portability.
|
|
14
|
-
Global installation is the default and recommended setup. For a project-only install, use `npm i -D sneakoscope` and initialize hooks with `npx sks
|
|
13
|
+
The npm package name is `sneakoscope`; the command is branded as SKS and exposed as lowercase `sks` for shell portability. The package also exposes a `sneakoscope` command alias, so `sks setup` and `sneakoscope setup` are equivalent.
|
|
14
|
+
Global installation is the default and recommended setup. During `sks setup` or `sks init`, SKS resolves the global binary when possible and writes that absolute path into `.codex/hooks.json`, which avoids PATH issues in GUI or hook execution environments. For a project-only install, use `npm i -D sneakoscope` and initialize hooks with `npx sks setup --install-scope project`; this writes hook commands that call the local `node_modules/sneakoscope` binary.
|
|
15
15
|
|
|
16
16
|
`@openai/codex` is intentionally not bundled. Install Codex separately, or set `SKS_CODEX_BIN` to the Codex executable you want Sneakoscope Codex to supervise.
|
|
17
17
|
|
|
18
|
+
## One-Prompt LLM Install
|
|
19
|
+
|
|
20
|
+
If you are using Codex App, ChatGPT, Claude Code, Cursor, or another coding agent, copy this prompt into the agent from your target project directory:
|
|
21
|
+
|
|
22
|
+
````text
|
|
23
|
+
You are installing Sneakoscope Codex in the current project. Do the setup end to end without asking follow-up questions unless a command needs user approval.
|
|
24
|
+
|
|
25
|
+
Repository:
|
|
26
|
+
https://github.com/mandarange/Sneakoscope-Codex.git
|
|
27
|
+
|
|
28
|
+
Requirements:
|
|
29
|
+
- Node.js must be >=20.11.
|
|
30
|
+
- Codex CLI is installed separately; if missing, report that @openai/codex must be installed or SKS_CODEX_BIN must be set.
|
|
31
|
+
- Prefer safe, local verification. Do not modify application source files unless needed for SKS setup.
|
|
32
|
+
|
|
33
|
+
Run:
|
|
34
|
+
```bash
|
|
35
|
+
npm i -g git+https://github.com/mandarange/Sneakoscope-Codex.git
|
|
36
|
+
sks setup
|
|
37
|
+
sks doctor --fix
|
|
38
|
+
sks selftest --mock
|
|
39
|
+
sks commands
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
If the global command is not on PATH, use:
|
|
43
|
+
```bash
|
|
44
|
+
npx -y -p git+https://github.com/mandarange/Sneakoscope-Codex.git sks setup
|
|
45
|
+
npx -y -p git+https://github.com/mandarange/Sneakoscope-Codex.git sks doctor --fix
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
After setup, explain these outputs to the user:
|
|
49
|
+
- `.sneakoscope/` mission state and policy
|
|
50
|
+
- `.codex/config.toml` Codex App profiles
|
|
51
|
+
- `.codex/hooks.json` SKS hook integration
|
|
52
|
+
- `.codex/skills/` local Codex App skills
|
|
53
|
+
- `.codex/SNEAKOSCOPE.md` Codex App quick reference
|
|
54
|
+
- `AGENTS.md` repository rules
|
|
55
|
+
|
|
56
|
+
Show the user how to discover commands:
|
|
57
|
+
```bash
|
|
58
|
+
sks help
|
|
59
|
+
sks commands
|
|
60
|
+
sks usage ralph
|
|
61
|
+
sks quickstart
|
|
62
|
+
sks codex-app
|
|
63
|
+
sks dollar-commands
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Tell the user they can use these prompt commands inside Codex App:
|
|
67
|
+
```text
|
|
68
|
+
$DF 글자 색 바꿔줘
|
|
69
|
+
$DF 내용을 영어로 바꿔줘
|
|
70
|
+
$SKS show me available workflows
|
|
71
|
+
$Ralph implement this with mandatory clarification
|
|
72
|
+
$Research investigate this idea
|
|
73
|
+
$DB check this migration safely
|
|
74
|
+
```
|
|
75
|
+
````
|
|
76
|
+
|
|
77
|
+
After SKS is installed, you can print this prompt again from the CLI:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
sks install-prompt
|
|
81
|
+
sks install-prompt --project
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Repository
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm i -g git+https://github.com/mandarange/Sneakoscope-Codex.git
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Source repository: <https://github.com/mandarange/Sneakoscope-Codex.git>
|
|
91
|
+
|
|
92
|
+
Local development checkout:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
git clone https://github.com/mandarange/Sneakoscope-Codex.git
|
|
96
|
+
cd Sneakoscope-Codex
|
|
97
|
+
npm i
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Installed Commands
|
|
101
|
+
|
|
102
|
+
Installing the package exposes two equivalent shell commands:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
sks <command>
|
|
106
|
+
sneakoscope <command>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Use `sks --help` or `sneakoscope --help` to inspect the installed CLI. The user-facing subcommands are listed in [Commands](#commands).
|
|
110
|
+
|
|
111
|
+
Useful discovery commands:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
sks commands
|
|
115
|
+
sks usage install
|
|
116
|
+
sks usage ralph
|
|
117
|
+
sks quickstart
|
|
118
|
+
sks install-prompt
|
|
119
|
+
sks codex-app
|
|
120
|
+
sks dollar-commands
|
|
121
|
+
sks df
|
|
122
|
+
sks aliases
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Prompt Pipeline and $ Commands
|
|
126
|
+
|
|
127
|
+
SKS installs a Codex App `UserPromptSubmit` hook that adds a lightweight prompt-optimization context to every user request. You do not need to type a command for basic routing: SKS will infer the lightest path before work starts.
|
|
128
|
+
|
|
129
|
+
Use `$` prompt commands inside Codex App or another coding agent when you want to force a route:
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
$DF fast design/content fix
|
|
133
|
+
$SKS general Sneakoscope workflow/help
|
|
134
|
+
$Ralph clarification-gated Ralph mission
|
|
135
|
+
$Research frontier research mission
|
|
136
|
+
$DB database/Supabase safety check
|
|
137
|
+
$GX deterministic visual context
|
|
138
|
+
$Help command and workflow help
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`$DF` is intentionally small and fast. Use it for changes like text color, visible copy, labels, spacing, button text, or translation:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
$DF 글자 색 파란색으로 바꿔줘
|
|
145
|
+
$DF 내용을 영어로 바꿔줘
|
|
146
|
+
$DF Change the CTA label to "Start"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
DF should not start Ralph, Research, evaluation, or a broad redesign unless you explicitly ask for that.
|
|
150
|
+
|
|
151
|
+
## Codex App
|
|
152
|
+
|
|
153
|
+
Sneakoscope Codex can also be used from Codex App when the repository is opened in the app. Run setup once in the project:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
sks setup
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
This creates the app-facing control surface:
|
|
160
|
+
|
|
161
|
+
```text
|
|
162
|
+
.codex/config.toml Codex App profiles for SKS Ralph, research, and default work
|
|
163
|
+
.codex/hooks.json Codex App hook entrypoints routed through SKS guards
|
|
164
|
+
.codex/skills/ local project skills for Ralph, DB safety, GX, research, and design work
|
|
165
|
+
.codex/SNEAKOSCOPE.md quick reference for using SKS inside Codex App
|
|
166
|
+
AGENTS.md repository rules loaded by Codex agents
|
|
167
|
+
.sneakoscope/ mission state, gates, logs, policy, GX cartridges, and reports
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Inside Codex App, you can ask the agent to use the local SKS control surface, for example:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
$DF 글자 색 바꿔줘
|
|
174
|
+
$DF 내용을 영어로 바꿔줘
|
|
175
|
+
Use Sneakoscope Ralph mode to prepare this task.
|
|
176
|
+
Run the latest Ralph mission with the sealed decision contract.
|
|
177
|
+
Use SKS DB safety before touching database or Supabase files.
|
|
178
|
+
Use SKS research mode for this investigation.
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
If Codex App cannot find `sks` from hooks, run:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
sks fix-path
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
For a project-only install, use:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
npm i -D sneakoscope
|
|
191
|
+
npx sks setup --install-scope project
|
|
192
|
+
```
|
|
193
|
+
|
|
18
194
|
## Requirements
|
|
19
195
|
|
|
20
196
|
- Node.js `>=20.11`
|
|
@@ -25,8 +201,7 @@ Global installation is the default and recommended setup. For a project-only ins
|
|
|
25
201
|
## Quick Start
|
|
26
202
|
|
|
27
203
|
```bash
|
|
28
|
-
sks
|
|
29
|
-
sks init
|
|
204
|
+
sks setup
|
|
30
205
|
sks selftest --mock
|
|
31
206
|
```
|
|
32
207
|
|
|
@@ -34,8 +209,19 @@ Project-only setup:
|
|
|
34
209
|
|
|
35
210
|
```bash
|
|
36
211
|
npm i -D sneakoscope
|
|
37
|
-
npx sks
|
|
38
|
-
|
|
212
|
+
npx sks setup --install-scope project
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
If a GUI hook, Codex session, or another project cannot find `sks`, refresh the hook command with the resolved binary path:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
sks fix-path
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
If your shell cannot find the global command yet, run through npm without relying on PATH:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
npx -y -p sneakoscope sks setup
|
|
39
225
|
```
|
|
40
226
|
|
|
41
227
|
Create a Ralph mission:
|
|
@@ -73,6 +259,8 @@ sks research run latest --max-cycles 3
|
|
|
73
259
|
- **Sealed decision contract**: `ralph answer` validates answers and writes `decision-contract.json`.
|
|
74
260
|
- **No-question Ralph loop**: after `ralph run` starts, Ralph must resolve ambiguity with the sealed contract instead of asking the user.
|
|
75
261
|
- **Research mode**: `research` runs a frontier-discovery loop for non-obvious hypotheses, falsification, novelty ledgers, and testable experiments.
|
|
262
|
+
- **Prompt pipeline and `$` routes**: user prompts are lightly optimized by default, and Codex App users can force routes such as `$DF`, `$Ralph`, `$Research`, `$DB`, and `$GX`.
|
|
263
|
+
- **Fast DF mode**: `$DF` handles small design/content edits like color, copy, labels, spacing, and translation without unnecessary Ralph, Research, or evaluation loops.
|
|
76
264
|
- **Database guard**: destructive DB operations, production writes, unsafe Supabase MCP configuration, and direct live SQL mutations are blocked or warned on.
|
|
77
265
|
- **H-Proof done gate**: completion requires supported critical claims, reviewed DB safety state, acceptable visual/wiki drift, and required test evidence.
|
|
78
266
|
- **Performance evaluation**: `sks eval` produces deterministic token, accuracy-proxy, recall, support, and runtime metrics for before/after evidence.
|
|
@@ -110,7 +298,24 @@ Core invariants:
|
|
|
110
298
|
|
|
111
299
|
## Commands
|
|
112
300
|
|
|
301
|
+
All examples below use `sks`, but the same commands can be run with the `sneakoscope` alias.
|
|
302
|
+
|
|
113
303
|
```bash
|
|
304
|
+
sks help [topic]
|
|
305
|
+
sks commands [--json]
|
|
306
|
+
sks usage [install|setup|ralph|research|db|codex-app|df|dollar|eval|gx]
|
|
307
|
+
sks quickstart
|
|
308
|
+
sks install-prompt [--project]
|
|
309
|
+
sks codex-app
|
|
310
|
+
sks dollar-commands [--json]
|
|
311
|
+
sks df
|
|
312
|
+
sks aliases
|
|
313
|
+
|
|
314
|
+
sks --help
|
|
315
|
+
sneakoscope --help
|
|
316
|
+
|
|
317
|
+
sks setup [--install-scope global|project] [--force] [--json]
|
|
318
|
+
sks fix-path [--install-scope global|project] [--json]
|
|
114
319
|
sks doctor [--fix] [--json] [--install-scope global|project]
|
|
115
320
|
sks init [--force] [--install-scope global|project]
|
|
116
321
|
sks selftest [--mock]
|
|
@@ -138,6 +343,7 @@ sks eval compare --baseline old.json --candidate new.json [--json]
|
|
|
138
343
|
sks eval thresholds
|
|
139
344
|
|
|
140
345
|
sks hproof check [mission-id|latest]
|
|
346
|
+
sks team "task"
|
|
141
347
|
sks gx init [name]
|
|
142
348
|
sks gx render [name] [--format svg|html|all]
|
|
143
349
|
sks gx validate [name]
|
|
@@ -146,6 +352,7 @@ sks gx snapshot [name]
|
|
|
146
352
|
sks profile show
|
|
147
353
|
sks profile set <model>
|
|
148
354
|
sks gc [--dry-run] [--json]
|
|
355
|
+
sks memory [--dry-run] [--json]
|
|
149
356
|
sks stats [--json]
|
|
150
357
|
```
|
|
151
358
|
|
|
@@ -272,6 +479,8 @@ sks hproof check latest
|
|
|
272
479
|
.sneakoscope/ mission state, policy, retention, logs, GX cartridges
|
|
273
480
|
.codex/config.toml Codex profiles used by Sneakoscope Codex
|
|
274
481
|
.codex/hooks.json hook entrypoints
|
|
482
|
+
.codex/skills/ Codex App local project skills
|
|
483
|
+
.codex/SNEAKOSCOPE.md Codex App quick reference
|
|
275
484
|
.agents/skills/ Sneakoscope Codex helper skills
|
|
276
485
|
AGENTS.md managed repository rules block
|
|
277
486
|
```
|
|
@@ -279,7 +488,7 @@ AGENTS.md managed repository rules block
|
|
|
279
488
|
Install scope controls `.codex/hooks.json`:
|
|
280
489
|
|
|
281
490
|
```text
|
|
282
|
-
global -> sks hook ...
|
|
491
|
+
global -> /absolute/path/to/sks hook ... when resolvable, otherwise sks hook ...
|
|
283
492
|
project -> node ./node_modules/sneakoscope/bin/sks.mjs hook ...
|
|
284
493
|
```
|
|
285
494
|
|
|
@@ -362,12 +571,32 @@ The published npm package is allowlisted to `bin`, `src`, `docs`, `README.md`, a
|
|
|
362
571
|
## Development
|
|
363
572
|
|
|
364
573
|
```bash
|
|
574
|
+
npm run repo-audit
|
|
365
575
|
npm run packcheck
|
|
366
576
|
npm run selftest
|
|
367
577
|
npm run sizecheck
|
|
368
578
|
npm run doctor
|
|
369
579
|
```
|
|
370
580
|
|
|
581
|
+
`npm run repo-audit` checks tracked files for risky local paths and high-confidence secret material such as private keys, npm/GitHub/OpenAI-style tokens, local MCP configs, DB dumps, and credential files. It is included in `prepack` and `prepublishOnly`.
|
|
582
|
+
|
|
371
583
|
`npm run sizecheck` blocks accidental package bloat before `npm pack` or `npm publish`. Defaults: packed tarball `<=96 KiB`, unpacked package `<=320 KiB`, package files `<=40`, and each tracked file `<=256 KiB`. Override only for an intentional release with `SKS_MAX_PACK_BYTES`, `SKS_MAX_UNPACKED_BYTES`, `SKS_MAX_PACK_FILES`, or `SKS_MAX_TRACKED_FILE_BYTES`.
|
|
372
584
|
|
|
373
585
|
`npm run selftest` uses the mock path and does not call a model. Live Ralph runs require a working Codex CLI installation and authentication.
|
|
586
|
+
|
|
587
|
+
## Publishing
|
|
588
|
+
|
|
589
|
+
The npm package is published as public package `sneakoscope`. You must be logged in as an npm owner for that package before publishing.
|
|
590
|
+
|
|
591
|
+
```bash
|
|
592
|
+
npm whoami
|
|
593
|
+
npm owner ls sneakoscope
|
|
594
|
+
npm run publish:dry
|
|
595
|
+
npm run publish:npm
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
If `npm whoami` returns `E401 Unauthorized`, run `npm login` with an owner account or ask an existing owner to add your npm username:
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
npm owner add <your-npm-username> sneakoscope
|
|
602
|
+
```
|
package/docs/PERFORMANCE.md
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "Sneakoscope Codex",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"description": "Sneakoscope Codex: database-safe, performance-bounded Codex CLI harness with Ralph no-question loop, H-Proof gates, deterministic GX visual context, and TriWiki compression.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"sks": "bin/sks.mjs"
|
|
8
|
+
"sks": "bin/sks.mjs",
|
|
9
|
+
"sneakoscope": "bin/sks.mjs"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public",
|
|
13
|
+
"registry": "https://registry.npmjs.org/"
|
|
9
14
|
},
|
|
10
15
|
"files": [
|
|
11
16
|
"bin",
|
|
@@ -18,12 +23,15 @@
|
|
|
18
23
|
"node": ">=20.11"
|
|
19
24
|
},
|
|
20
25
|
"scripts": {
|
|
26
|
+
"repo-audit": "node ./scripts/repo-audit.mjs",
|
|
21
27
|
"selftest": "node ./bin/sks.mjs selftest --mock",
|
|
22
28
|
"doctor": "node ./bin/sks.mjs doctor",
|
|
23
29
|
"packcheck": "find bin src scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check",
|
|
24
30
|
"sizecheck": "node ./scripts/sizecheck.mjs",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
31
|
+
"publish:dry": "npm --cache /tmp/sks-npm-cache pack --dry-run",
|
|
32
|
+
"publish:npm": "npm --cache /tmp/sks-npm-cache publish --access public",
|
|
33
|
+
"prepack": "npm run repo-audit && npm run packcheck && npm run selftest && npm run sizecheck",
|
|
34
|
+
"prepublishOnly": "npm run repo-audit && npm run packcheck && npm run selftest && npm run sizecheck"
|
|
27
35
|
},
|
|
28
36
|
"keywords": [
|
|
29
37
|
"sneakoscope",
|
package/src/cli/main.mjs
CHANGED
|
@@ -18,6 +18,46 @@ import { buildResearchPrompt, evaluateResearchGate, writeMockResearchResult, wri
|
|
|
18
18
|
|
|
19
19
|
const flag = (args, name) => args.includes(name);
|
|
20
20
|
const promptOf = (args) => args.filter((x) => !String(x).startsWith('--')).join(' ').trim();
|
|
21
|
+
const REPOSITORY_URL = 'https://github.com/mandarange/Sneakoscope-Codex.git';
|
|
22
|
+
const USAGE_TOPICS = 'install|setup|ralph|research|db|codex-app|df|dollar|eval|gx';
|
|
23
|
+
|
|
24
|
+
const DOLLAR_COMMANDS = [
|
|
25
|
+
{ command: '$DF', route: 'fast design/content fix', description: 'Small UI/content edits such as text color, copy, label, spacing, or translation. Avoids heavy loops.' },
|
|
26
|
+
{ command: '$SKS', route: 'general SKS workflow', description: 'General Sneakoscope setup, help, status, and workflow routing.' },
|
|
27
|
+
{ command: '$Ralph', route: 'Ralph mission', description: 'Mandatory clarification and no-question autonomous mission workflow.' },
|
|
28
|
+
{ command: '$Research', route: 'research mission', description: 'Frontier discovery, hypotheses, falsification, and testable predictions.' },
|
|
29
|
+
{ command: '$DB', route: 'database safety', description: 'Database, Supabase, migration, SQL, or MCP safety checks.' },
|
|
30
|
+
{ command: '$GX', route: 'visual context', description: 'Deterministic GX visual context cartridges.' },
|
|
31
|
+
{ command: '$Help', route: 'command help', description: 'Explain installed SKS commands and workflows.' }
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const COMMAND_CATALOG = [
|
|
35
|
+
{ name: 'help', usage: 'sks help [topic]', description: 'Show CLI help or focused help for a topic.' },
|
|
36
|
+
{ name: 'commands', usage: 'sks commands [--json]', description: 'List every user-facing command with a short description.' },
|
|
37
|
+
{ name: 'usage', usage: `sks usage [${USAGE_TOPICS}]`, description: 'Print copy-ready workflows for common tasks.' },
|
|
38
|
+
{ name: 'quickstart', usage: 'sks quickstart', description: 'Show the shortest safe setup and verification flow.' },
|
|
39
|
+
{ name: 'install-prompt', usage: 'sks install-prompt [--project]', description: 'Print an LLM-ready prompt that installs and configures SKS automatically.' },
|
|
40
|
+
{ name: 'codex-app', usage: 'sks codex-app', description: 'Show Codex App setup files and example prompts.' },
|
|
41
|
+
{ name: 'dollar-commands', usage: 'sks dollar-commands [--json]', description: 'List Codex App $ commands such as $DF.' },
|
|
42
|
+
{ name: 'df', usage: 'sks df', description: 'Explain $DF fast design/content fix mode.' },
|
|
43
|
+
{ name: 'aliases', usage: 'sks aliases', description: 'Show command aliases and npm binary names.' },
|
|
44
|
+
{ name: 'setup', usage: 'sks setup [--install-scope global|project] [--force] [--json]', description: 'Initialize SKS state, Codex App files, hooks, skills, and rules.' },
|
|
45
|
+
{ name: 'fix-path', usage: 'sks fix-path [--install-scope global|project] [--json]', description: 'Refresh hook commands with the resolved SKS binary path.' },
|
|
46
|
+
{ name: 'doctor', usage: 'sks doctor [--fix] [--json] [--install-scope global|project]', description: 'Check Node, Codex CLI, install scope, hooks, skills, DB guard, and Codex App files.' },
|
|
47
|
+
{ name: 'init', usage: 'sks init [--force] [--install-scope global|project]', description: 'Initialize the local SKS control surface.' },
|
|
48
|
+
{ name: 'selftest', usage: 'sks selftest [--mock]', description: 'Run local smoke tests without calling a model.' },
|
|
49
|
+
{ name: 'ralph', usage: 'sks ralph prepare|answer|run|status ...', description: 'Run mandatory-clarification Ralph missions with a no-question execution loop.' },
|
|
50
|
+
{ name: 'research', usage: 'sks research prepare|run|status ...', description: 'Run frontier-style research missions with novelty and falsification gates.' },
|
|
51
|
+
{ name: 'db', usage: 'sks db policy|scan|mcp-config|classify|check ...', description: 'Inspect and enforce database/Supabase safety policy.' },
|
|
52
|
+
{ name: 'eval', usage: 'sks eval run|compare|thresholds ...', description: 'Run deterministic context-quality and performance evidence checks.' },
|
|
53
|
+
{ name: 'hproof', usage: 'sks hproof check [mission-id|latest]', description: 'Evaluate the H-Proof done gate for a mission.' },
|
|
54
|
+
{ name: 'team', usage: 'sks team "task"', description: 'Create a clarification-gated team mission.' },
|
|
55
|
+
{ name: 'gx', usage: 'sks gx init|render|validate|drift|snapshot [name]', description: 'Create and verify deterministic SVG/HTML visual context cartridges.' },
|
|
56
|
+
{ name: 'profile', usage: 'sks profile show|set <model>', description: 'Inspect or set the current SKS model profile metadata.' },
|
|
57
|
+
{ name: 'gc', usage: 'sks gc [--dry-run] [--json]', description: 'Compact oversized logs and prune stale runtime artifacts.' },
|
|
58
|
+
{ name: 'memory', usage: 'sks memory [--dry-run] [--json]', description: 'Alias for SKS garbage collection and retention handling.' },
|
|
59
|
+
{ name: 'stats', usage: 'sks stats [--json]', description: 'Show package and .sneakoscope storage size.' }
|
|
60
|
+
];
|
|
21
61
|
|
|
22
62
|
function installScopeFromArgs(args = [], fallback = 'global') {
|
|
23
63
|
if (flag(args, '--project')) return 'project';
|
|
@@ -29,7 +69,18 @@ function installScopeFromArgs(args = [], fallback = 'global') {
|
|
|
29
69
|
export async function main(args) {
|
|
30
70
|
const [cmd, sub, ...rest] = args;
|
|
31
71
|
const tail = sub === undefined ? [] : [sub, ...rest];
|
|
32
|
-
if (!cmd || cmd === '
|
|
72
|
+
if (!cmd || cmd === '--help' || cmd === '-h') return help();
|
|
73
|
+
if (cmd === 'help') return help(tail);
|
|
74
|
+
if (cmd === 'commands') return commands(tail);
|
|
75
|
+
if (cmd === 'usage') return usage(tail);
|
|
76
|
+
if (cmd === 'quickstart') return quickstart();
|
|
77
|
+
if (cmd === 'install-prompt') return installPrompt(tail);
|
|
78
|
+
if (cmd === 'codex-app') return codexAppHelp();
|
|
79
|
+
if (cmd === 'dollar-commands' || cmd === 'dollars' || cmd === '$') return dollarCommands(tail);
|
|
80
|
+
if (String(cmd).toLowerCase() === 'df') return dfHelp();
|
|
81
|
+
if (cmd === 'aliases') return aliases();
|
|
82
|
+
if (cmd === 'setup') return setup(tail);
|
|
83
|
+
if (cmd === 'fix-path') return fixPath(tail);
|
|
33
84
|
if (cmd === 'doctor') return doctor(tail);
|
|
34
85
|
if (cmd === 'init') return init(tail);
|
|
35
86
|
if (cmd === 'selftest') return selftest(tail);
|
|
@@ -49,10 +100,23 @@ export async function main(args) {
|
|
|
49
100
|
process.exitCode = 1;
|
|
50
101
|
}
|
|
51
102
|
|
|
52
|
-
function help() {
|
|
103
|
+
function help(args = []) {
|
|
104
|
+
const topic = args[0];
|
|
105
|
+
if (topic) return usage([topic]);
|
|
53
106
|
console.log(`Sneakoscope Codex
|
|
54
107
|
|
|
55
108
|
Usage:
|
|
109
|
+
sks help [topic]
|
|
110
|
+
sks commands [--json]
|
|
111
|
+
sks usage [${USAGE_TOPICS}]
|
|
112
|
+
sks quickstart
|
|
113
|
+
sks install-prompt [--project]
|
|
114
|
+
sks codex-app
|
|
115
|
+
sks dollar-commands [--json]
|
|
116
|
+
sks df
|
|
117
|
+
sks aliases
|
|
118
|
+
sks setup [--install-scope global|project] [--force] [--json]
|
|
119
|
+
sks fix-path [--install-scope global|project] [--json]
|
|
56
120
|
sks doctor [--fix] [--json] [--install-scope global|project]
|
|
57
121
|
sks init [--install-scope global|project]
|
|
58
122
|
sks selftest [--mock]
|
|
@@ -75,17 +139,441 @@ Usage:
|
|
|
75
139
|
sks gx validate [name]
|
|
76
140
|
sks gx drift [name]
|
|
77
141
|
sks gx snapshot [name]
|
|
142
|
+
sks profile show
|
|
143
|
+
sks profile set <model>
|
|
78
144
|
sks gc [--dry-run] [--json]
|
|
145
|
+
sks memory [--dry-run] [--json]
|
|
79
146
|
sks stats [--json]
|
|
147
|
+
|
|
148
|
+
Discovery:
|
|
149
|
+
sks commands Full command list with descriptions
|
|
150
|
+
sks usage ralph Workflow examples for one topic
|
|
151
|
+
sks install-prompt Copy/paste prompt for an LLM installer
|
|
152
|
+
sks dollar-commands Codex App $ commands, including $DF
|
|
80
153
|
`);
|
|
81
154
|
}
|
|
82
155
|
|
|
156
|
+
function commands(args = []) {
|
|
157
|
+
if (flag(args, '--json')) return console.log(JSON.stringify({ aliases: ['sks', 'sneakoscope'], dollar_commands: DOLLAR_COMMANDS, commands: COMMAND_CATALOG }, null, 2));
|
|
158
|
+
console.log('Sneakoscope Codex Commands\n');
|
|
159
|
+
console.log('Aliases: sks, sneakoscope\n');
|
|
160
|
+
const width = Math.max(...COMMAND_CATALOG.map((c) => c.usage.length));
|
|
161
|
+
for (const c of COMMAND_CATALOG) console.log(`${c.usage.padEnd(width)} ${c.description}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function dollarCommands(args = []) {
|
|
165
|
+
if (flag(args, '--json')) return console.log(JSON.stringify({ dollar_commands: DOLLAR_COMMANDS }, null, 2));
|
|
166
|
+
console.log('Sneakoscope Codex $ Commands\n');
|
|
167
|
+
console.log('Use these inside Codex App or another agent prompt. Shells treat $ as variable syntax, so these are prompt commands, not terminal commands.\n');
|
|
168
|
+
const width = Math.max(...DOLLAR_COMMANDS.map((c) => c.command.length));
|
|
169
|
+
for (const c of DOLLAR_COMMANDS) console.log(`${c.command.padEnd(width)} ${c.route}: ${c.description}`);
|
|
170
|
+
console.log('\nDefault pipeline: even without a $ command, SKS optimizes the prompt and infers the lightest route. Simple design/content edits infer $DF.');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function dfHelp() {
|
|
174
|
+
console.log(`SKS DF Mode
|
|
175
|
+
|
|
176
|
+
Prompt command:
|
|
177
|
+
$DF <small design/content request>
|
|
178
|
+
|
|
179
|
+
Examples:
|
|
180
|
+
$DF 글자 색 파란색으로 바꿔줘
|
|
181
|
+
$DF 내용을 영어로 바꿔줘
|
|
182
|
+
$DF Change the CTA label to "Start"
|
|
183
|
+
|
|
184
|
+
Purpose:
|
|
185
|
+
Fast design/content fixes only. DF should prompt-engineer the user's request into the smallest implementation change.
|
|
186
|
+
|
|
187
|
+
Rules:
|
|
188
|
+
Do not run Ralph, Research, eval, or broad redesign.
|
|
189
|
+
Inspect only what is needed, edit only what is requested, and run cheap verification when useful.
|
|
190
|
+
`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function quickstart() {
|
|
194
|
+
console.log(`Sneakoscope Codex Quickstart
|
|
195
|
+
|
|
196
|
+
Install from npm:
|
|
197
|
+
npm i -g sneakoscope
|
|
198
|
+
|
|
199
|
+
Install from GitHub:
|
|
200
|
+
npm i -g git+${REPOSITORY_URL}
|
|
201
|
+
|
|
202
|
+
Initialize this project for CLI and Codex App:
|
|
203
|
+
sks setup
|
|
204
|
+
|
|
205
|
+
Verify:
|
|
206
|
+
sks doctor --fix
|
|
207
|
+
sks selftest --mock
|
|
208
|
+
sks commands
|
|
209
|
+
|
|
210
|
+
If hooks cannot find the command:
|
|
211
|
+
sks fix-path
|
|
212
|
+
|
|
213
|
+
Project-only install:
|
|
214
|
+
npm i -D sneakoscope
|
|
215
|
+
npx sks setup --install-scope project
|
|
216
|
+
`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function installPrompt(args = []) {
|
|
220
|
+
const projectOnly = flag(args, '--project');
|
|
221
|
+
const install = projectOnly
|
|
222
|
+
? `npm i -D git+${REPOSITORY_URL}\nnpx sks setup --install-scope project`
|
|
223
|
+
: `npm i -g git+${REPOSITORY_URL}\nsks setup`;
|
|
224
|
+
console.log(`Copy this prompt into an LLM coding assistant:
|
|
225
|
+
|
|
226
|
+
You are installing Sneakoscope Codex in the current project. Do the setup end to end without asking follow-up questions unless a command needs user approval.
|
|
227
|
+
|
|
228
|
+
Repository:
|
|
229
|
+
${REPOSITORY_URL}
|
|
230
|
+
|
|
231
|
+
Requirements:
|
|
232
|
+
- Node.js must be >=20.11.
|
|
233
|
+
- Codex CLI is installed separately; if missing, report that @openai/codex must be installed or SKS_CODEX_BIN must be set.
|
|
234
|
+
- Prefer safe, local verification. Do not modify application source files unless needed for SKS setup.
|
|
235
|
+
|
|
236
|
+
Run:
|
|
237
|
+
\`\`\`bash
|
|
238
|
+
${install}
|
|
239
|
+
${projectOnly ? 'npx sks doctor --fix --install-scope project\nnpx sks selftest --mock\nnpx sks commands' : 'sks doctor --fix\nsks selftest --mock\nsks commands'}
|
|
240
|
+
\`\`\`
|
|
241
|
+
|
|
242
|
+
If the global command is not on PATH, use:
|
|
243
|
+
\`\`\`bash
|
|
244
|
+
npx -y -p git+${REPOSITORY_URL} sks setup
|
|
245
|
+
npx -y -p git+${REPOSITORY_URL} sks doctor --fix
|
|
246
|
+
\`\`\`
|
|
247
|
+
|
|
248
|
+
After setup, explain these outputs to the user:
|
|
249
|
+
- \`.sneakoscope/\` mission state and policy
|
|
250
|
+
- \`.codex/config.toml\` Codex App profiles
|
|
251
|
+
- \`.codex/hooks.json\` SKS hook integration
|
|
252
|
+
- \`.codex/skills/\` local Codex App skills
|
|
253
|
+
- \`.codex/SNEAKOSCOPE.md\` Codex App quick reference
|
|
254
|
+
- \`AGENTS.md\` repository rules
|
|
255
|
+
|
|
256
|
+
Show the user how to discover commands:
|
|
257
|
+
\`\`\`bash
|
|
258
|
+
sks help
|
|
259
|
+
sks commands
|
|
260
|
+
sks usage ralph
|
|
261
|
+
sks quickstart
|
|
262
|
+
sks codex-app
|
|
263
|
+
sks dollar-commands
|
|
264
|
+
\`\`\`
|
|
265
|
+
|
|
266
|
+
Tell the user they can use these prompt commands inside Codex App:
|
|
267
|
+
\`\`\`text
|
|
268
|
+
$DF 글자 색 바꿔줘
|
|
269
|
+
$DF 내용을 영어로 바꿔줘
|
|
270
|
+
$Ralph implement this with mandatory clarification
|
|
271
|
+
$Research investigate this idea
|
|
272
|
+
$DB check this migration safely
|
|
273
|
+
\`\`\`
|
|
274
|
+
`);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function codexAppHelp() {
|
|
278
|
+
console.log(`Sneakoscope Codex App Usage
|
|
279
|
+
|
|
280
|
+
Run once in the project:
|
|
281
|
+
sks setup
|
|
282
|
+
|
|
283
|
+
Generated app files:
|
|
284
|
+
.codex/config.toml profiles for SKS Ralph, research, and default work
|
|
285
|
+
.codex/hooks.json hook events routed through SKS guards
|
|
286
|
+
.codex/skills/ local project skills
|
|
287
|
+
.codex/SNEAKOSCOPE.md app quick reference
|
|
288
|
+
AGENTS.md repository rules
|
|
289
|
+
|
|
290
|
+
Useful prompts inside Codex App:
|
|
291
|
+
$DF 글자 색 바꿔줘
|
|
292
|
+
$DF 내용을 영어로 바꿔줘
|
|
293
|
+
Use Sneakoscope Ralph mode to prepare this task.
|
|
294
|
+
Run the latest Ralph mission with the sealed decision contract.
|
|
295
|
+
Use SKS DB safety before touching database or Supabase files.
|
|
296
|
+
Use SKS research mode for this investigation.
|
|
297
|
+
|
|
298
|
+
Repair hook PATH issues:
|
|
299
|
+
sks fix-path
|
|
300
|
+
|
|
301
|
+
Discover usage:
|
|
302
|
+
sks commands
|
|
303
|
+
sks usage codex-app
|
|
304
|
+
sks dollar-commands
|
|
305
|
+
sks df
|
|
306
|
+
sks install-prompt
|
|
307
|
+
`);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function aliases() {
|
|
311
|
+
console.log(`Sneakoscope Codex Aliases
|
|
312
|
+
|
|
313
|
+
Binary aliases:
|
|
314
|
+
sks
|
|
315
|
+
sneakoscope
|
|
316
|
+
|
|
317
|
+
Command aliases:
|
|
318
|
+
sks memory -> sks gc
|
|
319
|
+
sks --help -> sks help
|
|
320
|
+
sks -h -> sks help
|
|
321
|
+
|
|
322
|
+
Codex App prompt commands:
|
|
323
|
+
$DF fast design/content fix
|
|
324
|
+
$SKS general Sneakoscope route
|
|
325
|
+
$Ralph Ralph mission route
|
|
326
|
+
$Research research mission route
|
|
327
|
+
$DB database safety route
|
|
328
|
+
$GX visual context route
|
|
329
|
+
$Help command help route
|
|
330
|
+
|
|
331
|
+
Examples:
|
|
332
|
+
sks setup
|
|
333
|
+
sneakoscope setup
|
|
334
|
+
sks commands
|
|
335
|
+
sneakoscope commands
|
|
336
|
+
`);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function usage(args = []) {
|
|
340
|
+
const topic = String(args[0] || 'overview').toLowerCase();
|
|
341
|
+
const blocks = {
|
|
342
|
+
overview: `Sneakoscope Codex Usage
|
|
343
|
+
|
|
344
|
+
Discovery:
|
|
345
|
+
sks help
|
|
346
|
+
sks commands
|
|
347
|
+
sks quickstart
|
|
348
|
+
sks install-prompt
|
|
349
|
+
sks codex-app
|
|
350
|
+
sks dollar-commands
|
|
351
|
+
|
|
352
|
+
Common workflows:
|
|
353
|
+
sks usage install
|
|
354
|
+
sks usage ralph
|
|
355
|
+
sks usage research
|
|
356
|
+
sks usage db
|
|
357
|
+
sks usage df
|
|
358
|
+
`,
|
|
359
|
+
install: `Install and Setup
|
|
360
|
+
|
|
361
|
+
Global install:
|
|
362
|
+
npm i -g sneakoscope
|
|
363
|
+
sks setup
|
|
364
|
+
sks doctor --fix
|
|
365
|
+
sks selftest --mock
|
|
366
|
+
|
|
367
|
+
GitHub install:
|
|
368
|
+
npm i -g git+${REPOSITORY_URL}
|
|
369
|
+
sks setup
|
|
370
|
+
|
|
371
|
+
Project-only install:
|
|
372
|
+
npm i -D sneakoscope
|
|
373
|
+
npx sks setup --install-scope project
|
|
374
|
+
|
|
375
|
+
LLM-assisted install:
|
|
376
|
+
sks install-prompt
|
|
377
|
+
`,
|
|
378
|
+
setup: `Setup Repair
|
|
379
|
+
|
|
380
|
+
Initialize:
|
|
381
|
+
sks setup
|
|
382
|
+
|
|
383
|
+
Refresh hook command paths:
|
|
384
|
+
sks fix-path
|
|
385
|
+
|
|
386
|
+
Inspect readiness:
|
|
387
|
+
sks doctor
|
|
388
|
+
sks doctor --fix
|
|
389
|
+
sks doctor --json
|
|
390
|
+
`,
|
|
391
|
+
ralph: `Ralph Workflow
|
|
392
|
+
|
|
393
|
+
Prepare:
|
|
394
|
+
sks ralph prepare "task"
|
|
395
|
+
|
|
396
|
+
Answer generated slots:
|
|
397
|
+
cat .sneakoscope/missions/<MISSION_ID>/questions.md
|
|
398
|
+
cp .sneakoscope/missions/<MISSION_ID>/required-answers.schema.json answers.json
|
|
399
|
+
sks ralph answer <MISSION_ID> answers.json
|
|
400
|
+
|
|
401
|
+
Run:
|
|
402
|
+
sks ralph run <MISSION_ID> --max-cycles 8
|
|
403
|
+
sks ralph status latest
|
|
404
|
+
|
|
405
|
+
Local smoke run:
|
|
406
|
+
sks ralph run latest --mock
|
|
407
|
+
`,
|
|
408
|
+
research: `Research Workflow
|
|
409
|
+
|
|
410
|
+
Prepare:
|
|
411
|
+
sks research prepare "topic" --depth frontier
|
|
412
|
+
|
|
413
|
+
Run:
|
|
414
|
+
sks research run latest --max-cycles 3
|
|
415
|
+
|
|
416
|
+
Inspect:
|
|
417
|
+
sks research status latest
|
|
418
|
+
`,
|
|
419
|
+
db: `Database Safety
|
|
420
|
+
|
|
421
|
+
Policy:
|
|
422
|
+
sks db policy
|
|
423
|
+
|
|
424
|
+
Scan project config:
|
|
425
|
+
sks db scan --migrations
|
|
426
|
+
|
|
427
|
+
Generate safe Supabase MCP config:
|
|
428
|
+
sks db mcp-config --project-ref <ref> --features database,docs
|
|
429
|
+
|
|
430
|
+
Classify/check operations:
|
|
431
|
+
sks db classify --sql "DROP TABLE users"
|
|
432
|
+
sks db check --command "supabase db reset"
|
|
433
|
+
sks db check --file ./migration.sql
|
|
434
|
+
`,
|
|
435
|
+
'codex-app': `Codex App
|
|
436
|
+
|
|
437
|
+
Initialize app files:
|
|
438
|
+
sks setup
|
|
439
|
+
|
|
440
|
+
Inspect app guidance:
|
|
441
|
+
sks codex-app
|
|
442
|
+
sks dollar-commands
|
|
443
|
+
cat .codex/SNEAKOSCOPE.md
|
|
444
|
+
|
|
445
|
+
Use inside Codex App:
|
|
446
|
+
$DF 글자 색 바꿔줘
|
|
447
|
+
$DF 내용을 영어로 바꿔줘
|
|
448
|
+
Use Sneakoscope Ralph mode to prepare this task.
|
|
449
|
+
Use SKS DB safety before touching database or Supabase files.
|
|
450
|
+
`,
|
|
451
|
+
df: `DF Fast Design/Content Fix
|
|
452
|
+
|
|
453
|
+
Use inside Codex App:
|
|
454
|
+
$DF 글자 색 파란색으로 바꿔줘
|
|
455
|
+
$DF 내용을 영어로 바꿔줘
|
|
456
|
+
$DF Change the button label to "Start"
|
|
457
|
+
|
|
458
|
+
Behavior:
|
|
459
|
+
Prompt-engineer the request into the smallest design/content edit.
|
|
460
|
+
Do not start Ralph, Research, eval, or a broad redesign.
|
|
461
|
+
Inspect only relevant files and run only cheap verification when useful.
|
|
462
|
+
|
|
463
|
+
CLI help:
|
|
464
|
+
sks df
|
|
465
|
+
`,
|
|
466
|
+
dollar: `Dollar Commands
|
|
467
|
+
|
|
468
|
+
Use inside Codex App or an agent prompt:
|
|
469
|
+
$DF fast design/content fix
|
|
470
|
+
$SKS general Sneakoscope route
|
|
471
|
+
$Ralph Ralph mission route
|
|
472
|
+
$Research research mission route
|
|
473
|
+
$DB database safety route
|
|
474
|
+
$GX visual context route
|
|
475
|
+
$Help command help route
|
|
476
|
+
|
|
477
|
+
Terminal discovery:
|
|
478
|
+
sks dollar-commands
|
|
479
|
+
sks dollar-commands --json
|
|
480
|
+
`,
|
|
481
|
+
eval: `Evaluation
|
|
482
|
+
|
|
483
|
+
Run benchmark:
|
|
484
|
+
sks eval run
|
|
485
|
+
sks eval run --json --out report.json
|
|
486
|
+
|
|
487
|
+
Compare reports:
|
|
488
|
+
sks eval compare --baseline old.json --candidate new.json
|
|
489
|
+
|
|
490
|
+
Show thresholds:
|
|
491
|
+
sks eval thresholds
|
|
492
|
+
`,
|
|
493
|
+
gx: `GX Visual Context
|
|
494
|
+
|
|
495
|
+
Create:
|
|
496
|
+
sks gx init architecture-atlas
|
|
497
|
+
|
|
498
|
+
Render and verify:
|
|
499
|
+
sks gx render architecture-atlas --format all
|
|
500
|
+
sks gx validate architecture-atlas
|
|
501
|
+
sks gx drift architecture-atlas
|
|
502
|
+
sks gx snapshot architecture-atlas
|
|
503
|
+
`
|
|
504
|
+
};
|
|
505
|
+
const text = blocks[topic] || blocks.overview;
|
|
506
|
+
console.log(text);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
async function setup(args) {
|
|
510
|
+
const root = await projectRoot();
|
|
511
|
+
const installScope = installScopeFromArgs(args);
|
|
512
|
+
const globalCommand = await globalSksCommand();
|
|
513
|
+
const res = await initProject(root, { force: flag(args, '--force'), installScope, globalCommand });
|
|
514
|
+
const install = await installStatus(root, installScope, { globalCommand });
|
|
515
|
+
const hooksPath = path.join(root, '.codex', 'hooks.json');
|
|
516
|
+
const result = {
|
|
517
|
+
root,
|
|
518
|
+
install,
|
|
519
|
+
hooks: hooksPath,
|
|
520
|
+
codex_app: {
|
|
521
|
+
config: path.join(root, '.codex', 'config.toml'),
|
|
522
|
+
hooks: hooksPath,
|
|
523
|
+
skills: path.join(root, '.codex', 'skills'),
|
|
524
|
+
quick_reference: path.join(root, '.codex', 'SNEAKOSCOPE.md'),
|
|
525
|
+
agents_rules: path.join(root, 'AGENTS.md')
|
|
526
|
+
},
|
|
527
|
+
created: res.created,
|
|
528
|
+
next: ['sks selftest --mock', 'sks doctor', 'sks commands']
|
|
529
|
+
};
|
|
530
|
+
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
531
|
+
console.log('Sneakoscope Codex Setup\n');
|
|
532
|
+
console.log(`Project: ${root}`);
|
|
533
|
+
console.log(`Install: ${install.ok ? 'ok' : 'missing'} ${install.scope} (${install.command_prefix})`);
|
|
534
|
+
console.log(`Hooks: ${path.relative(root, hooksPath)}`);
|
|
535
|
+
console.log(`Codex App: .codex/config.toml, .codex/hooks.json, .codex/skills, .codex/SNEAKOSCOPE.md`);
|
|
536
|
+
console.log(`Prompt: default optimization pipeline, $DF fast design/content route`);
|
|
537
|
+
console.log(`Skills: .codex/skills, .agents/skills`);
|
|
538
|
+
console.log(`Next: sks selftest --mock; sks commands; sks dollar-commands`);
|
|
539
|
+
if (!install.ok && install.scope === 'global') console.log('\nGlobal command missing. Run: npm i -g sneakoscope');
|
|
540
|
+
if (!install.ok && install.scope === 'project') console.log('\nProject package missing. Run: npm i -D sneakoscope');
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
async function fixPath(args) {
|
|
544
|
+
const root = await projectRoot();
|
|
545
|
+
const manifest = await readJson(path.join(root, '.sneakoscope', 'manifest.json'), null);
|
|
546
|
+
const installScope = args.includes('--install-scope') || flag(args, '--project') || flag(args, '--global')
|
|
547
|
+
? installScopeFromArgs(args)
|
|
548
|
+
: normalizeInstallScope(manifest?.installation?.scope || 'global');
|
|
549
|
+
const globalCommand = await globalSksCommand();
|
|
550
|
+
await initProject(root, { installScope, globalCommand });
|
|
551
|
+
const install = await installStatus(root, installScope, { globalCommand });
|
|
552
|
+
const result = {
|
|
553
|
+
root,
|
|
554
|
+
install_scope: installScope,
|
|
555
|
+
hook_command_prefix: sksCommandPrefix(installScope, { globalCommand }),
|
|
556
|
+
hooks: path.join(root, '.codex', 'hooks.json'),
|
|
557
|
+
install
|
|
558
|
+
};
|
|
559
|
+
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
560
|
+
console.log('SKS hook path refreshed\n');
|
|
561
|
+
console.log(`Project: ${root}`);
|
|
562
|
+
console.log(`Install: ${install.ok ? 'ok' : 'missing'} ${install.scope} (${install.command_prefix})`);
|
|
563
|
+
console.log(`Hooks: .codex/hooks.json`);
|
|
564
|
+
if (!install.ok && install.scope === 'global') console.log('\nGlobal command missing. Run: npm i -g sneakoscope');
|
|
565
|
+
if (!install.ok && install.scope === 'project') console.log('\nProject package missing. Run: npm i -D sneakoscope');
|
|
566
|
+
}
|
|
567
|
+
|
|
83
568
|
async function doctor(args) {
|
|
84
569
|
const root = await projectRoot();
|
|
85
570
|
const requestedScope = args.includes('--install-scope') || flag(args, '--project') || flag(args, '--global')
|
|
86
571
|
? installScopeFromArgs(args)
|
|
87
572
|
: null;
|
|
88
|
-
if (flag(args, '--fix'))
|
|
573
|
+
if (flag(args, '--fix')) {
|
|
574
|
+
const fixScope = requestedScope || 'global';
|
|
575
|
+
await initProject(root, { installScope: fixScope, globalCommand: await globalSksCommand() });
|
|
576
|
+
}
|
|
89
577
|
const codex = await getCodexInfo();
|
|
90
578
|
const rust = await rustInfo();
|
|
91
579
|
const nodeOk = Number(process.versions.node.split('.')[0]) >= 20;
|
|
@@ -96,16 +584,27 @@ async function doctor(args) {
|
|
|
96
584
|
const install = await installStatus(root, installScope);
|
|
97
585
|
const dbPolicyExists = await exists(path.join(root, '.sneakoscope', 'db-safety.json'));
|
|
98
586
|
const dbScan = await scanDbSafety(root).catch((err) => ({ ok: false, findings: [{ id: 'db_safety_scan_failed', severity: 'high', reason: err.message }] }));
|
|
587
|
+
const codexApp = {
|
|
588
|
+
config: { ok: await exists(path.join(root, '.codex', 'config.toml')) },
|
|
589
|
+
hooks: { ok: await exists(path.join(root, '.codex', 'hooks.json')) },
|
|
590
|
+
skills: { ok: await exists(path.join(root, '.codex', 'skills')) },
|
|
591
|
+
quick_reference: { ok: await exists(path.join(root, '.codex', 'SNEAKOSCOPE.md')) },
|
|
592
|
+
agents_rules: { ok: await exists(path.join(root, 'AGENTS.md')) }
|
|
593
|
+
};
|
|
99
594
|
const result = {
|
|
100
595
|
node: { ok: nodeOk, version: process.version }, root, codex, rust,
|
|
101
596
|
install,
|
|
102
597
|
sneakoscope: { ok: await exists(path.join(root, '.sneakoscope')) },
|
|
103
598
|
db_guard: { ok: dbPolicyExists && dbScan.ok, policy: dbPolicyExists ? await loadDbSafetyPolicy(root) : null, scan: dbScan },
|
|
104
599
|
hooks: { ok: await exists(path.join(root, '.codex', 'hooks.json')) },
|
|
105
|
-
skills: { ok: await exists(path.join(root, '.agents', 'skills')) },
|
|
600
|
+
skills: { ok: (await exists(path.join(root, '.codex', 'skills'))) && (await exists(path.join(root, '.agents', 'skills'))) },
|
|
601
|
+
codex_app: {
|
|
602
|
+
...codexApp,
|
|
603
|
+
ok: codexApp.config.ok && codexApp.hooks.ok && codexApp.skills.ok && codexApp.quick_reference.ok && codexApp.agents_rules.ok
|
|
604
|
+
},
|
|
106
605
|
package: { bytes: pkgBytes, human: formatBytes(pkgBytes) }, storage
|
|
107
606
|
};
|
|
108
|
-
result.ready = nodeOk && Boolean(codex.bin) && install.ok && result.sneakoscope.ok && result.db_guard.ok;
|
|
607
|
+
result.ready = nodeOk && Boolean(codex.bin) && install.ok && result.sneakoscope.ok && result.db_guard.ok && result.codex_app.ok;
|
|
109
608
|
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
110
609
|
console.log('Sneakoscope Codex Doctor\n');
|
|
111
610
|
console.log(`Node: ${nodeOk ? 'ok' : 'fail'} ${process.version}`);
|
|
@@ -116,7 +615,8 @@ async function doctor(args) {
|
|
|
116
615
|
console.log(`State: ${result.sneakoscope.ok ? 'ok' : 'missing .sneakoscope'}`);
|
|
117
616
|
console.log(`DB Guard: ${result.db_guard.ok ? 'ok' : 'blocked'} ${dbScan.findings?.length || 0} finding(s)`);
|
|
118
617
|
console.log(`Hooks: ${result.hooks.ok ? 'ok' : 'missing .codex/hooks.json'}`);
|
|
119
|
-
console.log(`
|
|
618
|
+
console.log(`Codex App: ${result.codex_app.ok ? 'ok' : 'missing app files'} .codex/config.toml .codex/hooks.json .codex/skills .codex/SNEAKOSCOPE.md`);
|
|
619
|
+
console.log(`Skills: ${result.skills.ok ? 'ok' : 'missing .codex/skills or .agents/skills'}`);
|
|
120
620
|
console.log(`Package: ${result.package.human}`);
|
|
121
621
|
console.log(`Storage: ${storage.total_human || '0 B'}`);
|
|
122
622
|
console.log(`Ready: ${result.ready ? 'yes' : 'no'}`);
|
|
@@ -129,15 +629,22 @@ async function doctor(args) {
|
|
|
129
629
|
async function init(args) {
|
|
130
630
|
const root = await projectRoot();
|
|
131
631
|
const installScope = installScopeFromArgs(args);
|
|
132
|
-
const
|
|
632
|
+
const globalCommand = await globalSksCommand();
|
|
633
|
+
const res = await initProject(root, { force: flag(args, '--force'), installScope, globalCommand });
|
|
133
634
|
console.log(`Initialized Sneakoscope Codex in ${root}`);
|
|
134
|
-
console.log(`Install scope: ${installScope} (${sksCommandPrefix(installScope)})`);
|
|
635
|
+
console.log(`Install scope: ${installScope} (${sksCommandPrefix(installScope, { globalCommand })})`);
|
|
135
636
|
for (const x of res.created) console.log(`- ${x}`);
|
|
136
637
|
}
|
|
137
638
|
|
|
138
|
-
async function
|
|
139
|
-
|
|
140
|
-
|
|
639
|
+
async function globalSksCommand() {
|
|
640
|
+
return process.env.SKS_BIN || await which('sks').catch(() => null) || 'sks';
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
async function installStatus(root, scope, opts = {}) {
|
|
644
|
+
const discoveredGlobalBin = await which('sks').catch(() => null);
|
|
645
|
+
const configuredGlobalBin = process.env.SKS_BIN || (opts.globalCommand && opts.globalCommand !== 'sks' ? opts.globalCommand : null);
|
|
646
|
+
const globalBin = configuredGlobalBin || discoveredGlobalBin;
|
|
647
|
+
const commandPrefix = sksCommandPrefix(scope, { globalCommand: globalBin || undefined });
|
|
141
648
|
const projectBin = path.join(root, 'node_modules', 'sneakoscope', 'bin', 'sks.mjs');
|
|
142
649
|
const projectBinExists = await exists(projectBin);
|
|
143
650
|
return {
|
|
@@ -386,12 +893,24 @@ async function selftest() {
|
|
|
386
893
|
await initProject(tmp, {});
|
|
387
894
|
const defaultHooks = await readJson(path.join(tmp, '.codex', 'hooks.json'));
|
|
388
895
|
if (defaultHooks.hooks.PreToolUse[0].hooks[0].command !== 'sks hook pre-tool') throw new Error('selftest failed: global install hook command changed');
|
|
896
|
+
const absoluteHookTmp = tmpdir();
|
|
897
|
+
await initProject(absoluteHookTmp, { globalCommand: '/usr/local/bin/sks' });
|
|
898
|
+
const absoluteHooks = await readJson(path.join(absoluteHookTmp, '.codex', 'hooks.json'));
|
|
899
|
+
if (absoluteHooks.hooks.PreToolUse[0].hooks[0].command !== '/usr/local/bin/sks hook pre-tool') throw new Error('selftest failed: absolute global hook command missing');
|
|
389
900
|
const projectScopeTmp = tmpdir();
|
|
390
901
|
await initProject(projectScopeTmp, { installScope: 'project' });
|
|
391
902
|
const projectHooks = await readJson(path.join(projectScopeTmp, '.codex', 'hooks.json'));
|
|
392
903
|
if (projectHooks.hooks.PreToolUse[0].hooks[0].command !== 'node ./node_modules/sneakoscope/bin/sks.mjs hook pre-tool') throw new Error('selftest failed: project install hook command missing');
|
|
393
904
|
const researchSkillExists = await exists(path.join(tmp, '.agents', 'skills', 'research-discovery', 'SKILL.md'));
|
|
394
905
|
if (!researchSkillExists) throw new Error('selftest failed: research skill not installed');
|
|
906
|
+
const codexAppSkillExists = await exists(path.join(tmp, '.codex', 'skills', 'research-discovery', 'SKILL.md'));
|
|
907
|
+
if (!codexAppSkillExists) throw new Error('selftest failed: Codex App skill not installed');
|
|
908
|
+
const dfSkillExists = await exists(path.join(tmp, '.codex', 'skills', 'DF', 'SKILL.md'));
|
|
909
|
+
if (!dfSkillExists) throw new Error('selftest failed: $DF skill not installed');
|
|
910
|
+
const promptPipelineSkillExists = await exists(path.join(tmp, '.codex', 'skills', 'prompt-pipeline', 'SKILL.md'));
|
|
911
|
+
if (!promptPipelineSkillExists) throw new Error('selftest failed: prompt pipeline skill not installed');
|
|
912
|
+
const codexAppQuickRefExists = await exists(path.join(tmp, '.codex', 'SNEAKOSCOPE.md'));
|
|
913
|
+
if (!codexAppQuickRefExists) throw new Error('selftest failed: Codex App quick reference missing');
|
|
395
914
|
const { id, dir, mission } = await createMission(tmp, { mode: 'ralph', prompt: '로그인 세션 만료 UX 개선 supabase db' });
|
|
396
915
|
const schema = buildQuestionSchema(mission.prompt);
|
|
397
916
|
await writeQuestions(dir, schema);
|
package/src/core/fsx.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
|
|
8
|
-
export const PACKAGE_VERSION = '0.
|
|
8
|
+
export const PACKAGE_VERSION = '0.6.0';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
|
|
@@ -22,10 +22,43 @@ function extractLastMessage(payload) {
|
|
|
22
22
|
return payload.last_assistant_message || payload.assistant_message || payload.message || payload.response || payload.raw || '';
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function extractUserPrompt(payload) {
|
|
26
|
+
return payload.prompt
|
|
27
|
+
|| payload.user_prompt
|
|
28
|
+
|| payload.userPrompt
|
|
29
|
+
|| payload.message
|
|
30
|
+
|| payload.input?.prompt
|
|
31
|
+
|| payload.input?.message
|
|
32
|
+
|| payload.raw
|
|
33
|
+
|| '';
|
|
34
|
+
}
|
|
35
|
+
|
|
25
36
|
function extractCommand(payload) {
|
|
26
37
|
return payload.command || payload.tool_input?.command || payload.input?.command || payload.tool?.input?.command || '';
|
|
27
38
|
}
|
|
28
39
|
|
|
40
|
+
function dollarCommand(prompt) {
|
|
41
|
+
const match = String(prompt || '').trim().match(/^\$([A-Za-z][A-Za-z0-9_-]*)(?:\s|:|$)/);
|
|
42
|
+
return match ? match[1].toUpperCase() : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function looksLikeFastDesignFix(prompt) {
|
|
46
|
+
const text = String(prompt || '');
|
|
47
|
+
const designCue = /(글자|텍스트|문구|내용|색|컬러|폰트|간격|여백|정렬|버튼|라벨|영어|한국어|번역|copy|text|color|font|spacing|padding|margin|align|label|button|translate)/i.test(text);
|
|
48
|
+
const changeCue = /(바꿔|변경|수정|교체|고쳐|영어로|한국어로|change|replace|update|make|turn|translate|fix)/i.test(text);
|
|
49
|
+
return designCue && changeCue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function promptPipelineContext(prompt) {
|
|
53
|
+
const command = dollarCommand(prompt);
|
|
54
|
+
const fastDesign = command === 'DF' || looksLikeFastDesignFix(prompt);
|
|
55
|
+
const route = command ? `$${command}` : (fastDesign ? '$DF inferred' : 'default');
|
|
56
|
+
const dfLine = fastDesign
|
|
57
|
+
? '\nFast design fix: treat this as $DF. Do the smallest relevant edit, avoid Ralph/research loops, avoid broad redesign, and run only cheap verification when useful.'
|
|
58
|
+
: '';
|
|
59
|
+
return `SKS prompt pipeline active. Route: ${route}. Optimize the user request before acting: extract intent, target files/surfaces, constraints, acceptance criteria, and the smallest safe execution path. Use explicit $ commands when present: $DF fast design/content edit, $Ralph clarification-gated mission, $Research discovery run, $DB database safety, $GX visual context, $SKS general SKS help. Without a command, infer the lightest matching route and avoid heavy loops unless the task requires them.${dfLine}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
29
62
|
export async function hookMain(name) {
|
|
30
63
|
const payload = await loadHookPayload();
|
|
31
64
|
const root = await projectRoot(payload.cwd || process.cwd());
|
|
@@ -40,7 +73,7 @@ export async function hookMain(name) {
|
|
|
40
73
|
}
|
|
41
74
|
|
|
42
75
|
async function hookUserPrompt(root, state, payload, noQuestion) {
|
|
43
|
-
if (!noQuestion) return { continue: true };
|
|
76
|
+
if (!noQuestion) return { continue: true, additionalContext: promptPipelineContext(extractUserPrompt(payload)) };
|
|
44
77
|
const id = state.mission_id;
|
|
45
78
|
if (id) await appendJsonl(path.join(missionDir(root, id), 'user_queue.jsonl'), { ts: nowIso(), payload });
|
|
46
79
|
return {
|
package/src/core/init.mjs
CHANGED
|
@@ -9,14 +9,14 @@ export function normalizeInstallScope(scope = 'global') {
|
|
|
9
9
|
throw new Error(`Invalid install scope: ${scope}. Use "global" or "project".`);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function sksCommandPrefix(scope = 'global') {
|
|
12
|
+
export function sksCommandPrefix(scope = 'global', opts = {}) {
|
|
13
13
|
return normalizeInstallScope(scope) === 'project'
|
|
14
14
|
? 'node ./node_modules/sneakoscope/bin/sks.mjs'
|
|
15
|
-
: 'sks';
|
|
15
|
+
: (opts.globalCommand || 'sks');
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function sksHookCommand(
|
|
19
|
-
return `${
|
|
18
|
+
function sksHookCommand(commandPrefix, hookName) {
|
|
19
|
+
return `${commandPrefix} hook ${hookName}`;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const AGENTS_BLOCK = `
|
|
@@ -44,6 +44,18 @@ When the user asks for research, new discoveries, hypothesis generation, frontie
|
|
|
44
44
|
|
|
45
45
|
When creating HTML, UI, prototype, deck-like, or visual artifacts, use the local design artifact skill. Gather design context first, build the actual usable experience rather than a marketing placeholder, expose variations when useful, and verify the rendered artifact before handoff.
|
|
46
46
|
|
|
47
|
+
## Prompt Optimization Pipeline
|
|
48
|
+
|
|
49
|
+
Every user prompt enters the SKS prompt optimization pipeline even when the user does not type a command. Extract intent, target files or surfaces, constraints, acceptance criteria, risks, and the smallest safe execution path before acting. Choose the lightest matching route: fast edit, normal implementation, Ralph, Research, DB safety, GX, or evaluation. Do not run heavy Ralph/research/evaluation loops for simple direct edits.
|
|
50
|
+
|
|
51
|
+
## Dollar Commands
|
|
52
|
+
|
|
53
|
+
Codex App users may invoke local SKS modes with skill-style dollar commands. \`$DF\` is the fast design/content fix route for small changes such as text color, copy edits, label changes, spacing tweaks, or translating visible text. \`$DF\` should avoid broad redesign, avoid unnecessary planning loops, and make the requested change directly with only cheap verification when useful.
|
|
54
|
+
|
|
55
|
+
## Codex App Usage
|
|
56
|
+
|
|
57
|
+
When this repository is opened in Codex App, use the local Sneakoscope files as the app control surface. Read \`.codex/SNEAKOSCOPE.md\` for the quick reference, load project skills from \`.codex/skills\` when applicable, and use the generated \`.codex/hooks.json\` hooks for DB safety, no-question Ralph runs, retention, and done-gate enforcement.
|
|
58
|
+
|
|
47
59
|
## Source Priority
|
|
48
60
|
|
|
49
61
|
1. Current code, tests, config
|
|
@@ -66,9 +78,10 @@ A task is not done until relevant tests are run or justified, unsupported critic
|
|
|
66
78
|
export async function initProject(root, opts = {}) {
|
|
67
79
|
const created = [];
|
|
68
80
|
const installScope = normalizeInstallScope(opts.installScope || 'global');
|
|
81
|
+
const hookCommandPrefix = opts.hookCommandPrefix || sksCommandPrefix(installScope, { globalCommand: opts.globalCommand });
|
|
69
82
|
const sine = path.join(root, '.sneakoscope');
|
|
70
83
|
const dirs = [
|
|
71
|
-
'.sneakoscope/state', '.sneakoscope/missions', '.sneakoscope/db', '.sneakoscope/bus', '.sneakoscope/hproof', '.sneakoscope/db', '.sneakoscope/memory/q0_raw', '.sneakoscope/memory/q1_evidence', '.sneakoscope/memory/q2_facts', '.sneakoscope/memory/q3_tags', '.sneakoscope/memory/q4_bits', '.sneakoscope/gx/cartridges', '.sneakoscope/model/fingerprints', '.sneakoscope/genome/candidates', '.sneakoscope/trajectories/raw', '.sneakoscope/locks', '.sneakoscope/tmp', '.sneakoscope/arenas', '.sneakoscope/reports', '.codex', '.agents/skills'
|
|
84
|
+
'.sneakoscope/state', '.sneakoscope/missions', '.sneakoscope/db', '.sneakoscope/bus', '.sneakoscope/hproof', '.sneakoscope/db', '.sneakoscope/memory/q0_raw', '.sneakoscope/memory/q1_evidence', '.sneakoscope/memory/q2_facts', '.sneakoscope/memory/q3_tags', '.sneakoscope/memory/q4_bits', '.sneakoscope/gx/cartridges', '.sneakoscope/model/fingerprints', '.sneakoscope/genome/candidates', '.sneakoscope/trajectories/raw', '.sneakoscope/locks', '.sneakoscope/tmp', '.sneakoscope/arenas', '.sneakoscope/reports', '.codex', '.codex/skills', '.agents/skills'
|
|
72
85
|
];
|
|
73
86
|
for (const d of dirs) await ensureDir(path.join(root, d));
|
|
74
87
|
|
|
@@ -78,13 +91,27 @@ export async function initProject(root, opts = {}) {
|
|
|
78
91
|
initialized_at: nowIso(),
|
|
79
92
|
no_external_tools: true,
|
|
80
93
|
codex_required: true,
|
|
94
|
+
codex_app_supported: true,
|
|
81
95
|
native_runtime_dependencies: 0,
|
|
82
96
|
installation: {
|
|
83
97
|
scope: installScope,
|
|
84
98
|
default_scope: 'global',
|
|
85
|
-
|
|
99
|
+
hook_command_prefix: hookCommandPrefix,
|
|
100
|
+
global_command: opts.globalCommand || 'sks',
|
|
86
101
|
project_command: 'node ./node_modules/sneakoscope/bin/sks.mjs'
|
|
87
102
|
},
|
|
103
|
+
codex_app: {
|
|
104
|
+
config: '.codex/config.toml',
|
|
105
|
+
hooks: '.codex/hooks.json',
|
|
106
|
+
skills: '.codex/skills',
|
|
107
|
+
quick_reference: '.codex/SNEAKOSCOPE.md',
|
|
108
|
+
agents_rules: 'AGENTS.md'
|
|
109
|
+
},
|
|
110
|
+
prompt_pipeline: {
|
|
111
|
+
default_enabled: true,
|
|
112
|
+
dollar_commands: ['$DF', '$SKS', '$Ralph', '$Research', '$DB', '$GX', '$Help'],
|
|
113
|
+
fast_design_command: '$DF'
|
|
114
|
+
},
|
|
88
115
|
database_safety: 'destructive_db_operations_denied_always',
|
|
89
116
|
gx_renderer: 'deterministic_svg_html'
|
|
90
117
|
});
|
|
@@ -98,20 +125,20 @@ export async function initProject(root, opts = {}) {
|
|
|
98
125
|
|
|
99
126
|
const policyPath = path.join(sine, 'policy.json');
|
|
100
127
|
if (!(await exists(policyPath)) || opts.force) {
|
|
101
|
-
await writeJsonAtomic(policyPath, defaultPolicy(installScope));
|
|
128
|
+
await writeJsonAtomic(policyPath, defaultPolicy(installScope, hookCommandPrefix));
|
|
102
129
|
created.push('.sneakoscope/policy.json');
|
|
103
130
|
} else {
|
|
104
131
|
const policy = await readJson(policyPath, {});
|
|
105
132
|
await writeJsonAtomic(policyPath, {
|
|
106
133
|
...policy,
|
|
107
|
-
installation: installPolicy(installScope)
|
|
134
|
+
installation: installPolicy(installScope, hookCommandPrefix)
|
|
108
135
|
});
|
|
109
136
|
}
|
|
110
137
|
|
|
111
|
-
function defaultPolicy(scope) {
|
|
138
|
+
function defaultPolicy(scope, commandPrefix) {
|
|
112
139
|
return {
|
|
113
140
|
schema_version: 1,
|
|
114
|
-
installation: installPolicy(scope),
|
|
141
|
+
installation: installPolicy(scope, commandPrefix),
|
|
115
142
|
retention: DEFAULT_RETENTION_POLICY,
|
|
116
143
|
database_safety: DEFAULT_DB_SAFETY_POLICY,
|
|
117
144
|
performance: {
|
|
@@ -140,17 +167,31 @@ export async function initProject(root, opts = {}) {
|
|
|
140
167
|
renderer: 'deterministic_svg_html',
|
|
141
168
|
source_of_truth: 'vgraph.json',
|
|
142
169
|
external_image_generation: false
|
|
170
|
+
},
|
|
171
|
+
codex_app: {
|
|
172
|
+
supported: true,
|
|
173
|
+
config: '.codex/config.toml',
|
|
174
|
+
hooks: '.codex/hooks.json',
|
|
175
|
+
skills: '.codex/skills',
|
|
176
|
+
quick_reference: '.codex/SNEAKOSCOPE.md',
|
|
177
|
+
agents_rules: 'AGENTS.md'
|
|
178
|
+
},
|
|
179
|
+
prompt_pipeline: {
|
|
180
|
+
default_enabled: true,
|
|
181
|
+
route_without_command: true,
|
|
182
|
+
dollar_commands: ['$DF', '$SKS', '$Ralph', '$Research', '$DB', '$GX', '$Help'],
|
|
183
|
+
fast_design_command: '$DF'
|
|
143
184
|
}
|
|
144
185
|
};
|
|
145
186
|
}
|
|
146
187
|
|
|
147
|
-
function installPolicy(scope) {
|
|
188
|
+
function installPolicy(scope, commandPrefix) {
|
|
148
189
|
return {
|
|
149
190
|
scope,
|
|
150
191
|
default_scope: 'global',
|
|
151
|
-
hook_command_prefix:
|
|
192
|
+
hook_command_prefix: commandPrefix,
|
|
152
193
|
global_install: 'npm i -g sneakoscope',
|
|
153
|
-
project_install: 'npm i -D sneakoscope && npx sks
|
|
194
|
+
project_install: 'npm i -D sneakoscope && npx sks setup --install-scope project'
|
|
154
195
|
};
|
|
155
196
|
}
|
|
156
197
|
|
|
@@ -166,24 +207,106 @@ export async function initProject(root, opts = {}) {
|
|
|
166
207
|
await writeTextAtomic(path.join(root, '.codex', 'config.toml'), `[features]\ncodex_hooks = true\n\n[profiles.sks-ralph]\nmodel = "gpt-5.5"\napproval_policy = "never"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-research]\nmodel = "gpt-5.5"\napproval_policy = "never"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "xhigh"\n\n[profiles.sks-default]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "medium"\n`);
|
|
167
208
|
created.push('.codex/config.toml');
|
|
168
209
|
|
|
210
|
+
await writeTextAtomic(path.join(root, '.codex', 'SNEAKOSCOPE.md'), codexAppQuickReference(installScope, hookCommandPrefix));
|
|
211
|
+
created.push('.codex/SNEAKOSCOPE.md');
|
|
212
|
+
|
|
169
213
|
await writeJsonAtomic(path.join(root, '.codex', 'hooks.json'), {
|
|
170
214
|
hooks: {
|
|
171
|
-
UserPromptSubmit: [{ hooks: [{ type: 'command', command: sksHookCommand(
|
|
172
|
-
PreToolUse: [{ matcher: '*', hooks: [{ type: 'command', command: sksHookCommand(
|
|
173
|
-
PostToolUse: [{ matcher: '*', hooks: [{ type: 'command', command: sksHookCommand(
|
|
174
|
-
PermissionRequest: [{ matcher: '*', hooks: [{ type: 'command', command: sksHookCommand(
|
|
175
|
-
Stop: [{ hooks: [{ type: 'command', command: sksHookCommand(
|
|
215
|
+
UserPromptSubmit: [{ hooks: [{ type: 'command', command: sksHookCommand(hookCommandPrefix, 'user-prompt-submit') }] }],
|
|
216
|
+
PreToolUse: [{ matcher: '*', hooks: [{ type: 'command', command: sksHookCommand(hookCommandPrefix, 'pre-tool') }] }],
|
|
217
|
+
PostToolUse: [{ matcher: '*', hooks: [{ type: 'command', command: sksHookCommand(hookCommandPrefix, 'post-tool') }] }],
|
|
218
|
+
PermissionRequest: [{ matcher: '*', hooks: [{ type: 'command', command: sksHookCommand(hookCommandPrefix, 'permission-request') }] }],
|
|
219
|
+
Stop: [{ hooks: [{ type: 'command', command: sksHookCommand(hookCommandPrefix, 'stop') }] }]
|
|
176
220
|
}
|
|
177
221
|
});
|
|
178
222
|
created.push(`.codex/hooks.json (${installScope})`);
|
|
179
223
|
|
|
180
224
|
await installSkills(root);
|
|
225
|
+
created.push('.codex/skills/*');
|
|
181
226
|
created.push('.agents/skills/*');
|
|
182
227
|
return { created };
|
|
183
228
|
}
|
|
184
229
|
|
|
230
|
+
function codexAppQuickReference(scope, commandPrefix) {
|
|
231
|
+
return `# Sneakoscope Codex for Codex App
|
|
232
|
+
|
|
233
|
+
This project has been initialized for both the SKS CLI and Codex App.
|
|
234
|
+
|
|
235
|
+
## App Control Surface
|
|
236
|
+
|
|
237
|
+
- Rules: \`AGENTS.md\`
|
|
238
|
+
- Hooks: \`.codex/hooks.json\`
|
|
239
|
+
- Profiles: \`.codex/config.toml\`
|
|
240
|
+
- App skills: \`.codex/skills/\`
|
|
241
|
+
- Mission state: \`.sneakoscope/missions/\`
|
|
242
|
+
- Current state: \`.sneakoscope/state/current.json\`
|
|
243
|
+
|
|
244
|
+
## Installed Command
|
|
245
|
+
|
|
246
|
+
\`\`\`bash
|
|
247
|
+
${commandPrefix} <command>
|
|
248
|
+
\`\`\`
|
|
249
|
+
|
|
250
|
+
Install scope: \`${scope}\`
|
|
251
|
+
|
|
252
|
+
## Discovery Commands
|
|
253
|
+
|
|
254
|
+
\`\`\`bash
|
|
255
|
+
${commandPrefix} help
|
|
256
|
+
${commandPrefix} commands
|
|
257
|
+
${commandPrefix} usage ralph
|
|
258
|
+
${commandPrefix} quickstart
|
|
259
|
+
${commandPrefix} install-prompt
|
|
260
|
+
${commandPrefix} codex-app
|
|
261
|
+
\`\`\`
|
|
262
|
+
|
|
263
|
+
## Dollar Commands
|
|
264
|
+
|
|
265
|
+
- \`$DF\`: fast design/content fix. Use for color, copy, label, spacing, translation, or small UI edits.
|
|
266
|
+
- \`$SKS\`: general Sneakoscope workflow/help route.
|
|
267
|
+
- \`$Ralph\`: clarification-gated autonomous mission route.
|
|
268
|
+
- \`$Research\`: frontier research route.
|
|
269
|
+
- \`$DB\`: database/Supabase safety route.
|
|
270
|
+
- \`$GX\`: deterministic visual context route.
|
|
271
|
+
- \`$Help\`: explain installed commands and workflows.
|
|
272
|
+
|
|
273
|
+
The prompt optimization pipeline also runs without a dollar command and infers the lightest route automatically.
|
|
274
|
+
|
|
275
|
+
## Common App Prompts
|
|
276
|
+
|
|
277
|
+
- "Use Sneakoscope Ralph mode to prepare this task."
|
|
278
|
+
- "$DF change the button text to English."
|
|
279
|
+
- "Run the latest Ralph mission with the sealed decision contract."
|
|
280
|
+
- "Use SKS DB safety before touching database or Supabase files."
|
|
281
|
+
- "Use SKS research mode for this investigation."
|
|
282
|
+
|
|
283
|
+
## CLI Bridge
|
|
284
|
+
|
|
285
|
+
Codex App can call the same project-local control surface through terminal commands:
|
|
286
|
+
|
|
287
|
+
\`\`\`bash
|
|
288
|
+
${commandPrefix} setup
|
|
289
|
+
${commandPrefix} doctor
|
|
290
|
+
${commandPrefix} ralph prepare "task"
|
|
291
|
+
${commandPrefix} ralph status latest
|
|
292
|
+
${commandPrefix} research prepare "topic"
|
|
293
|
+
${commandPrefix} db scan --migrations
|
|
294
|
+
\`\`\`
|
|
295
|
+
|
|
296
|
+
The hooks file routes Codex App tool events through SKS guards for no-question mode, DB safety, permission requests, and done-gate checks.
|
|
297
|
+
`;
|
|
298
|
+
}
|
|
299
|
+
|
|
185
300
|
async function installSkills(root) {
|
|
186
301
|
const skills = {
|
|
302
|
+
'DF': `---\nname: DF\ndescription: Fast design/content fix mode for $DF requests and inferred simple edits such as text color, copy, labels, spacing, or translation.\n---\n\nYou are running SKS DF mode.\n\nPurpose:\n- Quickly convert a small design/content request into the exact implementation change.\n- Use for requests like 글자 색 바꿔줘, 내용을 영어로 바꿔줘, button label 수정, spacing 조정, copy replacement, simple style tweaks.\n\nRules:\n- Do not start Ralph, Research, eval, or broad redesign unless the user explicitly asks.\n- Do not ask for more requirements when the target can be inferred from local context.\n- Inspect only the files needed to locate the target.\n- Make the smallest scoped edit that satisfies the request.\n- Preserve the existing design system and component patterns.\n- Run only cheap verification when useful, such as syntax check, focused test, or local render check for visual risk.\n- Final response should be short: what changed and any verification.\n`,
|
|
303
|
+
'SKS': `---\nname: SKS\ndescription: General Sneakoscope Codex command route for $SKS usage, setup, status, and workflow help.\n---\n\nUse the local SKS control surface. Prefer these discovery commands when the user asks what is available: sks commands, sks usage <topic>, sks quickstart, sks codex-app, sks install-prompt. If implementation is requested, route to the lightest matching SKS path.\n`,
|
|
304
|
+
'Ralph': `---\nname: Ralph\ndescription: Dollar-command route for SKS Ralph mandatory clarification and no-question mission workflows.\n---\n\nUse when the user invokes $Ralph or requests a clarification-gated autonomous implementation mission. Prepare with sks ralph prepare, answer/seal required slots when answers are provided, then run only after decision-contract.json exists.\n`,
|
|
305
|
+
'Research': `---\nname: Research\ndescription: Dollar-command route for SKS Research frontier discovery workflows.\n---\n\nUse when the user invokes $Research or asks for research, hypotheses, new mechanisms, falsification, or testable predictions. Prefer sks research prepare and sks research run. Do not use for ordinary code edits.\n`,
|
|
306
|
+
'DB': `---\nname: DB\ndescription: Dollar-command route for database and Supabase safety checks.\n---\n\nUse when the user invokes $DB or the task touches SQL, Supabase, Postgres, migrations, Prisma, Drizzle, Knex, MCP database tools, or production data. Run or follow sks db policy, sks db scan, sks db classify, and sks db check. Destructive database operations remain forbidden.\n`,
|
|
307
|
+
'GX': `---\nname: GX\ndescription: Dollar-command route for deterministic GX visual context cartridges.\n---\n\nUse when the user invokes $GX or asks for architecture/context visualization through SKS. Prefer sks gx init, render, validate, drift, and snapshot. vgraph.json remains the source of truth.\n`,
|
|
308
|
+
'Help': `---\nname: Help\ndescription: Dollar-command route for explaining installed SKS commands and workflows.\n---\n\nUse when the user invokes $Help or asks what commands exist. Prefer concise output from sks commands, sks usage <topic>, sks quickstart, sks aliases, and sks codex-app.\n`,
|
|
309
|
+
'prompt-pipeline': `---\nname: prompt-pipeline\ndescription: Default SKS prompt optimization pipeline that runs even without an explicit command.\n---\n\nFor every user request, silently extract intent, target surface, constraints, acceptance criteria, risk level, and the smallest safe route. Infer $DF for simple design/content edits. Use Ralph only for work that needs clarification gates, Research only for discovery work, DB only for database-risk work, GX only for visual context artifacts, and eval only when performance or context-quality claims need evidence.\n`,
|
|
187
310
|
'ralph-supervisor': `---\nname: ralph-supervisor\ndescription: Run the Ralph no-question loop after a decision contract is sealed.\n---\n\nYou are the Ralph Supervisor.\n\nRules:\n- Never ask the user during Ralph run.\n- Use decision-contract.json and the decision ladder.\n- Continue until done-gate.json passes or safe scope is completed with explicit limitation.\n- Keep outputs bounded. Write raw logs to files and summarize only tails.\n- Database destructive operations are never allowed.\n- Write progress to .sneakoscope mission files.\n`,
|
|
188
311
|
'ralph-resolver': `---\nname: ralph-resolver\ndescription: Resolve newly discovered ambiguity during Ralph using the sealed decision ladder, without asking the user.\n---\n\nResolve ambiguity in this order: seed contract, explicit answers, approved defaults, AGENTS.md, current code/tests, smallest reversible change, defer optional scope. Never ask the user. If database risk is involved, prefer read-only, no-op, local-only migration file, or safe limitation; never run destructive SQL.\n`,
|
|
189
312
|
'hproof-claim-ledger': `---\nname: hproof-claim-ledger\ndescription: Extract atomic claims and classify support status.\n---\n\nEvery factual statement must become an atomic claim. Unsupported critical claims cannot be used for implementation or final answer. Database claims require DB safety evidence.\n`,
|
|
@@ -198,8 +321,10 @@ async function installSkills(root) {
|
|
|
198
321
|
'design-artifact-expert': `---\nname: design-artifact-expert\ndescription: Create or revise high-fidelity HTML, UI, prototype, deck-like, or visual design artifacts using project design context, variations, and rendered verification.\n---\n\nUse when the user asks for design, UI, prototype, HTML artifact, landing page, deck-like visual work, interaction design, or visual refinement.\n\nWorkflow:\n1. Understand the artifact, audience, constraints, fidelity, variants, and existing brand/design system.\n2. Inspect local code, assets, screenshots, or design-system docs before inventing visuals. If context exists, follow its visual vocabulary.\n3. Build the actual usable screen or artifact first; avoid empty landing-page framing unless the task is explicitly marketing.\n4. Use descriptive HTML filenames. Keep large artifacts split into small support files when needed.\n5. For screens/slides, add data-screen-label attributes for comment context. Slide labels are 1-indexed.\n6. Preserve state for decks, videos, or multi-step prototypes with localStorage when refresh continuity matters.\n7. Expose a small Tweaks surface for useful variants such as layout, density, color, copy, or interaction options.\n8. Verify the artifact renders cleanly in a browser or preview. For design tasks, set done-gate.json design_verification_required/present fields and cite evidence.\n\nQuality bar:\n- Root design decisions in available assets and components.\n- Use restrained, domain-appropriate layout and typography.\n- Avoid text overlap, unreadable controls, decorative clutter, one-note palettes, and placeholder-only deliverables.\n- Prefer icons and familiar controls for tool actions, and make repeated UI dimensions stable.\n`
|
|
199
322
|
};
|
|
200
323
|
for (const [name, content] of Object.entries(skills)) {
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
324
|
+
for (const base of ['.codex/skills', '.agents/skills']) {
|
|
325
|
+
const dir = path.join(root, base, name);
|
|
326
|
+
await ensureDir(dir);
|
|
327
|
+
await writeTextAtomic(path.join(dir, 'SKILL.md'), `${content.trim()}\n`);
|
|
328
|
+
}
|
|
204
329
|
}
|
|
205
330
|
}
|