gaslighting-engine 0.2.2 → 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/.agents/prompts/gaslighting.md +2 -1
- package/.agents/skills/gaslighting/SKILL.md +4 -1
- package/.codex/prompts/gaslighting.md +2 -1
- package/.codex/skills/gaslighting/SKILL.md +4 -1
- package/README.md +36 -1
- package/dist/cli.js +38 -1
- package/dist/commands/cockpit.js +174 -0
- package/dist/commands/doctor.js +1 -0
- package/dist/core/cockpitHtml.js +596 -0
- package/dist/core/codexRuntime.js +74 -0
- package/dist/core/generateDocs.js +5 -3
- package/dist/core/generateOtherMarkdown.js +68 -4
- package/dist/index.js +1 -1
- package/dist/utils/logger.js +1 -1
- package/dist/version.js +1 -1
- package/docs/codex-usage.md +16 -4
- package/docs/examples.md +3 -0
- package/examples/ecommerce/.codex/prompts/gaslighting.md +2 -1
- package/examples/ecommerce/.codex/skills/gaslighting/SKILL.md +4 -1
- package/examples/ecommerce/.gaslighting/AGENTS.md +3 -1
- package/examples/ecommerce/.gaslighting/AGENT_RUNTIME.md +54 -0
- package/examples/ecommerce/.gaslighting/CODEX_PROMPT.md +2 -1
- package/examples/ecommerce/AGENTS.md +3 -2
- package/examples/hospital-homepage/.codex/prompts/gaslighting.md +2 -1
- package/examples/hospital-homepage/.codex/skills/gaslighting/SKILL.md +4 -1
- package/examples/hospital-homepage/.gaslighting/AGENTS.md +3 -1
- package/examples/hospital-homepage/.gaslighting/AGENT_RUNTIME.md +54 -0
- package/examples/hospital-homepage/.gaslighting/CODEX_PROMPT.md +2 -1
- package/examples/hospital-homepage/AGENTS.md +3 -2
- package/examples/landing-page/.codex/prompts/gaslighting.md +2 -1
- package/examples/landing-page/.codex/skills/gaslighting/SKILL.md +4 -1
- package/examples/landing-page/.gaslighting/AGENTS.md +3 -1
- package/examples/landing-page/.gaslighting/AGENT_RUNTIME.md +54 -0
- package/examples/landing-page/.gaslighting/CODEX_PROMPT.md +2 -1
- package/examples/landing-page/AGENTS.md +3 -2
- package/package.json +1 -1
|
@@ -10,7 +10,8 @@ Read the Gaslighting-engine project-control files before doing any work:
|
|
|
10
10
|
6. `.gaslighting/DECISION_LOG.md`
|
|
11
11
|
7. `AGENTS.md`
|
|
12
12
|
8. `.gaslighting/MEMORY.md`
|
|
13
|
-
9. `.gaslighting/
|
|
13
|
+
9. `.gaslighting/AGENT_RUNTIME.md`
|
|
14
|
+
10. `.gaslighting/PROJECT_CARE.md`
|
|
14
15
|
|
|
15
16
|
Then execute the user's requested implementation.
|
|
16
17
|
|
|
@@ -23,7 +23,8 @@ Instead:
|
|
|
23
23
|
10. Generate `.gaslighting/DECISION_LOG.md`.
|
|
24
24
|
11. Generate `.gaslighting/STACK_POLICY.md`.
|
|
25
25
|
12. Generate or update root `AGENTS.md`.
|
|
26
|
-
13. Generate `.gaslighting/
|
|
26
|
+
13. Generate `.gaslighting/AGENT_RUNTIME.md`.
|
|
27
|
+
14. Generate `.gaslighting/PROJECT_CARE.md`.
|
|
27
28
|
|
|
28
29
|
## Hardcore Discipline Rule
|
|
29
30
|
|
|
@@ -92,6 +93,8 @@ Keep main project-control files in `.gaslighting/` and keep only the Codex point
|
|
|
92
93
|
|
|
93
94
|
Use `.gaslighting/PROJECT_CARE.md` to track Git/GitHub/domain/deployment/launch risks without blocking implementation.
|
|
94
95
|
|
|
96
|
+
Use `.gaslighting/AGENT_RUNTIME.md` to define the execution loop Codex must follow after the docs are generated.
|
|
97
|
+
|
|
95
98
|
Do not only explain.
|
|
96
99
|
|
|
97
100
|
Do not produce a plan without files.
|
|
@@ -10,7 +10,8 @@ Read the Gaslighting-engine project-control files before doing any work:
|
|
|
10
10
|
6. `.gaslighting/DECISION_LOG.md`
|
|
11
11
|
7. `AGENTS.md`
|
|
12
12
|
8. `.gaslighting/MEMORY.md`
|
|
13
|
-
9. `.gaslighting/
|
|
13
|
+
9. `.gaslighting/AGENT_RUNTIME.md`
|
|
14
|
+
10. `.gaslighting/PROJECT_CARE.md`
|
|
14
15
|
|
|
15
16
|
Then execute the user's requested implementation.
|
|
16
17
|
|
|
@@ -23,7 +23,8 @@ Instead:
|
|
|
23
23
|
10. Generate `.gaslighting/DECISION_LOG.md`.
|
|
24
24
|
11. Generate `.gaslighting/STACK_POLICY.md`.
|
|
25
25
|
12. Generate or update root `AGENTS.md`.
|
|
26
|
-
13. Generate `.gaslighting/
|
|
26
|
+
13. Generate `.gaslighting/AGENT_RUNTIME.md`.
|
|
27
|
+
14. Generate `.gaslighting/PROJECT_CARE.md`.
|
|
27
28
|
|
|
28
29
|
## Hardcore Discipline Rule
|
|
29
30
|
|
|
@@ -92,6 +93,8 @@ Keep main project-control files in `.gaslighting/` and keep only the Codex point
|
|
|
92
93
|
|
|
93
94
|
Use `.gaslighting/PROJECT_CARE.md` to track Git/GitHub/domain/deployment/launch risks without blocking implementation.
|
|
94
95
|
|
|
96
|
+
Use `.gaslighting/AGENT_RUNTIME.md` to define the execution loop Codex must follow after the docs are generated.
|
|
97
|
+
|
|
95
98
|
Do not only explain.
|
|
96
99
|
|
|
97
100
|
Do not produce a plan without files.
|
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@ It generates:
|
|
|
30
30
|
- `.gaslighting/MISSING_INFO.md`
|
|
31
31
|
- `.gaslighting/DECISION_LOG.md`
|
|
32
32
|
- `.gaslighting/MEMORY.md`
|
|
33
|
+
- `.gaslighting/AGENT_RUNTIME.md`
|
|
33
34
|
- `.gaslighting/STACK_POLICY.md`
|
|
34
35
|
- `.gaslighting/PROJECT_CARE.md`
|
|
35
36
|
- `AGENTS.md`
|
|
@@ -40,9 +41,11 @@ It generates:
|
|
|
40
41
|
## Quick Start
|
|
41
42
|
|
|
42
43
|
```bash
|
|
43
|
-
npx gaslighting-engine "I want to build a hospital website."
|
|
44
|
+
npx gaslighting-engine@latest start "I want to build a hospital website."
|
|
44
45
|
```
|
|
45
46
|
|
|
47
|
+
This generates the discipline documents, opens the local Mission Control GUI, and prepares a Codex launch command.
|
|
48
|
+
|
|
46
49
|
Short aliases after global install or local link:
|
|
47
50
|
|
|
48
51
|
```bash
|
|
@@ -84,6 +87,9 @@ gaslighting init "I want to build a hospital website."
|
|
|
84
87
|
gaslighting-engine generate "Build an ecommerce MVP."
|
|
85
88
|
gaslighting-engine update "The hospital is actually an OB-GYN clinic, not dermatology."
|
|
86
89
|
gaslighting-engine doctor
|
|
90
|
+
gaslighting-engine start "Build a hospital homepage"
|
|
91
|
+
gaslighting-engine cockpit
|
|
92
|
+
gaslighting-engine run "Build a hospital homepage"
|
|
87
93
|
gaslighting-engine upgrade
|
|
88
94
|
gaslighting-engine codex-install
|
|
89
95
|
gaslighting-engine codex-doctor
|
|
@@ -99,6 +105,35 @@ Gaslighting-engine keeps project-control documents in `.gaslighting/` by default
|
|
|
99
105
|
|
|
100
106
|
Only root `AGENTS.md` is written at the top level because Codex expects project guidance there. It is a thin pointer into `.gaslighting/`.
|
|
101
107
|
|
|
108
|
+
## Mission Control
|
|
109
|
+
|
|
110
|
+
Mission Control is the Codex-first GUI agent surface:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx gaslighting-engine@latest start "I want to build a hospital website."
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
It shows:
|
|
117
|
+
|
|
118
|
+
- project purpose
|
|
119
|
+
- generated control documents
|
|
120
|
+
- missing information
|
|
121
|
+
- Git/GitHub and deployment care checks
|
|
122
|
+
- Codex runtime args
|
|
123
|
+
- Start Codex action
|
|
124
|
+
|
|
125
|
+
Open it for an existing project:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx gaslighting-engine@latest cockpit
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Run without the GUI:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npx gaslighting-engine@latest run "I want to build a hospital website."
|
|
135
|
+
```
|
|
136
|
+
|
|
102
137
|
## Project Care
|
|
103
138
|
|
|
104
139
|
Gaslighting-engine also writes `.gaslighting/PROJECT_CARE.md`.
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command, InvalidArgumentError } from "commander";
|
|
2
2
|
import { runAgents } from "./commands/agents.js";
|
|
3
3
|
import { runCare } from "./commands/care.js";
|
|
4
|
+
import { runCockpit, runCodexRun, runStart } from "./commands/cockpit.js";
|
|
4
5
|
import { runCodexDoctor, runCodexInstall } from "./commands/codexInstall.js";
|
|
5
6
|
import { runDoctor } from "./commands/doctor.js";
|
|
6
7
|
import { runGenerate } from "./commands/generate.js";
|
|
@@ -60,6 +61,7 @@ Examples:
|
|
|
60
61
|
$ gaslighting-engine init "Build a landing page" --dry-run
|
|
61
62
|
$ gaslighting-engine doctor
|
|
62
63
|
$ gaslighting-engine care --github-url https://github.com/user/repo.git
|
|
64
|
+
$ gaslighting-engine start "Build a hospital homepage"
|
|
63
65
|
$ gaslighting-engine upgrade
|
|
64
66
|
$ gaslighting-engine codex-install --force
|
|
65
67
|
|
|
@@ -104,6 +106,41 @@ Defaults:
|
|
|
104
106
|
.option("--github-url <url>", "initialize git if needed and connect origin to this GitHub URL")
|
|
105
107
|
.option("--force-remote", "replace an existing origin remote when used with --github-url")
|
|
106
108
|
.action(runCare);
|
|
109
|
+
program
|
|
110
|
+
.command("start <request>")
|
|
111
|
+
.description("Generate discipline docs, open Mission Control, and prepare Codex launch")
|
|
112
|
+
.option("--force", "overwrite existing files")
|
|
113
|
+
.option("--no-force", "preserve existing files and create .new variants instead")
|
|
114
|
+
.option("--no-open", "print the Mission Control URL without opening a browser")
|
|
115
|
+
.option("--port <port>", "Mission Control port, random by default")
|
|
116
|
+
.option("--path <path>", "target directory")
|
|
117
|
+
.option("--lang <lang>", "language: en or ko", "en")
|
|
118
|
+
.option("--type <type>", "project type override", parseProjectType)
|
|
119
|
+
.option("--codex-args <args>", "Codex CLI args used by the Start Codex button")
|
|
120
|
+
.action(runStart);
|
|
121
|
+
program
|
|
122
|
+
.command("cockpit [request]")
|
|
123
|
+
.description("Open the local Gaslighting Mission Control GUI")
|
|
124
|
+
.option("--no-generate", "open without regenerating discipline docs")
|
|
125
|
+
.option("--force", "overwrite existing files")
|
|
126
|
+
.option("--no-force", "preserve existing files and create .new variants instead")
|
|
127
|
+
.option("--no-open", "print the Mission Control URL without opening a browser")
|
|
128
|
+
.option("--port <port>", "Mission Control port, random by default")
|
|
129
|
+
.option("--path <path>", "target directory")
|
|
130
|
+
.option("--lang <lang>", "language: en or ko", "en")
|
|
131
|
+
.option("--type <type>", "project type override", parseProjectType)
|
|
132
|
+
.option("--codex-args <args>", "Codex CLI args used by the Start Codex button")
|
|
133
|
+
.action(runCockpit);
|
|
134
|
+
program
|
|
135
|
+
.command("run <request>")
|
|
136
|
+
.description("Generate discipline docs and launch Codex without opening the GUI")
|
|
137
|
+
.option("--force", "overwrite existing files")
|
|
138
|
+
.option("--no-force", "preserve existing files and create .new variants instead")
|
|
139
|
+
.option("--path <path>", "target directory")
|
|
140
|
+
.option("--lang <lang>", "language: en or ko", "en")
|
|
141
|
+
.option("--type <type>", "project type override", parseProjectType)
|
|
142
|
+
.option("--codex-args <args>", "Codex CLI args")
|
|
143
|
+
.action(runCodexRun);
|
|
107
144
|
program
|
|
108
145
|
.command("upgrade")
|
|
109
146
|
.description("Update the local Codex Gaslighting install with one simple command")
|
|
@@ -134,7 +171,7 @@ export function normalizeDefaultInitArgv(argv) {
|
|
|
134
171
|
return argv;
|
|
135
172
|
if (args.some((arg) => ["--help", "-h", "--version", "-V"].includes(arg)))
|
|
136
173
|
return argv;
|
|
137
|
-
const commands = new Set(["init", "generate", "update", "doctor", "skill", "agents", "care", "upgrade", "codex-install", "codex-doctor"]);
|
|
174
|
+
const commands = new Set(["init", "generate", "update", "doctor", "skill", "agents", "care", "start", "cockpit", "run", "upgrade", "codex-install", "codex-doctor"]);
|
|
138
175
|
const firstMeaningful = args.find((arg) => !arg.startsWith("-"));
|
|
139
176
|
if (firstMeaningful && commands.has(firstMeaningful))
|
|
140
177
|
return argv;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { platform } from "node:os";
|
|
6
|
+
import { analyze } from "../core/analyze.js";
|
|
7
|
+
import { getDefaultCodexArgs, launchCodex } from "../core/codexRuntime.js";
|
|
8
|
+
import { pageList, projectPurpose } from "../core/content.js";
|
|
9
|
+
import { generateCodexInstallDocs, generateDocs, generateProjectCareDoc } from "../core/generateDocs.js";
|
|
10
|
+
import { renderCockpitHtml } from "../core/cockpitHtml.js";
|
|
11
|
+
import { connectGitHubRemote, inspectProjectCare } from "../core/projectCare.js";
|
|
12
|
+
import { printBanner } from "../utils/banner.js";
|
|
13
|
+
import { writeDocs } from "../utils/file.js";
|
|
14
|
+
import { packageVersion } from "../version.js";
|
|
15
|
+
const docFiles = [
|
|
16
|
+
"AGENTS.md",
|
|
17
|
+
".gaslighting/GASLIGHTING.md",
|
|
18
|
+
".gaslighting/PRD.md",
|
|
19
|
+
".gaslighting/MISSING_INFO.md",
|
|
20
|
+
".gaslighting/ASSUMPTIONS.md",
|
|
21
|
+
".gaslighting/DECISION_LOG.md",
|
|
22
|
+
".gaslighting/MEMORY.md",
|
|
23
|
+
".gaslighting/AGENT_RUNTIME.md",
|
|
24
|
+
".gaslighting/PROJECT_CARE.md",
|
|
25
|
+
];
|
|
26
|
+
export async function runCockpit(rawUserRequest = "", options) {
|
|
27
|
+
await openCockpit(rawUserRequest, { ...options, generate: Boolean(rawUserRequest) && options.generate !== false, force: options.force ?? true });
|
|
28
|
+
}
|
|
29
|
+
export async function runStart(rawUserRequest, options) {
|
|
30
|
+
await openCockpit(rawUserRequest, { ...options, generate: true, force: options.force ?? true });
|
|
31
|
+
}
|
|
32
|
+
export function runCodexRun(rawUserRequest, options) {
|
|
33
|
+
const root = resolve(options.path ?? process.cwd());
|
|
34
|
+
const input = makeInput(rawUserRequest, options);
|
|
35
|
+
writeDocs(root, generateDocs(input, root).docs, options.force ?? true, false);
|
|
36
|
+
writeDocs(root, generateCodexInstallDocs(), true, false);
|
|
37
|
+
const result = launchCodex({ root, request: rawUserRequest, codexArgs: options.codexArgs });
|
|
38
|
+
printBanner("CODEX RUN");
|
|
39
|
+
console.log(result.message);
|
|
40
|
+
console.log(result.command);
|
|
41
|
+
}
|
|
42
|
+
async function openCockpit(rawUserRequest, options) {
|
|
43
|
+
const root = resolve(options.path ?? process.cwd());
|
|
44
|
+
let currentRequest = rawUserRequest || readExistingRequest(root) || "Build a practical MVP without shrinking scope.";
|
|
45
|
+
let currentInput = makeInput(currentRequest, options);
|
|
46
|
+
if (options.generate) {
|
|
47
|
+
writeDocs(root, generateDocs(currentInput, root).docs, options.force ?? true, false);
|
|
48
|
+
writeDocs(root, generateCodexInstallDocs(), true, false);
|
|
49
|
+
}
|
|
50
|
+
const requestedPort = Number.parseInt(options.port ?? "0", 10);
|
|
51
|
+
const server = createServer(async (request, response) => {
|
|
52
|
+
try {
|
|
53
|
+
if (request.method === "GET" && request.url === "/")
|
|
54
|
+
return sendHtml(response, renderCockpitHtml());
|
|
55
|
+
if (request.method === "GET" && request.url === "/api/state")
|
|
56
|
+
return sendJson(response, buildState(root, currentRequest, currentInput, options));
|
|
57
|
+
if (request.method === "POST" && request.url === "/api/generate") {
|
|
58
|
+
const body = await readJson(request);
|
|
59
|
+
currentRequest = String(body.request || currentRequest);
|
|
60
|
+
currentInput = makeInput(currentRequest, options);
|
|
61
|
+
writeDocs(root, generateDocs(currentInput, root).docs, true, false);
|
|
62
|
+
return sendJson(response, { state: buildState(root, currentRequest, currentInput, options) });
|
|
63
|
+
}
|
|
64
|
+
if (request.method === "POST" && request.url === "/api/start-codex") {
|
|
65
|
+
const body = await readJson(request);
|
|
66
|
+
currentRequest = String(body.request || currentRequest);
|
|
67
|
+
currentInput = makeInput(currentRequest, options);
|
|
68
|
+
writeDocs(root, generateDocs(currentInput, root).docs, true, false);
|
|
69
|
+
const result = launchCodex({ root, request: currentRequest, codexArgs: options.codexArgs });
|
|
70
|
+
return sendJson(response, { ...result });
|
|
71
|
+
}
|
|
72
|
+
if (request.method === "POST" && request.url === "/api/connect-github") {
|
|
73
|
+
const body = await readJson(request);
|
|
74
|
+
const githubUrl = String(body.githubUrl || "");
|
|
75
|
+
const results = connectGitHubRemote(root, githubUrl, Boolean(body.forceRemote));
|
|
76
|
+
writeDocs(root, generateProjectCareDoc(currentInput, root), true, false);
|
|
77
|
+
return sendJson(response, { results, state: buildState(root, currentRequest, currentInput, options) });
|
|
78
|
+
}
|
|
79
|
+
sendJson(response, { message: "Not found." }, 404);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : "Unknown cockpit error.";
|
|
83
|
+
sendJson(response, { message }, 500);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
await new Promise((resolveListen) => server.listen(requestedPort, "127.0.0.1", resolveListen));
|
|
87
|
+
const address = server.address();
|
|
88
|
+
const port = typeof address === "object" && address ? address.port : requestedPort;
|
|
89
|
+
const url = `http://127.0.0.1:${port}`;
|
|
90
|
+
printBanner("MISSION CONTROL");
|
|
91
|
+
console.log(`Project: ${currentRequest}`);
|
|
92
|
+
console.log(`Root: ${root}`);
|
|
93
|
+
console.log(`URL: ${url}`);
|
|
94
|
+
console.log("Close this terminal session to stop the cockpit.");
|
|
95
|
+
if (options.open !== false)
|
|
96
|
+
openBrowser(url);
|
|
97
|
+
}
|
|
98
|
+
function buildState(root, request, input, options) {
|
|
99
|
+
const analysis = analyze(input);
|
|
100
|
+
const docsPresent = Object.fromEntries(docFiles.map((file) => [file, existsSync(join(root, file))]));
|
|
101
|
+
return {
|
|
102
|
+
version: packageVersion,
|
|
103
|
+
root,
|
|
104
|
+
request,
|
|
105
|
+
analysis,
|
|
106
|
+
purpose: projectPurpose(analysis.projectType),
|
|
107
|
+
pages: pageList(analysis.projectType),
|
|
108
|
+
care: inspectProjectCare(root),
|
|
109
|
+
docsPresent,
|
|
110
|
+
codexArgs: options.codexArgs || getDefaultCodexArgs(),
|
|
111
|
+
codexAvailable: isCommandAvailable("codex"),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function makeInput(rawUserRequest, options) {
|
|
115
|
+
return {
|
|
116
|
+
rawUserRequest,
|
|
117
|
+
projectType: options.type,
|
|
118
|
+
language: options.lang ?? "en",
|
|
119
|
+
mode: "hardcore",
|
|
120
|
+
fullScope: true,
|
|
121
|
+
noTodo: true,
|
|
122
|
+
noShortcut: true,
|
|
123
|
+
force: options.force ?? true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function readExistingRequest(root) {
|
|
127
|
+
const carePath = join(root, ".gaslighting", "PROJECT_CARE.md");
|
|
128
|
+
if (!existsSync(carePath))
|
|
129
|
+
return undefined;
|
|
130
|
+
const content = readFileSync(carePath, "utf8");
|
|
131
|
+
return /^- Original request: (.+)$/m.exec(content)?.[1];
|
|
132
|
+
}
|
|
133
|
+
function isCommandAvailable(command) {
|
|
134
|
+
try {
|
|
135
|
+
if (platform() === "win32")
|
|
136
|
+
execFileSync("where", [command], { stdio: "ignore" });
|
|
137
|
+
else
|
|
138
|
+
execFileSync("sh", ["-lc", `command -v ${command}`], { stdio: "ignore" });
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function openBrowser(url) {
|
|
146
|
+
const command = platform() === "win32"
|
|
147
|
+
? { file: "cmd.exe", args: ["/c", "start", "", url] }
|
|
148
|
+
: platform() === "darwin"
|
|
149
|
+
? { file: "open", args: [url] }
|
|
150
|
+
: { file: "xdg-open", args: [url] };
|
|
151
|
+
try {
|
|
152
|
+
const child = spawn(command.file, command.args, { detached: true, stdio: "ignore" });
|
|
153
|
+
child.unref();
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// The printed URL is the fallback.
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function readJson(request) {
|
|
160
|
+
const chunks = [];
|
|
161
|
+
for await (const chunk of request)
|
|
162
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
163
|
+
if (chunks.length === 0)
|
|
164
|
+
return {};
|
|
165
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
166
|
+
}
|
|
167
|
+
function sendHtml(response, html) {
|
|
168
|
+
response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
169
|
+
response.end(html);
|
|
170
|
+
}
|
|
171
|
+
function sendJson(response, data, status = 200) {
|
|
172
|
+
response.writeHead(status, { "content-type": "application/json; charset=utf-8" });
|
|
173
|
+
response.end(JSON.stringify(data));
|
|
174
|
+
}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -18,6 +18,7 @@ export function runDoctor(options) {
|
|
|
18
18
|
fileCheck(root, ".gaslighting/MISSING_INFO.md"),
|
|
19
19
|
fileCheck(root, ".gaslighting/DECISION_LOG.md"),
|
|
20
20
|
fileCheck(root, ".gaslighting/MEMORY.md"),
|
|
21
|
+
fileCheck(root, ".gaslighting/AGENT_RUNTIME.md"),
|
|
21
22
|
fileCheck(root, ".gaslighting/PROJECT_CARE.md"),
|
|
22
23
|
{ name: ".gaslighting/GASLIGHTING.md contains project purpose", ok: /Project Purpose/i.test(gaslighting) },
|
|
23
24
|
{ name: ".gaslighting/GASLIGHTING.md contains no-fake-completion rules", ok: /No Fake Completion|Fake completion/i.test(gaslighting) },
|