litcodex-ai 0.3.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/LICENSE +21 -0
- package/README.md +62 -0
- package/bin/litcodex.js +12 -0
- package/dist/cli.d.ts +23 -0
- package/dist/cli.js +183 -0
- package/dist/config-migration/backup.d.ts +2 -0
- package/dist/config-migration/backup.js +42 -0
- package/dist/config-migration/catalog.d.ts +22 -0
- package/dist/config-migration/catalog.js +99 -0
- package/dist/config-migration/cli.d.ts +14 -0
- package/dist/config-migration/cli.js +85 -0
- package/dist/config-migration/config-paths.d.ts +4 -0
- package/dist/config-migration/config-paths.js +64 -0
- package/dist/config-migration/errors.d.ts +11 -0
- package/dist/config-migration/errors.js +28 -0
- package/dist/config-migration/index.d.ts +44 -0
- package/dist/config-migration/index.js +210 -0
- package/dist/config-migration/multi-agent-v2-guard.d.ts +2 -0
- package/dist/config-migration/multi-agent-v2-guard.js +106 -0
- package/dist/config-migration/root-settings.d.ts +6 -0
- package/dist/config-migration/root-settings.js +104 -0
- package/dist/config-migration/state.d.ts +16 -0
- package/dist/config-migration/state.js +40 -0
- package/dist/config-migration/toml-shape.d.ts +8 -0
- package/dist/config-migration/toml-shape.js +107 -0
- package/dist/install/codex.d.ts +34 -0
- package/dist/install/codex.js +94 -0
- package/dist/install/doctor.d.ts +12 -0
- package/dist/install/doctor.js +83 -0
- package/dist/install/errors.d.ts +19 -0
- package/dist/install/errors.js +43 -0
- package/dist/install/execute.d.ts +39 -0
- package/dist/install/execute.js +193 -0
- package/dist/install/index.d.ts +19 -0
- package/dist/install/index.js +193 -0
- package/dist/install/marketplace.d.ts +5 -0
- package/dist/install/marketplace.js +10 -0
- package/dist/install/plan.d.ts +3 -0
- package/dist/install/plan.js +54 -0
- package/dist/install/render-plan.d.ts +3 -0
- package/dist/install/render-plan.js +10 -0
- package/dist/install/types.d.ts +45 -0
- package/dist/install/types.js +5 -0
- package/model-catalog.json +31 -0
- package/node_modules/@litcodex/lit-loop/CHANGELOG.md +19 -0
- package/node_modules/@litcodex/lit-loop/LICENSE +21 -0
- package/node_modules/@litcodex/lit-loop/NOTICE +8 -0
- package/node_modules/@litcodex/lit-loop/README.md +37 -0
- package/node_modules/@litcodex/lit-loop/agents/litcodex-explorer.toml +75 -0
- package/node_modules/@litcodex/lit-loop/agents/litcodex-librarian.toml +98 -0
- package/node_modules/@litcodex/lit-loop/agents/litcodex-litwork-reviewer.toml +21 -0
- package/node_modules/@litcodex/lit-loop/agents/litcodex-metis.toml +64 -0
- package/node_modules/@litcodex/lit-loop/agents/litcodex-momus.toml +68 -0
- package/node_modules/@litcodex/lit-loop/agents/litcodex-plan.toml +163 -0
- package/node_modules/@litcodex/lit-loop/directive.md +85 -0
- package/node_modules/@litcodex/lit-loop/directives/lit-plan.md +286 -0
- package/node_modules/@litcodex/lit-loop/directives/litgoal.md +103 -0
- package/node_modules/@litcodex/lit-loop/directives/litwork.md +363 -0
- package/node_modules/@litcodex/lit-loop/dist/_scaffold.d.ts +1 -0
- package/node_modules/@litcodex/lit-loop/dist/_scaffold.js +3 -0
- package/node_modules/@litcodex/lit-loop/dist/cli.d.ts +6 -0
- package/node_modules/@litcodex/lit-loop/dist/cli.js +44 -0
- package/node_modules/@litcodex/lit-loop/dist/codex-goal-instruction.d.ts +18 -0
- package/node_modules/@litcodex/lit-loop/dist/codex-goal-instruction.js +94 -0
- package/node_modules/@litcodex/lit-loop/dist/codex-hook.d.ts +38 -0
- package/node_modules/@litcodex/lit-loop/dist/codex-hook.js +126 -0
- package/node_modules/@litcodex/lit-loop/dist/directive.d.ts +35 -0
- package/node_modules/@litcodex/lit-loop/dist/directive.js +80 -0
- package/node_modules/@litcodex/lit-loop/dist/goal-status.d.ts +12 -0
- package/node_modules/@litcodex/lit-loop/dist/goal-status.js +25 -0
- package/node_modules/@litcodex/lit-loop/dist/guards.d.ts +73 -0
- package/node_modules/@litcodex/lit-loop/dist/guards.js +215 -0
- package/node_modules/@litcodex/lit-loop/dist/hook-cli.d.ts +17 -0
- package/node_modules/@litcodex/lit-loop/dist/hook-cli.js +94 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-cli.d.ts +19 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-cli.js +106 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-doctor-render.d.ts +7 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-doctor-render.js +39 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-doctor-types.d.ts +52 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-doctor-types.js +7 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-doctor.d.ts +21 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-doctor.js +283 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-errors.d.ts +15 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-errors.js +43 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-handlers.d.ts +18 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-handlers.js +311 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-model.d.ts +51 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-model.js +165 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-stdout.d.ts +6 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-stdout.js +11 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-types.d.ts +26 -0
- package/node_modules/@litcodex/lit-loop/dist/loop-types.js +8 -0
- package/node_modules/@litcodex/lit-loop/dist/markers.d.ts +9 -0
- package/node_modules/@litcodex/lit-loop/dist/markers.js +14 -0
- package/node_modules/@litcodex/lit-loop/dist/modes.d.ts +15 -0
- package/node_modules/@litcodex/lit-loop/dist/modes.js +56 -0
- package/node_modules/@litcodex/lit-loop/dist/state-paths.d.ts +41 -0
- package/node_modules/@litcodex/lit-loop/dist/state-paths.js +111 -0
- package/node_modules/@litcodex/lit-loop/dist/state-store.d.ts +39 -0
- package/node_modules/@litcodex/lit-loop/dist/state-store.js +419 -0
- package/node_modules/@litcodex/lit-loop/dist/state-types.d.ts +90 -0
- package/node_modules/@litcodex/lit-loop/dist/state-types.js +61 -0
- package/node_modules/@litcodex/lit-loop/dist/trigger.d.ts +54 -0
- package/node_modules/@litcodex/lit-loop/dist/trigger.js +75 -0
- package/node_modules/@litcodex/lit-loop/package.json +27 -0
- package/package.json +30 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// M12 / T17 — installer barrel + process-facing route entrypoints (S12 §cli routes).
|
|
2
|
+
//
|
|
3
|
+
// These are the functions the top-level dispatcher (src/cli.ts) calls for the `install`/`doctor`/
|
|
4
|
+
// `uninstall` routes. They own the ONE real default `spawn` (always `codex`, never an exec-wrapper), parse
|
|
5
|
+
// argv into typed `InstallOptions`, and return an integer exit code. `--dry-run` returns BEFORE any
|
|
6
|
+
// spawn or fs write (renders the plan only). Unknown/bad flags exit 1.
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { migrateCodexConfig } from "../config-migration/index.js";
|
|
11
|
+
import { resolveCodexHome } from "./codex.js";
|
|
12
|
+
import { renderDoctorText, runDoctor } from "./doctor.js";
|
|
13
|
+
import { exitCodeForInstallError, InstallError, toErrorJson } from "./errors.js";
|
|
14
|
+
import { executeInstallPlan } from "./execute.js";
|
|
15
|
+
import { LITCODEX_PLUGIN_REF, LITCODEX_REPO_URL } from "./marketplace.js";
|
|
16
|
+
import { buildInstallPlan } from "./plan.js";
|
|
17
|
+
import { renderInstallPlan } from "./render-plan.js";
|
|
18
|
+
export { renderDoctorText, runDoctor } from "./doctor.js";
|
|
19
|
+
export { INSTALL_ERROR_CODES, InstallError, toErrorJson } from "./errors.js";
|
|
20
|
+
export { executeInstallPlan } from "./execute.js";
|
|
21
|
+
export { buildInstallPlan } from "./plan.js";
|
|
22
|
+
export { INSTALL_PLAN_HEADER, renderInstallPlan } from "./render-plan.js";
|
|
23
|
+
const KNOWN_INSTALL_FLAGS = new Set(["--dry-run", "--no-tui", "--codex-autonomous", "--force", "--json", "--repo"]);
|
|
24
|
+
/** The real default spawn: argv array, never `shell:true`, never string concatenation. */
|
|
25
|
+
const realSpawn = (cmd, args, opts) => {
|
|
26
|
+
const res = spawnSync(cmd, args, { stdio: opts.stdio, encoding: "utf8" });
|
|
27
|
+
const out = {
|
|
28
|
+
status: res.status,
|
|
29
|
+
stdout: res.stdout ?? "",
|
|
30
|
+
stderr: res.stderr ?? "",
|
|
31
|
+
};
|
|
32
|
+
if (res.error) {
|
|
33
|
+
out.error = res.error;
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
};
|
|
37
|
+
const realFs = {
|
|
38
|
+
existsSync,
|
|
39
|
+
readFileSync: (p, enc) => readFileSync(p, enc),
|
|
40
|
+
};
|
|
41
|
+
const realWriteFs = {
|
|
42
|
+
existsSync,
|
|
43
|
+
mkdirSync: (p, o) => {
|
|
44
|
+
mkdirSync(p, o);
|
|
45
|
+
},
|
|
46
|
+
readdirSync: (p) => readdirSync(p),
|
|
47
|
+
readFileSync: (p, e) => readFileSync(p, e),
|
|
48
|
+
writeFileSync: (p, d) => {
|
|
49
|
+
writeFileSync(p, d);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
function defaultIo() {
|
|
53
|
+
return {
|
|
54
|
+
stdout: process.stdout,
|
|
55
|
+
stderr: process.stderr,
|
|
56
|
+
env: process.env,
|
|
57
|
+
repoRoot: process.cwd(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function emitError(io, err) {
|
|
61
|
+
const json = toErrorJson(err);
|
|
62
|
+
io.stderr.write(`${JSON.stringify(json)}\n`);
|
|
63
|
+
io.stderr.write(`[litcodex] ${json.error.message}\n`);
|
|
64
|
+
return err instanceof InstallError ? exitCodeForInstallError(err.code) : 1;
|
|
65
|
+
}
|
|
66
|
+
/** `litcodex install [flags]` — render plan (dry-run) or execute against `codex`. */
|
|
67
|
+
export async function runInstallCli(args, io = defaultIo()) {
|
|
68
|
+
let opts;
|
|
69
|
+
try {
|
|
70
|
+
opts = parseInstallOptions(args, io);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
return emitError(io, err);
|
|
74
|
+
}
|
|
75
|
+
const plan = buildInstallPlan(opts);
|
|
76
|
+
if (opts.dryRun) {
|
|
77
|
+
// ZERO spawns, ZERO fs writes: render and return.
|
|
78
|
+
io.stdout.write(`${renderInstallPlan(plan)}\n`);
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
result = await executeInstallPlan(plan, {
|
|
84
|
+
spawn: realSpawn,
|
|
85
|
+
fs: realFs,
|
|
86
|
+
env: io.env,
|
|
87
|
+
now: () => Date.now(),
|
|
88
|
+
repoRoot: io.repoRoot,
|
|
89
|
+
migrateConfig: migrateCodexConfig,
|
|
90
|
+
force: opts.force,
|
|
91
|
+
codexHome: opts.codexHome,
|
|
92
|
+
writeFs: realWriteFs,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
return emitError(io, err);
|
|
97
|
+
}
|
|
98
|
+
if (opts.json) {
|
|
99
|
+
io.stdout.write(`${JSON.stringify(result)}\n`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
for (const step of result.steps) {
|
|
103
|
+
io.stdout.write(`${step.status} ${step.kind}: ${step.detail}\n`);
|
|
104
|
+
}
|
|
105
|
+
io.stdout.write("litcodex install: complete\n");
|
|
106
|
+
}
|
|
107
|
+
return result.ok ? 0 : 3;
|
|
108
|
+
}
|
|
109
|
+
/** `litcodex doctor [--json]` — read-only health report. Exit 0 when ok, 4 otherwise. */
|
|
110
|
+
export function runDoctorCli(args, io = defaultIo()) {
|
|
111
|
+
const json = args.includes("--json");
|
|
112
|
+
const report = runDoctor({ spawn: realSpawn, fs: realFs, env: io.env, repoRoot: io.repoRoot });
|
|
113
|
+
if (json) {
|
|
114
|
+
io.stdout.write(`${JSON.stringify(report)}\n`);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
io.stdout.write(`${renderDoctorText(report)}\n`);
|
|
118
|
+
}
|
|
119
|
+
return report.ok ? 0 : 4;
|
|
120
|
+
}
|
|
121
|
+
/** `litcodex uninstall [--json]` — remove the registered plugin via `codex plugin remove`. */
|
|
122
|
+
export function runUninstallCli(args, io = defaultIo()) {
|
|
123
|
+
const json = args.includes("--json");
|
|
124
|
+
const codexHome = resolveCodexHome(io.env);
|
|
125
|
+
const env = io.env;
|
|
126
|
+
const codexBin = env["CODEX_BIN"]?.trim() && existsSync(env["CODEX_BIN"].trim()) ? env["CODEX_BIN"].trim() : "codex";
|
|
127
|
+
const res = realSpawn(codexBin, ["plugin", "remove", LITCODEX_PLUGIN_REF], { stdio: "inherit" });
|
|
128
|
+
const ok = !res.error && res.status === 0;
|
|
129
|
+
// Remove litcodex-owned agent files from <codexHome>/agents/.
|
|
130
|
+
const agentsDir = join(codexHome, "agents");
|
|
131
|
+
if (existsSync(agentsDir)) {
|
|
132
|
+
try {
|
|
133
|
+
const files = readdirSync(agentsDir);
|
|
134
|
+
for (const file of files) {
|
|
135
|
+
if (/^litcodex-.*\.toml$/.test(file)) {
|
|
136
|
+
rmSync(join(agentsDir, file));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Best-effort; do not fail uninstall due to agent cleanup issues.
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (json) {
|
|
145
|
+
io.stdout.write(`${JSON.stringify({ ok, codexHome })}\n`);
|
|
146
|
+
}
|
|
147
|
+
else if (ok) {
|
|
148
|
+
io.stdout.write("litcodex uninstall: complete\n");
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
io.stderr.write("[litcodex] uninstall: codex plugin remove failed\n");
|
|
152
|
+
}
|
|
153
|
+
return ok ? 0 : 3;
|
|
154
|
+
}
|
|
155
|
+
/** Parse argv (already past `install`) into typed options. Unknown flag → BAD_FLAG (exit 1). */
|
|
156
|
+
function parseInstallOptions(args, io) {
|
|
157
|
+
// `--repo <value>` consumes the following token as its value; never treat that value as a flag.
|
|
158
|
+
const repoValueIndex = args.indexOf("--repo") + 1;
|
|
159
|
+
for (let i = 0; i < args.length; i++) {
|
|
160
|
+
const token = args[i];
|
|
161
|
+
if (token === undefined || i === repoValueIndex) {
|
|
162
|
+
continue; // the --repo VALUE is not a flag
|
|
163
|
+
}
|
|
164
|
+
if (token.startsWith("--") && !KNOWN_INSTALL_FLAGS.has(token)) {
|
|
165
|
+
throw new InstallError("LITCODEX_INSTALL_BAD_FLAG", `unknown flag "${token}"`, { flag: token });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
dryRun: args.includes("--dry-run"),
|
|
170
|
+
noTui: args.includes("--no-tui"),
|
|
171
|
+
autonomous: args.includes("--codex-autonomous"),
|
|
172
|
+
force: args.includes("--force"),
|
|
173
|
+
json: args.includes("--json"),
|
|
174
|
+
codexHome: resolveCodexHome(io.env),
|
|
175
|
+
repoUrl: parseRepoUrl(args),
|
|
176
|
+
repoRoot: io.repoRoot,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* `--repo <local-path|git-url>` overrides the marketplace source (default LITCODEX_REPO_URL).
|
|
181
|
+
* Enables installing the local/unpublished marketplace before the canonical repo is published.
|
|
182
|
+
*/
|
|
183
|
+
function parseRepoUrl(args) {
|
|
184
|
+
const i = args.indexOf("--repo");
|
|
185
|
+
if (i === -1) {
|
|
186
|
+
return LITCODEX_REPO_URL;
|
|
187
|
+
}
|
|
188
|
+
const value = args[i + 1];
|
|
189
|
+
if (value === undefined || value.startsWith("--")) {
|
|
190
|
+
throw new InstallError("LITCODEX_INSTALL_BAD_FLAG", "--repo requires a value (a local marketplace path or a git URL)", { flag: "--repo" });
|
|
191
|
+
}
|
|
192
|
+
return value;
|
|
193
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const LITCODEX_MARKETPLACE: "litcodex";
|
|
2
|
+
export declare const LITCODEX_PLUGIN: "litcodex";
|
|
3
|
+
export declare const LITCODEX_REPO_URL: "https://github.com/wjgoarxiv/litcodex";
|
|
4
|
+
/** The plugin reference Codex consumes: `<plugin>@<marketplace>`. */
|
|
5
|
+
export declare const LITCODEX_PLUGIN_REF: "litcodex@litcodex";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// M12 / T17 — registration identity constants (S12 §marketplace.ts; A3 Part D).
|
|
2
|
+
//
|
|
3
|
+
// Single source for the marketplace id + plugin id + repo URL the installer registers with Codex.
|
|
4
|
+
// `${owner}` is a placeholder until the live repo lands (A5 carries the UNVERIFIED note); the argv
|
|
5
|
+
// strings built from these constants are asserted byte-stable by the dry-run golden.
|
|
6
|
+
export const LITCODEX_MARKETPLACE = "litcodex";
|
|
7
|
+
export const LITCODEX_PLUGIN = "litcodex";
|
|
8
|
+
export const LITCODEX_REPO_URL = "https://github.com/wjgoarxiv/litcodex";
|
|
9
|
+
/** The plugin reference Codex consumes: `<plugin>@<marketplace>`. */
|
|
10
|
+
export const LITCODEX_PLUGIN_REF = `${LITCODEX_PLUGIN}@${LITCODEX_MARKETPLACE}`;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// M12 / T17 — pure install plan builder (S12 §plan.ts; addendum A5.3 pinned argv).
|
|
2
|
+
//
|
|
3
|
+
// `buildInstallPlan` is pure + deterministic: identical flags → identical ordered steps → a
|
|
4
|
+
// byte-stable dry-run rendering free of legacy tokens. The argv every step carries is the literal
|
|
5
|
+
// `codex …` vector that WOULD be spawned (never an exec-wrapper). No environment-dependent reordering.
|
|
6
|
+
import { LITCODEX_PLUGIN_REF } from "./marketplace.js";
|
|
7
|
+
/** Build the ordered plan. The fixed order is marketplace → plugin → hooks → config → verify. */
|
|
8
|
+
export function buildInstallPlan(opts) {
|
|
9
|
+
// `codex plugin add` is non-interactive and (codex-cli 0.139.x) REJECTS `--no-tui` as an unknown
|
|
10
|
+
// option — the correct argv is just `codex plugin add <plugin>@<marketplace>`. The accepted
|
|
11
|
+
// `--no-tui` CLI flag is now a no-op kept for habit/compat (VERIFY-LIVE finding vs codex 0.139.0).
|
|
12
|
+
const pluginAddArgs = ["codex", "plugin", "add", LITCODEX_PLUGIN_REF];
|
|
13
|
+
const configTitle = opts.autonomous
|
|
14
|
+
? "Update Codex config.toml (non-destructive, autonomous defaults)"
|
|
15
|
+
: "Update Codex config.toml (non-destructive)";
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
kind: "marketplace-add",
|
|
19
|
+
title: `Add LitCodex marketplace: codex plugin marketplace add ${opts.repoUrl}`,
|
|
20
|
+
command: ["codex", "plugin", "marketplace", "add", opts.repoUrl],
|
|
21
|
+
skippable: true,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
kind: "plugin-add",
|
|
25
|
+
title: `Install plugin: ${pluginAddArgs.join(" ")}`,
|
|
26
|
+
command: pluginAddArgs,
|
|
27
|
+
skippable: true,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
kind: "hooks-register",
|
|
31
|
+
title: "Register lit-loop UserPromptSubmit hook (bundled hooks.json)",
|
|
32
|
+
command: null,
|
|
33
|
+
skippable: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
kind: "agents-install",
|
|
37
|
+
title: "Install litwork subagent roles into Codex agents dir (backup-safe)",
|
|
38
|
+
command: null,
|
|
39
|
+
skippable: true,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
kind: "config-update",
|
|
43
|
+
title: configTitle,
|
|
44
|
+
command: null,
|
|
45
|
+
skippable: false,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
kind: "verify",
|
|
49
|
+
title: "Verify: litcodex doctor",
|
|
50
|
+
command: null,
|
|
51
|
+
skippable: false,
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// M12 / T17 — dry-run plan renderer (S12 §render-plan.ts).
|
|
2
|
+
//
|
|
3
|
+
// `renderInstallPlan` is the exact stdout text for `install --dry-run`: a fixed LitCodex header
|
|
4
|
+
// followed by one numbered step title per line, in execution order. No exec-wrapper line, no legacy token,
|
|
5
|
+
// no trailing blank line (the caller appends the final "\n").
|
|
6
|
+
export const INSTALL_PLAN_HEADER = "litcodex install plan (Codex)";
|
|
7
|
+
export function renderInstallPlan(steps) {
|
|
8
|
+
const lines = [INSTALL_PLAN_HEADER, ...steps.map((step, i) => `${i + 1}. ${step.title}`)];
|
|
9
|
+
return lines.join("\n");
|
|
10
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Parsed, typed install options (parse-don't-validate boundary out of argv). */
|
|
2
|
+
export interface InstallOptions {
|
|
3
|
+
readonly dryRun: boolean;
|
|
4
|
+
readonly noTui: boolean;
|
|
5
|
+
readonly autonomous: boolean;
|
|
6
|
+
readonly force: boolean;
|
|
7
|
+
readonly json: boolean;
|
|
8
|
+
/** Resolved absolute Codex home (never relative). */
|
|
9
|
+
readonly codexHome: string;
|
|
10
|
+
/** Marketplace source repo URL (compile-time constant; never user-supplied). */
|
|
11
|
+
readonly repoUrl: string;
|
|
12
|
+
/** Absolute repo root used to resolve the bundled marketplace metadata / hooks. */
|
|
13
|
+
readonly repoRoot: string;
|
|
14
|
+
}
|
|
15
|
+
export type InstallStepKind = "marketplace-add" | "plugin-add" | "hooks-register" | "agents-install" | "config-update" | "verify";
|
|
16
|
+
export interface InstallStep {
|
|
17
|
+
readonly kind: InstallStepKind;
|
|
18
|
+
/** Human one-line label (LitCodex-native; no legacy tokens). */
|
|
19
|
+
readonly title: string;
|
|
20
|
+
/** argv to spawn (always `codex …`), or null for an in-process step. */
|
|
21
|
+
readonly command: readonly string[] | null;
|
|
22
|
+
/** True when a prior identical state makes this a probe-gated no-op. */
|
|
23
|
+
readonly skippable: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type InstallStepStatus = "ok" | "skipped" | "failed";
|
|
26
|
+
export interface InstallStepResult {
|
|
27
|
+
readonly kind: InstallStepKind;
|
|
28
|
+
readonly status: InstallStepStatus;
|
|
29
|
+
readonly detail: string;
|
|
30
|
+
}
|
|
31
|
+
export interface InstallResult {
|
|
32
|
+
readonly ok: boolean;
|
|
33
|
+
readonly steps: readonly InstallStepResult[];
|
|
34
|
+
readonly codexHome: string;
|
|
35
|
+
}
|
|
36
|
+
export interface DoctorReport {
|
|
37
|
+
readonly ok: boolean;
|
|
38
|
+
readonly marketplaceRegistered: boolean;
|
|
39
|
+
readonly pluginInstalled: boolean;
|
|
40
|
+
readonly hooksWired: boolean;
|
|
41
|
+
readonly configManaged: boolean;
|
|
42
|
+
readonly codexBinaryFound: boolean;
|
|
43
|
+
readonly agentsInstalled: boolean;
|
|
44
|
+
readonly issues: readonly string[];
|
|
45
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// M12 / T17 — installer shared types (S12 §Public-contract types.ts).
|
|
2
|
+
//
|
|
3
|
+
// Pure type declarations only. The installer is self-contained: the ONLY child process it ever
|
|
4
|
+
// spawns is `codex`; no exec-wrapper, no forwarder. `--dry-run` performs zero spawns and zero writes.
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2026-06-13.gpt-5.5-400k-high",
|
|
3
|
+
"current": {
|
|
4
|
+
"model": "gpt-5.5",
|
|
5
|
+
"model_context_window": 400000,
|
|
6
|
+
"model_reasoning_effort": "high",
|
|
7
|
+
"plan_mode_reasoning_effort": "xhigh"
|
|
8
|
+
},
|
|
9
|
+
"roles": {
|
|
10
|
+
"default": {
|
|
11
|
+
"model": "gpt-5.5",
|
|
12
|
+
"model_context_window": 400000,
|
|
13
|
+
"model_reasoning_effort": "high",
|
|
14
|
+
"plan_mode_reasoning_effort": "xhigh"
|
|
15
|
+
},
|
|
16
|
+
"verifier": { "model": "gpt-5.5", "model_reasoning_effort": "high" },
|
|
17
|
+
"worker": { "model": "gpt-5.5", "model_reasoning_effort": "high" }
|
|
18
|
+
},
|
|
19
|
+
"managedProfiles": [
|
|
20
|
+
{
|
|
21
|
+
"version": "legacy.gpt-5.5-1m",
|
|
22
|
+
"match": {
|
|
23
|
+
"model": "gpt-5.5",
|
|
24
|
+
"model_context_window": 1000000,
|
|
25
|
+
"model_reasoning_effort": "high",
|
|
26
|
+
"plan_mode_reasoning_effort": "xhigh"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{ "version": "legacy.gpt-5.5-272k", "match": { "model": "gpt-5.5", "model_context_window": 272000 } }
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@litcodex/lit-loop` are documented here.
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] - 2026-06-13
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Bounded `lit` trigger (Unicode-aware; rejects `split`/`literal`/`litmus`/`lithium`/`glitter`).
|
|
13
|
+
- Codex `UserPromptSubmit` hook that injects the `<lit-loop-mode>` directive, with duplicate,
|
|
14
|
+
context-pressure, and prompt-injection guards.
|
|
15
|
+
- Durable `.litcodex/lit-loop` state store: atomic writes (tmp + fsync + rename), append-only
|
|
16
|
+
ledger, schema validation, and non-destructive corruption recovery.
|
|
17
|
+
- `litcodex loop` command model: `create`, `status`, `run`, `checkpoint`, `record-evidence`,
|
|
18
|
+
`doctor`, `help`.
|
|
19
|
+
- Loop doctor diagnostics (six checks) and the lit-loop operational skill.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LitCodex Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
LitCodex — @litcodex/lit-loop
|
|
2
|
+
Copyright (c) 2026 LitCodex Authors
|
|
3
|
+
|
|
4
|
+
This product is licensed under the MIT License (see LICENSE).
|
|
5
|
+
|
|
6
|
+
The lit-loop trigger/hook/loop-runtime mechanics were re-implemented for LitCodex with a
|
|
7
|
+
LitCodex-native identity and hardened path, state, and packaging handling. No third-party code is
|
|
8
|
+
vendored into this package; the bundled directive and skill content are original to LitCodex.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @litcodex/lit-loop
|
|
2
|
+
|
|
3
|
+
The **lit-loop** component of [LitCodex](../../../../README.md) — the bare-`lit` trigger, the Codex
|
|
4
|
+
`UserPromptSubmit` hook, and the durable loop runtime.
|
|
5
|
+
|
|
6
|
+
This package is bundled and installed by [`litcodex-ai`](https://www.npmjs.com/package/litcodex-ai);
|
|
7
|
+
you normally don't install it directly.
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
Typing a bare **`lit`** (bounded — `split`, `literal`, `litmus` do not trigger) in Codex makes the
|
|
12
|
+
hook inject a `<lit-loop-mode>` directive that puts the agent into **lit-loop**: an evidence-bound,
|
|
13
|
+
autonomous work loop that maintains durable state, verifies progress, checkpoints evidence, and
|
|
14
|
+
continues until the work is genuinely done or blocked.
|
|
15
|
+
|
|
16
|
+
## Loop state
|
|
17
|
+
|
|
18
|
+
Durable state lives under `.litcodex/lit-loop/` in the project:
|
|
19
|
+
|
|
20
|
+
| File | Role |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| `brief.md` | the run brief |
|
|
23
|
+
| `goals.json` | the plan + goals + success criteria |
|
|
24
|
+
| `ledger.jsonl` | append-only event ledger |
|
|
25
|
+
| `evidence/` | captured evidence artifacts |
|
|
26
|
+
|
|
27
|
+
Writes are atomic (tmp + fsync + rename) and corruption is recovered to a timestamped `.bak`, never
|
|
28
|
+
auto-discarded.
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
`litcodex loop create | status | run | checkpoint | record-evidence | doctor` — see the
|
|
33
|
+
[repository README](../../../../README.md) for the full loop model.
|
|
34
|
+
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name = "litcodex-explorer"
|
|
2
|
+
description = "Codebase search specialist for Codex sessions. Finds files and code in the working tree, returns absolute paths with structured results. Read-only."
|
|
3
|
+
nickname_candidates = ["Explorer"]
|
|
4
|
+
model = "gpt-5.4-mini"
|
|
5
|
+
model_reasoning_effort = "low"
|
|
6
|
+
service_tier = "fast"
|
|
7
|
+
|
|
8
|
+
developer_instructions = """
|
|
9
|
+
Role: codebase search specialist. Find files + code, return actionable results. Read-only.
|
|
10
|
+
|
|
11
|
+
# Goal
|
|
12
|
+
Answer the orchestrator's "Where is X?" / "Which files do Y?" / "Find code that does Z" precisely enough that the caller proceeds without follow-up.
|
|
13
|
+
|
|
14
|
+
# When to invoke me (self-check)
|
|
15
|
+
- USE me when: multiple search angles are needed, the module structure is unfamiliar, or cross-layer pattern discovery is required.
|
|
16
|
+
- AVOID me when: the caller already knows the exact file or symbol, or a single keyword search suffices. If a request looks like that, answer in one shot and skip the parallel flood.
|
|
17
|
+
|
|
18
|
+
# Thoroughness
|
|
19
|
+
The caller MAY specify thoroughness. Honor it:
|
|
20
|
+
- `quick` -> 1 wave, the most-likely 1-2 files, terse `<answer>`.
|
|
21
|
+
- `medium` (default) -> 1-2 waves, all clearly relevant files, normal `<answer>`.
|
|
22
|
+
- `very thorough` -> multiple waves, every plausible match across the repo, exhaustive `<answer>` including adjacent surfaces the caller might touch next.
|
|
23
|
+
|
|
24
|
+
# Required output (ALWAYS, BOTH BLOCKS)
|
|
25
|
+
|
|
26
|
+
<analysis>
|
|
27
|
+
**Literal Request**: [what was literally asked]
|
|
28
|
+
**Actual Need**: [what the caller is really trying to accomplish]
|
|
29
|
+
**Success Looks Like**: [the answer that would let them proceed immediately]
|
|
30
|
+
</analysis>
|
|
31
|
+
|
|
32
|
+
<results>
|
|
33
|
+
<files>
|
|
34
|
+
- /absolute/path/to/file1.ext - why this file is relevant
|
|
35
|
+
- /absolute/path/to/file2.ext - why this file is relevant
|
|
36
|
+
</files>
|
|
37
|
+
|
|
38
|
+
<answer>
|
|
39
|
+
[Direct answer to the actual need, not just a file list.
|
|
40
|
+
If asked "where is auth?", explain the auth flow you found.]
|
|
41
|
+
</answer>
|
|
42
|
+
|
|
43
|
+
<next_steps>
|
|
44
|
+
[What to do with this information, or "Ready to proceed - no follow-up needed".]
|
|
45
|
+
</next_steps>
|
|
46
|
+
</results>
|
|
47
|
+
|
|
48
|
+
# Tool strategy (parallel, flood the first wave)
|
|
49
|
+
- Use the `shell` tool for repo-wide inspection, CLI smoke tests, git/history checks, and bounded command output. Use plain `capture-pane` only to inspect an existing tmux pane.
|
|
50
|
+
- Symbol questions -> `lsp_goto_definition`, `lsp_find_references`, `lsp_symbols`, `lsp_diagnostics`.
|
|
51
|
+
- Structural shapes -> `ast_grep_search` with `$VAR` / `$$$` metavars.
|
|
52
|
+
- Text / strings / comments / logs -> `rg` (grep).
|
|
53
|
+
- File-name discovery -> `glob` / `find`.
|
|
54
|
+
- Verbatim content -> `read`.
|
|
55
|
+
- History -> `git log` / `git blame` / `git show`.
|
|
56
|
+
|
|
57
|
+
Fire 3+ independent calls in the first action. Cross-validate findings across multiple tools. Do not serialize unless one call's output strictly feeds the next.
|
|
58
|
+
|
|
59
|
+
# Retrieval budget
|
|
60
|
+
Stop searching when the question is concretely answered. After two parallel waves with no new useful matches, stop and report what you have.
|
|
61
|
+
|
|
62
|
+
# Success criteria (the response is INVALID if any is unmet)
|
|
63
|
+
- Every path is **absolute** (starts with `/`).
|
|
64
|
+
- ALL relevant matches are included, not just the first one.
|
|
65
|
+
- The answer addresses the **actual need**, not only the literal request.
|
|
66
|
+
- The caller can act without asking "but where exactly?" or "what about X?".
|
|
67
|
+
- Both `<analysis>` and `<results>` blocks are present.
|
|
68
|
+
|
|
69
|
+
# Constraints
|
|
70
|
+
- READ-ONLY. Tools I will NEVER call: `edit`, `write`, `apply_patch`, anything that mutates the filesystem.
|
|
71
|
+
- NEVER create files. Report findings as message text only - no scratch files, no notes on disk, no temp dumps.
|
|
72
|
+
- Do not browse the internet. External research is the litcodex-librarian's job.
|
|
73
|
+
- No emojis. Keep output clean and parseable.
|
|
74
|
+
- No tool names in prose (say "search the codebase", not "use rg"). No preamble ("I'll help you with..."). Answer directly.
|
|
75
|
+
"""
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name = "litcodex-librarian"
|
|
2
|
+
description = "External open-source codebase and documentation researcher. Investigates libraries via gh CLI, web search, and webfetch, returning SHA-pinned GitHub permalink citations. Read-only."
|
|
3
|
+
nickname_candidates = ["Librarian"]
|
|
4
|
+
model = "gpt-5.4-mini"
|
|
5
|
+
model_reasoning_effort = "low"
|
|
6
|
+
service_tier = "fast"
|
|
7
|
+
|
|
8
|
+
developer_instructions = """
|
|
9
|
+
# THE LIBRARIAN
|
|
10
|
+
|
|
11
|
+
You are THE LIBRARIAN, a read-only researcher for external libraries, OSS projects, and vendor APIs. Every code claim you make carries a SHA-pinned GitHub permalink, verifiable in one click.
|
|
12
|
+
|
|
13
|
+
# When to invoke me (self-check)
|
|
14
|
+
- USE me when: the question concerns an unfamiliar package, a behaviour likely originating from a dependency, an upstream API contract, or finding an existing OSS implementation of something.
|
|
15
|
+
- AVOID me when: the answer lives in the local working-tree codebase (that's the litcodex-explorer's job), the question is purely conceptual with no external source involved, or the caller already has the URL and just wants one page summarized (use a direct webfetch instead).
|
|
16
|
+
|
|
17
|
+
# Date awareness
|
|
18
|
+
Check the current date from the environment before any search; never query with last year's date. Include the current year in time-sensitive queries ("<library> topic <CURRENT_YEAR>"); when older results conflict with current-year ones, drop the stale ones and say so in the response.
|
|
19
|
+
|
|
20
|
+
# Classify first (state the type in one line before investigating)
|
|
21
|
+
- TYPE A - CONCEPTUAL: "How do I use X?" / "Best practice for Y?" -> doc discovery, then docs + lightweight code search.
|
|
22
|
+
- TYPE B - IMPLEMENTATION: "How does X implement Y?" / "Show me the source of Z" -> clone + read + blame + permalink.
|
|
23
|
+
- TYPE C - CONTEXT / HISTORY: "Why was X changed?" / "History of Y?" -> issues / PRs / git log / git blame.
|
|
24
|
+
- TYPE D - COMPREHENSIVE: complex or ambiguous -> doc discovery, then all of the above in parallel.
|
|
25
|
+
|
|
26
|
+
# Doc discovery (before TYPE A and TYPE D; skip for TYPE B and TYPE C)
|
|
27
|
+
1. One parallel batch: `context7` (resolve the library id, then query the specific topic - the first stop for any library question) + `web_search("<library> official documentation")` to pick the official base URL (not blogs, tutorials, or aggregators).
|
|
28
|
+
2. If the user names a version ("React 18", "v2.x"): query `context7` with the versioned id (`/org/project/<version>`) + `web_search("<library> v<version> documentation")`, and confirm the docs match that version (versioned URL segments like `/docs/v2/`, `/v14/`).
|
|
29
|
+
3. `webfetch` the specific doc pages surfaced by step 1. Only when `context7` does not index the library, map the docs via `webfetch(<base>/sitemap.xml)` (fallbacks: `/sitemap-0.xml`, `/sitemap_index.xml`, or the docs index page navigation), then fetch the matching section pages.
|
|
30
|
+
|
|
31
|
+
If the library has no official docs at all (rare), note that in the response and work from source.
|
|
32
|
+
|
|
33
|
+
# Execute by type
|
|
34
|
+
Run independent calls as one parallel batch, and vary the angle per call - the same query twice wastes budget (good: `gh search code "useQuery("`, then `"queryOptions"`, then `"staleTime:"`; bad: `"useQuery"` twice).
|
|
35
|
+
|
|
36
|
+
## TYPE A (3-4 parallel calls after doc discovery)
|
|
37
|
+
- `context7` follow-up on the specific API surface (the first stop for any library question).
|
|
38
|
+
- `web_search` for current-year usage examples and best practices.
|
|
39
|
+
- `grep_app` for real-world usage on GitHub; `gh search code "<pattern>" --language <lang>` when you need repo/path/language filters.
|
|
40
|
+
- `webfetch` the targeted doc pages from doc discovery.
|
|
41
|
+
|
|
42
|
+
## TYPE B (sequence, with parallel acceleration)
|
|
43
|
+
1. Clone shallowly: `gh repo clone <o>/<r> "${TMPDIR:-/tmp}/<name>" -- --depth 1` (cross-platform temp path; let the shell resolve it).
|
|
44
|
+
2. Pin the SHA: `git rev-parse HEAD` in the clone.
|
|
45
|
+
3. Locate with `rg` / `ast_grep`, `read` the specific file, `git blame` for context if needed.
|
|
46
|
+
4. Build permalinks against the pinned SHA.
|
|
47
|
+
Accelerate with one batch of 4+ calls: the clone + `grep_app` or `gh search code "<symbol>" --repo <o>/<r>` + `gh api repos/<o>/<r>/commits/HEAD --jq .sha` + a `context7` or targeted docs fetch of the same API surface.
|
|
48
|
+
|
|
49
|
+
## TYPE C (4+ parallel calls)
|
|
50
|
+
- `gh search issues "<keyword>" --repo <o>/<r> --state all --limit 10` and `gh search prs "<keyword>" --repo <o>/<r> --state merged --limit 10`.
|
|
51
|
+
- Clone with more depth (`-- --depth 50`), then `git log --oneline -n 20 -- <path>`, `git blame -L <a>,<b> <path>`, and `git show` as needed.
|
|
52
|
+
- `gh api repos/<o>/<r>/releases --jq '.[0:5]'` for recent release notes.
|
|
53
|
+
For a specific issue / PR: `gh issue view <num> --repo <o>/<r> --comments`, `gh pr view <num> --repo <o>/<r> --comments`, `gh api repos/<o>/<r>/pulls/<num>/files` for the diff surface.
|
|
54
|
+
|
|
55
|
+
## TYPE D (6+ parallel calls after doc discovery)
|
|
56
|
+
2 docs calls (`context7` topic query + targeted `webfetch`) + 2 code-search calls (`grep_app` / `gh search code`, different angles) + 1 source clone + 1 issues/PRs query.
|
|
57
|
+
|
|
58
|
+
# Evidence synthesis
|
|
59
|
+
Every code claim MUST use this block (repeat per claim):
|
|
60
|
+
|
|
61
|
+
````markdown
|
|
62
|
+
**Claim**: [what you're asserting]
|
|
63
|
+
|
|
64
|
+
**Evidence** ([source](https://github.com/<owner>/<repo>/blob/<sha>/<path>#L<a>-L<b>)):
|
|
65
|
+
```<language>
|
|
66
|
+
// the actual code, verbatim
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Explanation**: [why this works, grounded in the code above]
|
|
70
|
+
````
|
|
71
|
+
|
|
72
|
+
End the response with one line: `Open questions: none` or `Open questions: <list>`.
|
|
73
|
+
|
|
74
|
+
Permalink format: `https://github.com/<owner>/<repo>/blob/<commit-sha>/<filepath>#L<start>-L<end>`
|
|
75
|
+
(e.g. `https://github.com/tanstack/query/blob/abc123def/packages/react-query/src/useQuery.ts#L42-L50`).
|
|
76
|
+
Get the SHA from the clone (`git rev-parse HEAD`), the API (`gh api repos/<o>/<r>/commits/HEAD --jq .sha`), or a tag (`gh api repos/<o>/<r>/git/refs/tags/<tag> --jq .object.sha`). NEVER link to a branch name (`/blob/main/...`) - always pin to a SHA so the line numbers stay valid forever.
|
|
77
|
+
|
|
78
|
+
# Failure recovery
|
|
79
|
+
- `context7` library-id lookup returns nothing -> sitemap-driven `webfetch` of the official docs; if docs are thin, clone and read source + README.
|
|
80
|
+
- `gh search code` returns nothing -> broaden, search the concept instead of the exact symbol, or try forks and mirrors.
|
|
81
|
+
- `gh` rate-limited -> fall back to the clone in `${TMPDIR:-/tmp}`.
|
|
82
|
+
- Repo not found -> search for forks or mirrors.
|
|
83
|
+
- Versioned docs missing -> fall back to the latest version and say so explicitly.
|
|
84
|
+
- Sources disagree -> surface the disagreement plainly; do not pick a side by guessing.
|
|
85
|
+
- Genuinely uncertain -> state the uncertainty and propose a hypothesis the caller can verify; never fabricate a confident answer.
|
|
86
|
+
|
|
87
|
+
# Constraints
|
|
88
|
+
- READ-ONLY. Tools I will NEVER call: `edit`, `write`, `apply_patch`, anything that mutates the working-tree filesystem. Cloning into `${TMPDIR:-/tmp}` is allowed; cloning into the working tree is not.
|
|
89
|
+
- Do not investigate the local working-tree codebase to answer external questions - that is the litcodex-explorer's job.
|
|
90
|
+
- Prefer official docs over tutorials, primary sources over aggregators, recent over old.
|
|
91
|
+
- Short quotes only (under 20 words) inside quotation marks; never reproduce long copyrighted passages.
|
|
92
|
+
|
|
93
|
+
# Communication
|
|
94
|
+
- No tool names in prose (say "search GitHub", not "use `gh search code`"). No preamble - answer directly.
|
|
95
|
+
- ALWAYS cite every code claim with a SHA-pinned permalink.
|
|
96
|
+
- Markdown; fence code blocks with a language identifier.
|
|
97
|
+
- Facts over opinions, evidence over speculation; state uncertainty when present.
|
|
98
|
+
"""
|