sneakoscope 0.6.6 → 0.6.7
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 +11 -3
- package/package.json +1 -1
- package/src/cli/main.mjs +36 -10
- package/src/core/fsx.mjs +1 -1
- package/src/core/init.mjs +54 -4
package/README.md
CHANGED
|
@@ -28,6 +28,14 @@ sks setup
|
|
|
28
28
|
sks doctor --fix
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
Use local-only setup when the generated SKS files must never appear in git status:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
sks setup --local-only
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This writes repo-local excludes to `.git/info/exclude` for `.sneakoscope/`, `.codex/`, `.agents/`, and `AGENTS.md`. If `AGENTS.md` already exists, local-only setup does not modify it.
|
|
38
|
+
|
|
31
39
|
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.
|
|
32
40
|
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.
|
|
33
41
|
|
|
@@ -378,10 +386,10 @@ sks aliases
|
|
|
378
386
|
sks --help
|
|
379
387
|
sneakoscope --help
|
|
380
388
|
|
|
381
|
-
sks setup [--install-scope global|project] [--force] [--json]
|
|
389
|
+
sks setup [--install-scope global|project] [--local-only] [--force] [--json]
|
|
382
390
|
sks fix-path [--install-scope global|project] [--json]
|
|
383
|
-
sks doctor [--fix] [--json] [--install-scope global|project]
|
|
384
|
-
sks init [--force] [--install-scope global|project]
|
|
391
|
+
sks doctor [--fix] [--local-only] [--json] [--install-scope global|project]
|
|
392
|
+
sks init [--force] [--local-only] [--install-scope global|project]
|
|
385
393
|
sks selftest [--mock]
|
|
386
394
|
|
|
387
395
|
sks ralph prepare "task"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "Sneakoscope Codex",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.7",
|
|
5
5
|
"description": "Sneakoscope Codex: update-aware, database-safe Codex CLI harness with multi-agent Team orchestration, Ralph no-question execution, autoresearch-style loops, and H-Proof gates.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
package/src/cli/main.mjs
CHANGED
|
@@ -50,10 +50,10 @@ const COMMAND_CATALOG = [
|
|
|
50
50
|
{ name: 'dollar-commands', usage: 'sks dollar-commands [--json]', description: 'List Codex App $ commands such as $DF.' },
|
|
51
51
|
{ name: 'df', usage: 'sks df', description: 'Explain $DF fast design/content fix mode.' },
|
|
52
52
|
{ name: 'aliases', usage: 'sks aliases', description: 'Show command aliases and npm binary names.' },
|
|
53
|
-
{ name: 'setup', usage: 'sks setup [--install-scope global|project] [--force] [--json]', description: 'Initialize SKS state, Codex App files, hooks, skills, and rules.' },
|
|
53
|
+
{ name: 'setup', usage: 'sks setup [--install-scope global|project] [--local-only] [--force] [--json]', description: 'Initialize SKS state, Codex App files, hooks, skills, and rules.' },
|
|
54
54
|
{ name: 'fix-path', usage: 'sks fix-path [--install-scope global|project] [--json]', description: 'Refresh hook commands with the resolved SKS binary path.' },
|
|
55
|
-
{ 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.' },
|
|
56
|
-
{ name: 'init', usage: 'sks init [--force] [--install-scope global|project]', description: 'Initialize the local SKS control surface.' },
|
|
55
|
+
{ name: 'doctor', usage: 'sks doctor [--fix] [--local-only] [--json] [--install-scope global|project]', description: 'Check Node, Codex CLI, install scope, hooks, skills, DB guard, and Codex App files.' },
|
|
56
|
+
{ name: 'init', usage: 'sks init [--force] [--local-only] [--install-scope global|project]', description: 'Initialize the local SKS control surface.' },
|
|
57
57
|
{ name: 'selftest', usage: 'sks selftest [--mock]', description: 'Run local smoke tests without calling a model.' },
|
|
58
58
|
{ name: 'ralph', usage: 'sks ralph prepare|answer|run|status ...', description: 'Run mandatory-clarification Ralph missions with a no-question execution loop.' },
|
|
59
59
|
{ name: 'research', usage: 'sks research prepare|run|status ...', description: 'Run frontier-style research missions with novelty and falsification gates.' },
|
|
@@ -134,10 +134,10 @@ Usage:
|
|
|
134
134
|
sks dollar-commands [--json]
|
|
135
135
|
sks df
|
|
136
136
|
sks aliases
|
|
137
|
-
sks setup [--install-scope global|project] [--force] [--json]
|
|
137
|
+
sks setup [--install-scope global|project] [--local-only] [--force] [--json]
|
|
138
138
|
sks fix-path [--install-scope global|project] [--json]
|
|
139
|
-
sks doctor [--fix] [--json] [--install-scope global|project]
|
|
140
|
-
sks init [--install-scope global|project]
|
|
139
|
+
sks doctor [--fix] [--local-only] [--json] [--install-scope global|project]
|
|
140
|
+
sks init [--install-scope global|project] [--local-only]
|
|
141
141
|
sks selftest [--mock]
|
|
142
142
|
sks ralph prepare "task"
|
|
143
143
|
sks ralph answer <mission-id|latest> <answers.json>
|
|
@@ -326,6 +326,11 @@ Project-only install:
|
|
|
326
326
|
npm i -D sneakoscope
|
|
327
327
|
npx sks setup --install-scope project
|
|
328
328
|
|
|
329
|
+
Local-only install artifacts:
|
|
330
|
+
sks setup --local-only
|
|
331
|
+
# writes generated SKS files but excludes .sneakoscope/, .codex/, .agents/, AGENTS.md through .git/info/exclude
|
|
332
|
+
# existing AGENTS.md is not modified in local-only mode
|
|
333
|
+
|
|
329
334
|
GitHub install for unreleased commits:
|
|
330
335
|
npm i -g git+${REPOSITORY_URL}
|
|
331
336
|
`);
|
|
@@ -563,6 +568,11 @@ Project-only install:
|
|
|
563
568
|
npm i -D sneakoscope
|
|
564
569
|
npx sks setup --install-scope project
|
|
565
570
|
|
|
571
|
+
Local-only install artifacts:
|
|
572
|
+
sks setup --local-only
|
|
573
|
+
# excludes .sneakoscope/, .codex/, .agents/, AGENTS.md through .git/info/exclude
|
|
574
|
+
# existing AGENTS.md is not modified in local-only mode
|
|
575
|
+
|
|
566
576
|
GitHub install for unreleased commits:
|
|
567
577
|
npm i -g git+${REPOSITORY_URL}
|
|
568
578
|
sks setup
|
|
@@ -750,8 +760,9 @@ Render and verify:
|
|
|
750
760
|
async function setup(args) {
|
|
751
761
|
const root = await projectRoot();
|
|
752
762
|
const installScope = installScopeFromArgs(args);
|
|
763
|
+
const localOnly = flag(args, '--local-only');
|
|
753
764
|
const globalCommand = await globalSksCommand();
|
|
754
|
-
const res = await initProject(root, { force: flag(args, '--force'), installScope, globalCommand });
|
|
765
|
+
const res = await initProject(root, { force: flag(args, '--force'), installScope, globalCommand, localOnly });
|
|
755
766
|
const install = await installStatus(root, installScope, { globalCommand });
|
|
756
767
|
const hooksPath = path.join(root, '.codex', 'hooks.json');
|
|
757
768
|
const result = {
|
|
@@ -767,6 +778,7 @@ async function setup(args) {
|
|
|
767
778
|
agents_rules: path.join(root, 'AGENTS.md')
|
|
768
779
|
},
|
|
769
780
|
created: res.created,
|
|
781
|
+
local_only: localOnly,
|
|
770
782
|
next: ['sks selftest --mock', 'sks doctor', 'sks commands']
|
|
771
783
|
};
|
|
772
784
|
if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
|
|
@@ -774,6 +786,7 @@ async function setup(args) {
|
|
|
774
786
|
console.log(`Project: ${root}`);
|
|
775
787
|
console.log(`Install: ${install.ok ? 'ok' : 'missing'} ${install.scope} (${install.command_prefix})`);
|
|
776
788
|
console.log(`Hooks: ${path.relative(root, hooksPath)}`);
|
|
789
|
+
if (localOnly) console.log('Git: local-only (.git/info/exclude; existing AGENTS.md not modified)');
|
|
777
790
|
console.log(`Codex App: .codex/config.toml, .codex/hooks.json, .codex/skills, .codex/agents, .codex/SNEAKOSCOPE.md`);
|
|
778
791
|
console.log(`Prompt: default optimization pipeline, $DF fast design/content route`);
|
|
779
792
|
console.log(`Skills: .codex/skills, .agents/skills`);
|
|
@@ -789,7 +802,7 @@ async function fixPath(args) {
|
|
|
789
802
|
? installScopeFromArgs(args)
|
|
790
803
|
: normalizeInstallScope(manifest?.installation?.scope || 'global');
|
|
791
804
|
const globalCommand = await globalSksCommand();
|
|
792
|
-
await initProject(root, { installScope, globalCommand });
|
|
805
|
+
await initProject(root, { installScope, globalCommand, localOnly: flag(args, '--local-only') || Boolean(manifest?.git?.local_only) });
|
|
793
806
|
const install = await installStatus(root, installScope, { globalCommand });
|
|
794
807
|
const result = {
|
|
795
808
|
root,
|
|
@@ -814,7 +827,8 @@ async function doctor(args) {
|
|
|
814
827
|
: null;
|
|
815
828
|
if (flag(args, '--fix')) {
|
|
816
829
|
const fixScope = requestedScope || 'global';
|
|
817
|
-
await
|
|
830
|
+
const existingManifest = await readJson(path.join(root, '.sneakoscope', 'manifest.json'), null);
|
|
831
|
+
await initProject(root, { installScope: fixScope, globalCommand: await globalSksCommand(), localOnly: flag(args, '--local-only') || Boolean(existingManifest?.git?.local_only) });
|
|
818
832
|
}
|
|
819
833
|
const codex = await getCodexInfo();
|
|
820
834
|
const rust = await rustInfo();
|
|
@@ -872,10 +886,12 @@ async function doctor(args) {
|
|
|
872
886
|
async function init(args) {
|
|
873
887
|
const root = await projectRoot();
|
|
874
888
|
const installScope = installScopeFromArgs(args);
|
|
889
|
+
const localOnly = flag(args, '--local-only');
|
|
875
890
|
const globalCommand = await globalSksCommand();
|
|
876
|
-
const res = await initProject(root, { force: flag(args, '--force'), installScope, globalCommand });
|
|
891
|
+
const res = await initProject(root, { force: flag(args, '--force'), installScope, globalCommand, localOnly });
|
|
877
892
|
console.log(`Initialized Sneakoscope Codex in ${root}`);
|
|
878
893
|
console.log(`Install scope: ${installScope} (${sksCommandPrefix(installScope, { globalCommand })})`);
|
|
894
|
+
if (localOnly) console.log('Git mode: local-only (.git/info/exclude)');
|
|
879
895
|
for (const x of res.created) console.log(`- ${x}`);
|
|
880
896
|
}
|
|
881
897
|
|
|
@@ -1207,6 +1223,16 @@ async function selftest() {
|
|
|
1207
1223
|
await initProject(projectScopeTmp, { installScope: 'project' });
|
|
1208
1224
|
const projectHooks = await readJson(path.join(projectScopeTmp, '.codex', 'hooks.json'));
|
|
1209
1225
|
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');
|
|
1226
|
+
const localOnlyTmp = tmpdir();
|
|
1227
|
+
await ensureDir(path.join(localOnlyTmp, '.git'));
|
|
1228
|
+
await writeTextAtomic(path.join(localOnlyTmp, 'AGENTS.md'), 'existing local rules\n');
|
|
1229
|
+
await initProject(localOnlyTmp, { localOnly: true });
|
|
1230
|
+
const localExclude = await safeReadText(path.join(localOnlyTmp, '.git', 'info', 'exclude'));
|
|
1231
|
+
if (!localExclude.includes('.codex/') || !localExclude.includes('AGENTS.md')) throw new Error('selftest failed: local-only git excludes missing');
|
|
1232
|
+
const localAgents = await safeReadText(path.join(localOnlyTmp, 'AGENTS.md'));
|
|
1233
|
+
if (localAgents.trim() !== 'existing local rules') throw new Error('selftest failed: local-only modified existing AGENTS.md');
|
|
1234
|
+
const localManifest = await readJson(path.join(localOnlyTmp, '.sneakoscope', 'manifest.json'));
|
|
1235
|
+
if (!localManifest.git?.local_only) throw new Error('selftest failed: local-only manifest missing');
|
|
1210
1236
|
if (!isTransientNpmBinPath('/tmp/.npm/_npx/abc/node_modules/.bin/sks')) throw new Error('selftest failed: npx bin path not recognized as transient');
|
|
1211
1237
|
if (!isTransientNpmBinPath('/tmp/.npm-cache/_cacache/tmp/git-cloneabc/bin/sks.mjs')) throw new Error('selftest failed: npm cache git clone path not recognized as transient');
|
|
1212
1238
|
if (isTransientNpmBinPath('/usr/local/bin/sks')) throw new Error('selftest failed: stable global bin marked transient');
|
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.6.
|
|
8
|
+
export const PACKAGE_VERSION = '0.6.7';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
|
package/src/core/init.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { ensureDir, readJson, writeJsonAtomic, writeTextAtomic, mergeManagedBlock, nowIso, PACKAGE_VERSION, exists } from './fsx.mjs';
|
|
2
|
+
import { ensureDir, readJson, readText, writeJsonAtomic, writeTextAtomic, mergeManagedBlock, nowIso, PACKAGE_VERSION, exists } from './fsx.mjs';
|
|
3
3
|
import { DEFAULT_RETENTION_POLICY } from './retention.mjs';
|
|
4
4
|
import { DEFAULT_DB_SAFETY_POLICY } from './db-safety.mjs';
|
|
5
5
|
|
|
@@ -98,12 +98,15 @@ A task is not done until relevant tests are run or justified, unsupported critic
|
|
|
98
98
|
export async function initProject(root, opts = {}) {
|
|
99
99
|
const created = [];
|
|
100
100
|
const installScope = normalizeInstallScope(opts.installScope || 'global');
|
|
101
|
+
const localOnly = Boolean(opts.localOnly);
|
|
101
102
|
const hookCommandPrefix = opts.hookCommandPrefix || sksCommandPrefix(installScope, { globalCommand: opts.globalCommand });
|
|
102
103
|
const sine = path.join(root, '.sneakoscope');
|
|
103
104
|
const dirs = [
|
|
104
105
|
'.sneakoscope/state', '.sneakoscope/missions', '.sneakoscope/db', '.sneakoscope/bus', '.sneakoscope/hproof', '.sneakoscope/db', '.sneakoscope/wiki', '.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', '.codex/agents', '.agents/skills'
|
|
105
106
|
];
|
|
106
107
|
for (const d of dirs) await ensureDir(path.join(root, d));
|
|
108
|
+
const localExclude = localOnly ? await ensureLocalOnlyGitExclude(root) : null;
|
|
109
|
+
if (localExclude?.path) created.push(`${path.relative(root, localExclude.path)} local-only excludes`);
|
|
107
110
|
|
|
108
111
|
await writeJsonAtomic(path.join(sine, 'manifest.json'), {
|
|
109
112
|
package: 'sneakoscope',
|
|
@@ -138,6 +141,11 @@ export async function initProject(root, opts = {}) {
|
|
|
138
141
|
channel_map: { r: 'domainAngle', g: 'layerRadius', b: 'phase', a: 'concentration' },
|
|
139
142
|
continuity_model: 'selected_text_plus_hydratable_rgba_trig_anchors'
|
|
140
143
|
},
|
|
144
|
+
git: {
|
|
145
|
+
local_only: localOnly,
|
|
146
|
+
exclude_path: localExclude?.path ? path.relative(root, localExclude.path) : null,
|
|
147
|
+
excluded_patterns: localExclude?.patterns || []
|
|
148
|
+
},
|
|
141
149
|
database_safety: 'destructive_db_operations_denied_always',
|
|
142
150
|
gx_renderer: 'deterministic_svg_html'
|
|
143
151
|
});
|
|
@@ -157,7 +165,13 @@ export async function initProject(root, opts = {}) {
|
|
|
157
165
|
const policy = await readJson(policyPath, {});
|
|
158
166
|
await writeJsonAtomic(policyPath, {
|
|
159
167
|
...policy,
|
|
160
|
-
installation: installPolicy(installScope, hookCommandPrefix)
|
|
168
|
+
installation: installPolicy(installScope, hookCommandPrefix),
|
|
169
|
+
git: {
|
|
170
|
+
...(policy.git || {}),
|
|
171
|
+
local_only: localOnly || Boolean(policy.git?.local_only),
|
|
172
|
+
exclude_path: localExclude?.path ? path.relative(root, localExclude.path) : policy.git?.exclude_path || null,
|
|
173
|
+
excluded_patterns: localExclude?.patterns || policy.git?.excluded_patterns || []
|
|
174
|
+
}
|
|
161
175
|
});
|
|
162
176
|
}
|
|
163
177
|
|
|
@@ -165,6 +179,11 @@ export async function initProject(root, opts = {}) {
|
|
|
165
179
|
return {
|
|
166
180
|
schema_version: 1,
|
|
167
181
|
installation: installPolicy(scope, commandPrefix),
|
|
182
|
+
git: {
|
|
183
|
+
local_only: localOnly,
|
|
184
|
+
exclude_path: localExclude?.path ? path.relative(root, localExclude.path) : null,
|
|
185
|
+
excluded_patterns: localExclude?.patterns || []
|
|
186
|
+
},
|
|
168
187
|
retention: DEFAULT_RETENTION_POLICY,
|
|
169
188
|
update_check: {
|
|
170
189
|
enabled: true,
|
|
@@ -244,8 +263,13 @@ export async function initProject(root, opts = {}) {
|
|
|
244
263
|
created.push('.sneakoscope/state/current.json');
|
|
245
264
|
}
|
|
246
265
|
|
|
247
|
-
|
|
248
|
-
|
|
266
|
+
const agentsMdPath = path.join(root, 'AGENTS.md');
|
|
267
|
+
if (localOnly && await exists(agentsMdPath)) {
|
|
268
|
+
created.push('AGENTS.md skipped (local-only existing file)');
|
|
269
|
+
} else {
|
|
270
|
+
await mergeManagedBlock(agentsMdPath, 'Sneakoscope Codex GX MANAGED BLOCK', AGENTS_BLOCK);
|
|
271
|
+
created.push('AGENTS.md managed block');
|
|
272
|
+
}
|
|
249
273
|
|
|
250
274
|
await writeTextAtomic(path.join(root, '.codex', 'config.toml'), `[features]\ncodex_hooks = true\nmulti_agent = true\n\n[agents]\nmax_threads = 6\nmax_depth = 1\n\n[agents.team_consensus]\ndescription = "Planning and debate agent for SKS Team mode. Maps options, constraints, risks, and proposes the agreed objective before implementation starts."\nconfig_file = "./agents/team-consensus.toml"\nnickname_candidates = ["Consensus", "Atlas"]\n\n[agents.implementation_worker]\ndescription = "Implementation worker for SKS Team mode. Owns a clearly bounded write set and coordinates with other workers without reverting their edits."\nconfig_file = "./agents/implementation-worker.toml"\nnickname_candidates = ["Builder", "Mason"]\n\n[agents.db_safety_reviewer]\ndescription = "Read-only database safety reviewer for SQL, migrations, RLS, destructive-operation risk, and rollback safety."\nconfig_file = "./agents/db-safety-reviewer.toml"\nnickname_candidates = ["Sentinel", "Ledger"]\n\n[agents.qa_reviewer]\ndescription = "Read-only verification reviewer for correctness, tests, regressions, and missing evidence."\nconfig_file = "./agents/qa-reviewer.toml"\nnickname_candidates = ["Verifier", "Scout"]\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-team]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-default]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "medium"\n`);
|
|
251
275
|
created.push('.codex/config.toml');
|
|
@@ -272,6 +296,32 @@ export async function initProject(root, opts = {}) {
|
|
|
272
296
|
return { created };
|
|
273
297
|
}
|
|
274
298
|
|
|
299
|
+
async function ensureLocalOnlyGitExclude(root) {
|
|
300
|
+
const gitDir = await resolveGitDir(root);
|
|
301
|
+
if (!gitDir) return { path: null, patterns: [] };
|
|
302
|
+
const patterns = ['.sneakoscope/', '.codex/', '.agents/', 'AGENTS.md'];
|
|
303
|
+
const excludePath = path.join(gitDir, 'info', 'exclude');
|
|
304
|
+
await ensureDir(path.dirname(excludePath));
|
|
305
|
+
const markerStart = '# Sneakoscope Codex local-only generated files';
|
|
306
|
+
const current = await readText(excludePath, '');
|
|
307
|
+
if (!current.includes(markerStart)) {
|
|
308
|
+
const block = `${markerStart}\n${patterns.join('\n')}\n`;
|
|
309
|
+
await writeTextAtomic(excludePath, `${current.trimEnd()}${current.trim() ? '\n\n' : ''}${block}`);
|
|
310
|
+
}
|
|
311
|
+
return { path: excludePath, patterns };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async function resolveGitDir(root) {
|
|
315
|
+
const dotGit = path.join(root, '.git');
|
|
316
|
+
if (!(await exists(dotGit))) return null;
|
|
317
|
+
const text = await readText(dotGit, null);
|
|
318
|
+
if (typeof text === 'string') {
|
|
319
|
+
const match = text.match(/^gitdir:\s*(.+)\s*$/m);
|
|
320
|
+
if (match) return path.resolve(root, match[1]);
|
|
321
|
+
}
|
|
322
|
+
return dotGit;
|
|
323
|
+
}
|
|
324
|
+
|
|
275
325
|
function codexAppQuickReference(scope, commandPrefix) {
|
|
276
326
|
return `# Sneakoscope Codex for Codex App
|
|
277
327
|
|