gaslighting-engine 0.3.1 → 0.4.1

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.
Files changed (194) hide show
  1. package/README.md +133 -18
  2. package/desktop-dist/assets/index-BoI6eWtN.js +44 -0
  3. package/desktop-dist/assets/index-oFTvTTu8.css +1 -0
  4. package/desktop-dist/index.html +13 -0
  5. package/dist/agent-runtimes/permissions.js +34 -0
  6. package/dist/agent-runtimes/prompts.js +30 -0
  7. package/dist/agent-runtimes/registry.js +214 -0
  8. package/dist/agent-runtimes/types.js +1 -0
  9. package/dist/cli.js +142 -4
  10. package/dist/commands/agent.js +11 -0
  11. package/dist/commands/apiRun.js +32 -0
  12. package/dist/commands/cockpit.js +37 -6
  13. package/dist/commands/desktop.js +45 -0
  14. package/dist/commands/doctor.js +8 -1
  15. package/dist/commands/loop.js +64 -0
  16. package/dist/commands/mcp.js +43 -0
  17. package/dist/commands/skill.js +23 -0
  18. package/dist/core/codexRuntime.js +2 -19
  19. package/dist/core/generateDocs.js +16 -10
  20. package/dist/core/generateOtherMarkdown.js +27 -27
  21. package/dist/core/generateStructuredDocs.js +405 -0
  22. package/dist/core/mcpRegistry.js +103 -0
  23. package/dist/core/missionLoop.js +179 -0
  24. package/dist/core/skillRegistry.js +62 -0
  25. package/dist/desktop/main.js +188 -0
  26. package/dist/desktop/preload.js +22 -0
  27. package/dist/utils/logger.js +1 -1
  28. package/dist/version.js +1 -1
  29. package/docs/codex-usage.md +28 -3
  30. package/examples/ecommerce/.agents/config.json +10 -0
  31. package/examples/ecommerce/.agents/mcp/manifest.json +5 -0
  32. package/examples/ecommerce/.agents/runtimes/claude.json +6 -0
  33. package/examples/ecommerce/.agents/runtimes/codex.json +6 -0
  34. package/examples/ecommerce/.agents/runtimes/kimi.json +6 -0
  35. package/examples/ecommerce/.agents/runtimes/local.json +6 -0
  36. package/examples/ecommerce/.agents/runtimes/openai_compatible.json +6 -0
  37. package/examples/ecommerce/.agents/runtimes/opencode.json +6 -0
  38. package/examples/ecommerce/.agents/runtimes/qwen.json +6 -0
  39. package/examples/ecommerce/.codex/prompts/gaslighting.md +9 -9
  40. package/examples/ecommerce/.gaslighting/AGENTS.md +9 -9
  41. package/examples/ecommerce/.gaslighting/AGENT_RUNTIME.md +1 -1
  42. package/examples/ecommerce/.gaslighting/CODEX_PROMPT.md +9 -9
  43. package/examples/ecommerce/.gaslighting/DECISION_LOG.md +1 -1
  44. package/examples/ecommerce/.gaslighting/GASLIGHTING.md +2 -2
  45. package/examples/ecommerce/.gaslighting/INDEX.md +39 -0
  46. package/examples/ecommerce/.gaslighting/MEMORY.md +1 -1
  47. package/examples/ecommerce/.gaslighting/PRD.md +1 -1
  48. package/examples/ecommerce/.gaslighting/PROJECT_CARE.md +1 -1
  49. package/examples/ecommerce/.gaslighting/checkpoints/latest.md +7 -0
  50. package/examples/ecommerce/.gaslighting/config.json +7 -0
  51. package/examples/ecommerce/.gaslighting/decisions/ADR-0001-stack.md +11 -0
  52. package/examples/ecommerce/.gaslighting/decisions/ADR-0002-agent-runtime.md +11 -0
  53. package/examples/ecommerce/.gaslighting/features/core-scope/DECISIONS.md +5 -0
  54. package/examples/ecommerce/.gaslighting/features/core-scope/FEATURE.md +7 -0
  55. package/examples/ecommerce/.gaslighting/features/core-scope/RISKS.md +5 -0
  56. package/examples/ecommerce/.gaslighting/features/core-scope/TASKS.md +18 -0
  57. package/examples/ecommerce/.gaslighting/loops/current-session.json +9 -0
  58. package/examples/ecommerce/.gaslighting/memory/OPEN_QUESTIONS.md +5 -0
  59. package/examples/ecommerce/.gaslighting/memory/PROJECT_MEMORY.md +5 -0
  60. package/examples/ecommerce/.gaslighting/memory/SESSION_LOG.md +3 -0
  61. package/examples/ecommerce/.gaslighting/mission/COMPLETION_STANDARD.md +11 -0
  62. package/examples/ecommerce/.gaslighting/mission/EXECUTION_RULES.md +20 -0
  63. package/examples/ecommerce/.gaslighting/mission/PROJECT_PURPOSE.md +20 -0
  64. package/examples/ecommerce/.gaslighting/operations/DEPLOYMENT.md +6 -0
  65. package/examples/ecommerce/.gaslighting/operations/DOMAIN.md +6 -0
  66. package/examples/ecommerce/.gaslighting/operations/ENV.md +5 -0
  67. package/examples/ecommerce/.gaslighting/operations/GIT.md +7 -0
  68. package/examples/ecommerce/.gaslighting/operations/GITHUB.md +7 -0
  69. package/examples/ecommerce/.gaslighting/operations/PROJECT_CARE.md +76 -0
  70. package/examples/ecommerce/.gaslighting/pages/admin-products/ACCEPTANCE.md +7 -0
  71. package/examples/ecommerce/.gaslighting/pages/admin-products/PAGE_PRD.md +15 -0
  72. package/examples/ecommerce/.gaslighting/pages/cart/ACCEPTANCE.md +7 -0
  73. package/examples/ecommerce/.gaslighting/pages/cart/PAGE_PRD.md +15 -0
  74. package/examples/ecommerce/.gaslighting/pages/checkout/ACCEPTANCE.md +7 -0
  75. package/examples/ecommerce/.gaslighting/pages/checkout/PAGE_PRD.md +15 -0
  76. package/examples/ecommerce/.gaslighting/pages/home/ACCEPTANCE.md +7 -0
  77. package/examples/ecommerce/.gaslighting/pages/home/PAGE_PRD.md +15 -0
  78. package/examples/ecommerce/.gaslighting/pages/my-orders/ACCEPTANCE.md +7 -0
  79. package/examples/ecommerce/.gaslighting/pages/my-orders/PAGE_PRD.md +15 -0
  80. package/examples/ecommerce/.gaslighting/pages/order-complete/ACCEPTANCE.md +7 -0
  81. package/examples/ecommerce/.gaslighting/pages/order-complete/PAGE_PRD.md +15 -0
  82. package/examples/ecommerce/.gaslighting/pages/product-detail/ACCEPTANCE.md +7 -0
  83. package/examples/ecommerce/.gaslighting/pages/product-detail/PAGE_PRD.md +15 -0
  84. package/examples/ecommerce/.gaslighting/pages/product-list/ACCEPTANCE.md +7 -0
  85. package/examples/ecommerce/.gaslighting/pages/product-list/PAGE_PRD.md +15 -0
  86. package/examples/ecommerce/.gaslighting/product/PAGE_MAP.md +11 -0
  87. package/examples/ecommerce/.gaslighting/product/PRD.md +115 -0
  88. package/examples/ecommerce/.gaslighting/product/USER_FLOWS.md +22 -0
  89. package/examples/ecommerce/.gaslighting/tasks/TASK-0001.md +17 -0
  90. package/examples/ecommerce/.gaslighting/verification/latest-report.md +3 -0
  91. package/examples/ecommerce/AGENTS.md +12 -10
  92. package/examples/hospital-homepage/.agents/config.json +10 -0
  93. package/examples/hospital-homepage/.agents/mcp/manifest.json +5 -0
  94. package/examples/hospital-homepage/.agents/runtimes/claude.json +6 -0
  95. package/examples/hospital-homepage/.agents/runtimes/codex.json +6 -0
  96. package/examples/hospital-homepage/.agents/runtimes/kimi.json +6 -0
  97. package/examples/hospital-homepage/.agents/runtimes/local.json +6 -0
  98. package/examples/hospital-homepage/.agents/runtimes/openai_compatible.json +6 -0
  99. package/examples/hospital-homepage/.agents/runtimes/opencode.json +6 -0
  100. package/examples/hospital-homepage/.agents/runtimes/qwen.json +6 -0
  101. package/examples/hospital-homepage/.codex/prompts/gaslighting.md +9 -9
  102. package/examples/hospital-homepage/.gaslighting/AGENTS.md +9 -9
  103. package/examples/hospital-homepage/.gaslighting/CODEX_PROMPT.md +9 -9
  104. package/examples/hospital-homepage/.gaslighting/INDEX.md +37 -0
  105. package/examples/hospital-homepage/.gaslighting/checkpoints/latest.md +7 -0
  106. package/examples/hospital-homepage/.gaslighting/config.json +7 -0
  107. package/examples/hospital-homepage/.gaslighting/decisions/ADR-0001-stack.md +11 -0
  108. package/examples/hospital-homepage/.gaslighting/decisions/ADR-0002-agent-runtime.md +11 -0
  109. package/examples/hospital-homepage/.gaslighting/features/core-scope/DECISIONS.md +5 -0
  110. package/examples/hospital-homepage/.gaslighting/features/core-scope/FEATURE.md +7 -0
  111. package/examples/hospital-homepage/.gaslighting/features/core-scope/RISKS.md +5 -0
  112. package/examples/hospital-homepage/.gaslighting/features/core-scope/TASKS.md +17 -0
  113. package/examples/hospital-homepage/.gaslighting/loops/current-session.json +9 -0
  114. package/examples/hospital-homepage/.gaslighting/memory/OPEN_QUESTIONS.md +5 -0
  115. package/examples/hospital-homepage/.gaslighting/memory/PROJECT_MEMORY.md +5 -0
  116. package/examples/hospital-homepage/.gaslighting/memory/SESSION_LOG.md +3 -0
  117. package/examples/hospital-homepage/.gaslighting/mission/COMPLETION_STANDARD.md +11 -0
  118. package/examples/hospital-homepage/.gaslighting/mission/EXECUTION_RULES.md +20 -0
  119. package/examples/hospital-homepage/.gaslighting/mission/PROJECT_PURPOSE.md +20 -0
  120. package/examples/hospital-homepage/.gaslighting/operations/DEPLOYMENT.md +6 -0
  121. package/examples/hospital-homepage/.gaslighting/operations/DOMAIN.md +6 -0
  122. package/examples/hospital-homepage/.gaslighting/operations/ENV.md +5 -0
  123. package/examples/hospital-homepage/.gaslighting/operations/GIT.md +7 -0
  124. package/examples/hospital-homepage/.gaslighting/operations/GITHUB.md +7 -0
  125. package/examples/hospital-homepage/.gaslighting/operations/PROJECT_CARE.md +76 -0
  126. package/examples/hospital-homepage/.gaslighting/pages/consultation-contact/ACCEPTANCE.md +7 -0
  127. package/examples/hospital-homepage/.gaslighting/pages/consultation-contact/PAGE_PRD.md +15 -0
  128. package/examples/hospital-homepage/.gaslighting/pages/departments-treatments/ACCEPTANCE.md +7 -0
  129. package/examples/hospital-homepage/.gaslighting/pages/departments-treatments/PAGE_PRD.md +15 -0
  130. package/examples/hospital-homepage/.gaslighting/pages/doctor-profiles/ACCEPTANCE.md +7 -0
  131. package/examples/hospital-homepage/.gaslighting/pages/doctor-profiles/PAGE_PRD.md +15 -0
  132. package/examples/hospital-homepage/.gaslighting/pages/home/ACCEPTANCE.md +7 -0
  133. package/examples/hospital-homepage/.gaslighting/pages/home/PAGE_PRD.md +15 -0
  134. package/examples/hospital-homepage/.gaslighting/pages/hospital-introduction/ACCEPTANCE.md +7 -0
  135. package/examples/hospital-homepage/.gaslighting/pages/hospital-introduction/PAGE_PRD.md +15 -0
  136. package/examples/hospital-homepage/.gaslighting/pages/location/ACCEPTANCE.md +7 -0
  137. package/examples/hospital-homepage/.gaslighting/pages/location/PAGE_PRD.md +15 -0
  138. package/examples/hospital-homepage/.gaslighting/pages/privacy-policy/ACCEPTANCE.md +7 -0
  139. package/examples/hospital-homepage/.gaslighting/pages/privacy-policy/PAGE_PRD.md +15 -0
  140. package/examples/hospital-homepage/.gaslighting/product/PAGE_MAP.md +9 -0
  141. package/examples/hospital-homepage/.gaslighting/product/PRD.md +119 -0
  142. package/examples/hospital-homepage/.gaslighting/product/USER_FLOWS.md +20 -0
  143. package/examples/hospital-homepage/.gaslighting/tasks/TASK-0001.md +17 -0
  144. package/examples/hospital-homepage/.gaslighting/verification/latest-report.md +3 -0
  145. package/examples/hospital-homepage/AGENTS.md +12 -10
  146. package/examples/landing-page/.agents/config.json +10 -0
  147. package/examples/landing-page/.agents/mcp/manifest.json +5 -0
  148. package/examples/landing-page/.agents/runtimes/claude.json +6 -0
  149. package/examples/landing-page/.agents/runtimes/codex.json +6 -0
  150. package/examples/landing-page/.agents/runtimes/kimi.json +6 -0
  151. package/examples/landing-page/.agents/runtimes/local.json +6 -0
  152. package/examples/landing-page/.agents/runtimes/openai_compatible.json +6 -0
  153. package/examples/landing-page/.agents/runtimes/opencode.json +6 -0
  154. package/examples/landing-page/.agents/runtimes/qwen.json +6 -0
  155. package/examples/landing-page/.codex/prompts/gaslighting.md +9 -9
  156. package/examples/landing-page/.gaslighting/AGENTS.md +9 -9
  157. package/examples/landing-page/.gaslighting/AGENT_RUNTIME.md +1 -1
  158. package/examples/landing-page/.gaslighting/CODEX_PROMPT.md +9 -9
  159. package/examples/landing-page/.gaslighting/DECISION_LOG.md +1 -1
  160. package/examples/landing-page/.gaslighting/GASLIGHTING.md +2 -2
  161. package/examples/landing-page/.gaslighting/INDEX.md +31 -0
  162. package/examples/landing-page/.gaslighting/MEMORY.md +1 -1
  163. package/examples/landing-page/.gaslighting/PRD.md +1 -1
  164. package/examples/landing-page/.gaslighting/PROJECT_CARE.md +1 -1
  165. package/examples/landing-page/.gaslighting/checkpoints/latest.md +7 -0
  166. package/examples/landing-page/.gaslighting/config.json +7 -0
  167. package/examples/landing-page/.gaslighting/decisions/ADR-0001-stack.md +11 -0
  168. package/examples/landing-page/.gaslighting/decisions/ADR-0002-agent-runtime.md +11 -0
  169. package/examples/landing-page/.gaslighting/features/core-scope/DECISIONS.md +5 -0
  170. package/examples/landing-page/.gaslighting/features/core-scope/FEATURE.md +7 -0
  171. package/examples/landing-page/.gaslighting/features/core-scope/RISKS.md +5 -0
  172. package/examples/landing-page/.gaslighting/features/core-scope/TASKS.md +11 -0
  173. package/examples/landing-page/.gaslighting/loops/current-session.json +9 -0
  174. package/examples/landing-page/.gaslighting/memory/OPEN_QUESTIONS.md +5 -0
  175. package/examples/landing-page/.gaslighting/memory/PROJECT_MEMORY.md +5 -0
  176. package/examples/landing-page/.gaslighting/memory/SESSION_LOG.md +3 -0
  177. package/examples/landing-page/.gaslighting/mission/COMPLETION_STANDARD.md +11 -0
  178. package/examples/landing-page/.gaslighting/mission/EXECUTION_RULES.md +20 -0
  179. package/examples/landing-page/.gaslighting/mission/PROJECT_PURPOSE.md +19 -0
  180. package/examples/landing-page/.gaslighting/operations/DEPLOYMENT.md +6 -0
  181. package/examples/landing-page/.gaslighting/operations/DOMAIN.md +6 -0
  182. package/examples/landing-page/.gaslighting/operations/ENV.md +5 -0
  183. package/examples/landing-page/.gaslighting/operations/GIT.md +7 -0
  184. package/examples/landing-page/.gaslighting/operations/GITHUB.md +7 -0
  185. package/examples/landing-page/.gaslighting/operations/PROJECT_CARE.md +75 -0
  186. package/examples/landing-page/.gaslighting/pages/single-landing-page-with-hero-problem-solution-benefits-social-p/ACCEPTANCE.md +7 -0
  187. package/examples/landing-page/.gaslighting/pages/single-landing-page-with-hero-problem-solution-benefits-social-p/PAGE_PRD.md +15 -0
  188. package/examples/landing-page/.gaslighting/product/PAGE_MAP.md +3 -0
  189. package/examples/landing-page/.gaslighting/product/PRD.md +103 -0
  190. package/examples/landing-page/.gaslighting/product/USER_FLOWS.md +14 -0
  191. package/examples/landing-page/.gaslighting/tasks/TASK-0001.md +17 -0
  192. package/examples/landing-page/.gaslighting/verification/latest-report.md +3 -0
  193. package/examples/landing-page/AGENTS.md +12 -10
  194. package/package.json +22 -5
@@ -0,0 +1,405 @@
1
+ import { pageList, projectPurpose, stackSummary, decisionDate } from "./content.js";
2
+ import { generateProjectCareMarkdown } from "./projectCare.js";
3
+ import { generatePrdMarkdown } from "./generatePrdMarkdown.js";
4
+ export function generateStructuredDocs(input, analysis, root) {
5
+ const pages = pageList(analysis.projectType);
6
+ const purpose = projectPurpose(analysis.projectType);
7
+ const primaryPages = pages.slice(0, 8);
8
+ return [
9
+ { filename: ".gaslighting/config.json", content: gaslightingConfigJson(input) },
10
+ { filename: ".agents/config.json", content: agentsConfigJson(input) },
11
+ { filename: ".agents/runtimes/codex.json", content: runtimeConfig("codex", true, true) },
12
+ { filename: ".agents/runtimes/claude.json", content: runtimeConfig("claude", true, true) },
13
+ { filename: ".agents/runtimes/qwen.json", content: runtimeConfig("qwen", true, false) },
14
+ { filename: ".agents/runtimes/kimi.json", content: runtimeConfig("kimi", true, true) },
15
+ { filename: ".agents/runtimes/opencode.json", content: runtimeConfig("opencode", true, false) },
16
+ { filename: ".agents/runtimes/openai_compatible.json", content: runtimeConfig("openai_compatible", false, false) },
17
+ { filename: ".agents/runtimes/local.json", content: runtimeConfig("local", false, false) },
18
+ { filename: ".agents/mcp/manifest.json", content: mcpManifestJson() },
19
+ { filename: ".gaslighting/INDEX.md", content: indexMarkdown(input, analysis, pages) },
20
+ { filename: ".gaslighting/mission/PROJECT_PURPOSE.md", content: projectPurposeMarkdown(input, analysis, purpose) },
21
+ { filename: ".gaslighting/mission/EXECUTION_RULES.md", content: executionRulesMarkdown(input) },
22
+ { filename: ".gaslighting/mission/COMPLETION_STANDARD.md", content: completionStandardMarkdown() },
23
+ { filename: ".gaslighting/product/PRD.md", content: generatePrdMarkdown(input, analysis) },
24
+ { filename: ".gaslighting/product/USER_FLOWS.md", content: userFlowsMarkdown(analysis, pages) },
25
+ { filename: ".gaslighting/product/PAGE_MAP.md", content: pageMapMarkdown(pages) },
26
+ { filename: ".gaslighting/features/core-scope/FEATURE.md", content: featureMarkdown(input, analysis) },
27
+ { filename: ".gaslighting/features/core-scope/TASKS.md", content: tasksMarkdown(input, analysis, primaryPages) },
28
+ { filename: ".gaslighting/features/core-scope/DECISIONS.md", content: featureDecisionsMarkdown(analysis) },
29
+ { filename: ".gaslighting/features/core-scope/RISKS.md", content: featureRisksMarkdown(analysis) },
30
+ ...primaryPages.flatMap((page) => pageDocs(page, analysis)),
31
+ { filename: ".gaslighting/operations/GIT.md", content: operationGitMarkdown(root) },
32
+ { filename: ".gaslighting/operations/GITHUB.md", content: operationGitHubMarkdown(root) },
33
+ { filename: ".gaslighting/operations/DOMAIN.md", content: operationDomainMarkdown() },
34
+ { filename: ".gaslighting/operations/DEPLOYMENT.md", content: operationDeploymentMarkdown() },
35
+ { filename: ".gaslighting/operations/ENV.md", content: operationEnvMarkdown() },
36
+ { filename: ".gaslighting/decisions/ADR-0001-stack.md", content: adrStackMarkdown(analysis) },
37
+ { filename: ".gaslighting/decisions/ADR-0002-agent-runtime.md", content: adrAgentRuntimeMarkdown(input) },
38
+ { filename: ".gaslighting/tasks/TASK-0001.md", content: firstTaskMarkdown(input, analysis) },
39
+ { filename: ".gaslighting/loops/current-session.json", content: loopSessionJson(input) },
40
+ { filename: ".gaslighting/checkpoints/latest.md", content: checkpointMarkdown(input) },
41
+ { filename: ".gaslighting/verification/latest-report.md", content: verificationReportMarkdown() },
42
+ { filename: ".gaslighting/memory/PROJECT_MEMORY.md", content: projectMemoryMarkdown(input, analysis) },
43
+ { filename: ".gaslighting/memory/SESSION_LOG.md", content: sessionLogMarkdown(input) },
44
+ { filename: ".gaslighting/memory/OPEN_QUESTIONS.md", content: openQuestionsMarkdown(analysis) },
45
+ { filename: ".gaslighting/operations/PROJECT_CARE.md", content: generateProjectCareMarkdown(input, analysis, root) },
46
+ ];
47
+ }
48
+ function gaslightingConfigJson(input) {
49
+ return `${JSON.stringify({
50
+ defaultRuntime: input.runtime ?? "codex",
51
+ loopMode: input.loopMode ?? "off",
52
+ permissionMode: input.permissionMode ?? "auto_review",
53
+ skillSource: ".agents",
54
+ documentLayout: "structured",
55
+ }, null, 2)}\n`;
56
+ }
57
+ function agentsConfigJson(input) {
58
+ return `${JSON.stringify({
59
+ sourceOfTruth: true,
60
+ defaultRuntime: input.runtime ?? "codex",
61
+ permissionMode: input.permissionMode ?? "auto_review",
62
+ exports: [".codex"],
63
+ skillRoot: ".agents/skills",
64
+ mcpRoot: ".agents/mcp",
65
+ }, null, 2)}\n`;
66
+ }
67
+ function runtimeConfig(id, supportsMcp, supportsSkills) {
68
+ return `${JSON.stringify({ id, enabled: id === "codex", supportsMcp, supportsSkills }, null, 2)}\n`;
69
+ }
70
+ function mcpManifestJson() {
71
+ return `${JSON.stringify({ servers: [], installedAt: null, source: ".agents/mcp" }, null, 2)}\n`;
72
+ }
73
+ function indexMarkdown(input, analysis, pages) {
74
+ return `# Gaslighting-engine Index
75
+
76
+ This is the structured source of truth for the project discipline layer.
77
+
78
+ ## Mission
79
+
80
+ - Original request: ${input.rawUserRequest}
81
+ - Project type: ${analysis.projectType}
82
+ - Classification confidence: ${analysis.confidence}
83
+ - Default runtime: ${input.runtime ?? "codex"}
84
+ - Loop mode: ${input.loopMode ?? "off"}
85
+ - Permission mode: ${input.permissionMode ?? "auto_review"}
86
+
87
+ ## Read Order For Agents
88
+
89
+ 1. \`mission/PROJECT_PURPOSE.md\`
90
+ 2. \`mission/EXECUTION_RULES.md\`
91
+ 3. \`mission/COMPLETION_STANDARD.md\`
92
+ 4. \`product/PRD.md\`
93
+ 5. \`product/PAGE_MAP.md\`
94
+ 6. \`features/core-scope/TASKS.md\`
95
+ 7. \`operations/PROJECT_CARE.md\`
96
+ 8. \`loops/current-session.json\`
97
+
98
+ ## Pages
99
+
100
+ ${pages.map((page) => `- ${page}`).join("\n")}
101
+
102
+ ## Compatibility Files
103
+
104
+ Older agents may still read the root compatibility markdown files in \`.gaslighting/\`. Those files remain generated for backward compatibility, but this index is the preferred entrypoint.
105
+ `;
106
+ }
107
+ function projectPurposeMarkdown(input, analysis, purpose) {
108
+ return `# Project Purpose
109
+
110
+ Original request:
111
+
112
+ > ${input.rawUserRequest}
113
+
114
+ Project type: \`${analysis.projectType}\`
115
+
116
+ The purpose is:
117
+
118
+ ${purpose.map((item) => `- ${item}`).join("\n")}
119
+
120
+ Do not turn this project into a generic showcase. Preserve the business purpose and conversion/operation goals implied by the project type.
121
+ `;
122
+ }
123
+ function executionRulesMarkdown(input) {
124
+ return `# Execution Rules
125
+
126
+ - Runtime: ${input.runtime ?? "codex"}
127
+ - Loop mode: ${input.loopMode ?? "off"}
128
+ - Permission mode: ${input.permissionMode ?? "auto_review"}
129
+
130
+ ## Non-Negotiables
131
+
132
+ - Do the actual work.
133
+ - Do not shrink scope.
134
+ - Do not use TODOs as fake implementation.
135
+ - Do not present representative examples as full coverage.
136
+ - Document missing information and continue unless truly blocked.
137
+ - Record operational risk in \`operations/PROJECT_CARE.md\`.
138
+
139
+ ## Permission Modes
140
+
141
+ - \`ask_each_task\`: request approval before each task action.
142
+ - \`auto_review\`: continue ordinary work; request approval for destructive, publishing, deployment, secret, DNS, payment, MCP install, or global configuration changes.
143
+ - \`full_autonomy\`: continue without approval, but log every action and never expose secrets.
144
+ `;
145
+ }
146
+ function completionStandardMarkdown() {
147
+ return `# Completion Standard
148
+
149
+ A task is complete only when:
150
+
151
+ - Requested scope is fully handled.
152
+ - No required item was silently skipped.
153
+ - No placeholder is pretending to be implementation.
154
+ - No TODO replaces requested implementation.
155
+ - Verification was run or the reason it could not run is stated.
156
+ - Assumptions, missing information, and operational care risks are updated.
157
+ - The result can actually be used.
158
+ `;
159
+ }
160
+ function userFlowsMarkdown(analysis, pages) {
161
+ return `# User Flows
162
+
163
+ Project type: \`${analysis.projectType}\`
164
+
165
+ ## Primary Flow
166
+
167
+ 1. User lands on the first relevant page.
168
+ 2. User understands the offer or purpose quickly.
169
+ 3. User explores the page or feature set needed for trust and decision-making.
170
+ 4. User completes the primary conversion or operational action.
171
+
172
+ ## Page Coverage
173
+
174
+ ${pages.map((page, index) => `${index + 1}. ${page}`).join("\n")}
175
+ `;
176
+ }
177
+ function pageMapMarkdown(pages) {
178
+ return `# Page Map
179
+
180
+ ${pages.map((page) => `- [ ] ${page}: define purpose, content, CTA, empty state, and acceptance criteria.`).join("\n")}
181
+ `;
182
+ }
183
+ function featureMarkdown(input, analysis) {
184
+ return `# Core Scope Feature
185
+
186
+ Original request: ${input.rawUserRequest}
187
+
188
+ This feature captures the complete MVP scope for \`${analysis.projectType}\`.
189
+
190
+ The agent must not reduce it to a sample, scaffold, or visual-only shell.
191
+ `;
192
+ }
193
+ function tasksMarkdown(input, analysis, pages) {
194
+ return `# Core Scope Tasks
195
+
196
+ - [ ] Preserve and restate the project purpose for \`${analysis.projectType}\`.
197
+ - [ ] Implement all required MVP pages or feature surfaces.
198
+ ${pages.map((page) => `- [ ] Implement and verify page/surface: ${page}`).join("\n")}
199
+ - [ ] Verify build/test/lint/browser flow as appropriate.
200
+ - [ ] Update decisions, missing info, memory, and project care files.
201
+
202
+ Original request:
203
+
204
+ > ${input.rawUserRequest}
205
+ `;
206
+ }
207
+ function featureDecisionsMarkdown(analysis) {
208
+ return `# Feature Decisions
209
+
210
+ - Project type initialized as \`${analysis.projectType}\`.
211
+ - Deterministic template generation is used instead of an LLM API.
212
+ - Scope preservation is mandatory.
213
+ `;
214
+ }
215
+ function featureRisksMarkdown(analysis) {
216
+ return `# Feature Risks
217
+
218
+ - Classification confidence: ${analysis.confidence}
219
+ - Missing information can affect copy, data model, page details, and production readiness.
220
+ - Repetitive surfaces are at risk of being summarized instead of implemented.
221
+ `;
222
+ }
223
+ function pageDocs(page, analysis) {
224
+ const slug = slugify(page);
225
+ return [
226
+ {
227
+ filename: `.gaslighting/pages/${slug}/PAGE_PRD.md`,
228
+ content: `# ${page} Page PRD
229
+
230
+ Project type: \`${analysis.projectType}\`
231
+
232
+ ## Purpose
233
+
234
+ This page must support the project purpose and not become decorative filler.
235
+
236
+ ## Required Coverage
237
+
238
+ - Clear user goal.
239
+ - Clear content hierarchy.
240
+ - Clear CTA or operational action.
241
+ - Mobile usability.
242
+ - Empty/error states when relevant.
243
+ `,
244
+ },
245
+ {
246
+ filename: `.gaslighting/pages/${slug}/ACCEPTANCE.md`,
247
+ content: `# ${page} Acceptance Criteria
248
+
249
+ - [ ] Page purpose is visible.
250
+ - [ ] Required content is not placeholder-only.
251
+ - [ ] CTA or operational action is usable.
252
+ - [ ] Mobile layout is usable.
253
+ - [ ] No TODO replaces implementation.
254
+ `,
255
+ },
256
+ ];
257
+ }
258
+ function operationGitMarkdown(root) {
259
+ return `# Git Operations
260
+
261
+ Project root: \`${root}\`
262
+
263
+ - Keep meaningful checkpoints.
264
+ - Do not rewrite user changes.
265
+ - Record remote changes in decisions.
266
+ `;
267
+ }
268
+ function operationGitHubMarkdown(root) {
269
+ return `# GitHub Operations
270
+
271
+ Project root: \`${root}\`
272
+
273
+ - If no GitHub remote exists, ask for the GitHub URL and offer to connect it.
274
+ - If a remote exists, preserve it unless the user explicitly asks to replace it.
275
+ - Push only when permission mode allows it or approval is granted.
276
+ `;
277
+ }
278
+ function operationDomainMarkdown() {
279
+ return `# Domain Operations
280
+
281
+ - Production domain: missing until confirmed.
282
+ - DNS provider: missing until confirmed.
283
+ - Domain owner: missing until confirmed.
284
+ - Do not treat missing domain data as implementation-blocking unless launch is requested.
285
+ `;
286
+ }
287
+ function operationDeploymentMarkdown() {
288
+ return `# Deployment Operations
289
+
290
+ - Deployment provider: unconfirmed until detected or selected.
291
+ - Preview URL policy: missing until confirmed.
292
+ - Rollback path: missing until confirmed.
293
+ - Deployment commands require approval in auto-review mode.
294
+ `;
295
+ }
296
+ function operationEnvMarkdown() {
297
+ return `# Environment Operations
298
+
299
+ - Keep real secrets out of generated documents.
300
+ - Prefer \`.env.example\` for required variables.
301
+ - Secret changes require approval in auto-review mode.
302
+ `;
303
+ }
304
+ function adrStackMarkdown(analysis) {
305
+ return `# ADR-0001: Stack Policy
306
+
307
+ Date: ${decisionDate()}
308
+
309
+ ## Decision
310
+
311
+ ${stackSummary(analysis)}
312
+
313
+ ## Consequence
314
+
315
+ The agent must avoid over-engineering and choose technology that serves the project purpose.
316
+ `;
317
+ }
318
+ function adrAgentRuntimeMarkdown(input) {
319
+ return `# ADR-0002: Agent Runtime
320
+
321
+ Date: ${decisionDate()}
322
+
323
+ ## Decision
324
+
325
+ Default runtime is \`${input.runtime ?? "codex"}\`.
326
+
327
+ Loop mode defaults to \`${input.loopMode ?? "off"}\`.
328
+
329
+ Permission mode defaults to \`${input.permissionMode ?? "auto_review"}\`.
330
+ `;
331
+ }
332
+ function firstTaskMarkdown(input, analysis) {
333
+ return `# TASK-0001: Initialize Mission Scope
334
+
335
+ Status: pending
336
+ Runtime: ${input.runtime ?? "codex"}
337
+ Permission mode: ${input.permissionMode ?? "auto_review"}
338
+
339
+ ## Goal
340
+
341
+ Turn the original request into implemented project work without fake completion.
342
+
343
+ ## Request
344
+
345
+ > ${input.rawUserRequest}
346
+
347
+ ## Project Type
348
+
349
+ \`${analysis.projectType}\`
350
+ `;
351
+ }
352
+ function loopSessionJson(input) {
353
+ return `${JSON.stringify({
354
+ active: input.loopMode === "on",
355
+ status: input.loopMode === "on" ? "ready" : "off",
356
+ currentTask: "TASK-0001",
357
+ runtime: input.runtime ?? "codex",
358
+ permissionMode: input.permissionMode ?? "auto_review",
359
+ iterations: 0,
360
+ stopRequested: false,
361
+ }, null, 2)}\n`;
362
+ }
363
+ function checkpointMarkdown(input) {
364
+ return `# Latest Checkpoint
365
+
366
+ No loop iteration has completed yet.
367
+
368
+ Original request:
369
+
370
+ > ${input.rawUserRequest}
371
+ `;
372
+ }
373
+ function verificationReportMarkdown() {
374
+ return `# Latest Verification Report
375
+
376
+ No verification has run yet.
377
+ `;
378
+ }
379
+ function projectMemoryMarkdown(input, analysis) {
380
+ return `# Project Memory
381
+
382
+ - Original request: ${input.rawUserRequest}
383
+ - Project type: ${analysis.projectType}
384
+ - Classification confidence: ${analysis.confidence}
385
+ `;
386
+ }
387
+ function sessionLogMarkdown(input) {
388
+ return `# Session Log
389
+
390
+ - ${decisionDate()}: Gaslighting-engine structured mission initialized for: ${input.rawUserRequest}
391
+ `;
392
+ }
393
+ function openQuestionsMarkdown(analysis) {
394
+ return `# Open Questions
395
+
396
+ ${analysis.missingInfo.map((item) => `- ${item.item}: ${item.recommendedAction}`).join("\n") || "- No open questions recorded yet."}
397
+ `;
398
+ }
399
+ function slugify(value) {
400
+ return value
401
+ .toLowerCase()
402
+ .replace(/[^a-z0-9]+/g, "-")
403
+ .replace(/^-+|-+$/g, "")
404
+ .slice(0, 64) || "page";
405
+ }
@@ -0,0 +1,103 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ const registry = [
4
+ {
5
+ id: "github",
6
+ label: "GitHub",
7
+ description: "Repository, issue, pull request, and code review operations.",
8
+ url: "https://api.githubcopilot.com/mcp/",
9
+ runtimes: ["codex", "claude", "qwen", "opencode"],
10
+ },
11
+ {
12
+ id: "vercel",
13
+ label: "Vercel",
14
+ description: "Deployments, domains, logs, projects, and environment variables.",
15
+ url: "https://mcp.vercel.com",
16
+ runtimes: ["codex", "claude", "qwen", "opencode"],
17
+ },
18
+ {
19
+ id: "postgres",
20
+ label: "PostgreSQL",
21
+ description: "Database schema and readonly query workflows through dbhub.",
22
+ command: "npx",
23
+ args: ["-y", "@bytebase/dbhub"],
24
+ runtimes: ["codex", "claude", "qwen", "opencode"],
25
+ },
26
+ {
27
+ id: "figma",
28
+ label: "Figma",
29
+ description: "Design context and component handoff workflows.",
30
+ url: "https://mcp.figma.com/mcp",
31
+ runtimes: ["codex", "claude", "qwen", "opencode"],
32
+ },
33
+ ];
34
+ export function searchMcpServers(query) {
35
+ const normalized = query.toLowerCase();
36
+ return registry.filter((server) => `${server.id} ${server.label} ${server.description}`.toLowerCase().includes(normalized));
37
+ }
38
+ export function listInstalledMcpServers(root) {
39
+ const manifest = readManifest(root);
40
+ return manifest.servers;
41
+ }
42
+ export function installMcpServer(root, id, runtime) {
43
+ const server = registry.find((item) => item.id === id);
44
+ if (!server)
45
+ return { ok: false, message: `Unknown MCP server: ${id}` };
46
+ const manifest = readManifest(root);
47
+ manifest.servers = [...manifest.servers.filter((item) => item.id !== server.id), server];
48
+ writeJson(join(root, ".agents", "mcp", "manifest.json"), manifest);
49
+ exportMcp(root, server, runtime);
50
+ return { ok: true, message: `Installed ${server.label} MCP definition for ${runtime}.` };
51
+ }
52
+ export function doctorMcp(root) {
53
+ const installed = listInstalledMcpServers(root);
54
+ return [
55
+ {
56
+ ok: existsSync(join(root, ".agents", "mcp", "manifest.json")),
57
+ message: ".agents/mcp/manifest.json exists.",
58
+ },
59
+ {
60
+ ok: installed.length > 0,
61
+ message: installed.length > 0 ? `${installed.length} MCP server definition(s) installed.` : "No MCP servers installed yet.",
62
+ },
63
+ ];
64
+ }
65
+ function exportMcp(root, server, runtime) {
66
+ if (runtime === "codex") {
67
+ const path = join(root, ".codex", "config.toml");
68
+ const body = server.url
69
+ ? `[mcp_servers.${server.id}]\nurl = "${server.url}"\n`
70
+ : `[mcp_servers.${server.id}]\ncommand = "${server.command}"\nargs = [${(server.args ?? []).map((arg) => `"${arg}"`).join(", ")}]\n`;
71
+ appendUnique(path, body, `[mcp_servers.${server.id}]`);
72
+ }
73
+ if (runtime === "claude") {
74
+ const path = join(root, ".mcp.json");
75
+ const existing = existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : { mcpServers: {} };
76
+ existing.mcpServers[server.id] = server.url ? { type: "http", url: server.url } : { command: server.command, args: server.args ?? [] };
77
+ writeJson(path, existing);
78
+ }
79
+ }
80
+ function readManifest(root) {
81
+ const path = join(root, ".agents", "mcp", "manifest.json");
82
+ if (!existsSync(path))
83
+ return { servers: [] };
84
+ try {
85
+ return JSON.parse(readFileSync(path, "utf8"));
86
+ }
87
+ catch {
88
+ return { servers: [] };
89
+ }
90
+ }
91
+ function appendUnique(path, body, marker) {
92
+ const existing = existsSync(path) ? readFileSync(path, "utf8") : "";
93
+ if (existing.includes(marker))
94
+ return;
95
+ writeText(path, `${existing.trimEnd()}\n\n${body}`.trimStart());
96
+ }
97
+ function writeJson(path, data) {
98
+ writeText(path, `${JSON.stringify(data, null, 2)}\n`);
99
+ }
100
+ function writeText(path, content) {
101
+ mkdirSync(dirname(path), { recursive: true });
102
+ writeFileSync(path, content, "utf8");
103
+ }
@@ -0,0 +1,179 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { getAgentRuntimeAdapter } from "../agent-runtimes/registry.js";
5
+ import { reviewPermission } from "../agent-runtimes/permissions.js";
6
+ import { generateDocs } from "./generateDocs.js";
7
+ import { writeDocs } from "../utils/file.js";
8
+ import { decisionDate } from "./content.js";
9
+ const sessionFile = ".gaslighting/loops/current-session.json";
10
+ export function startMissionLoop(options) {
11
+ const request = options.request || "Continue the current Gaslighting mission without shrinking scope.";
12
+ const input = {
13
+ rawUserRequest: request,
14
+ runtime: options.runtime ?? "codex",
15
+ permissionMode: options.permissionMode ?? "auto_review",
16
+ loopMode: "on",
17
+ mode: "hardcore",
18
+ fullScope: true,
19
+ noTodo: true,
20
+ noShortcut: true,
21
+ force: true,
22
+ };
23
+ writeDocs(options.root, generateDocs(input, options.root).docs, true, false);
24
+ const session = {
25
+ active: true,
26
+ status: "ready",
27
+ request,
28
+ currentTask: "TASK-0001",
29
+ runtime: input.runtime ?? "codex",
30
+ permissionMode: input.permissionMode ?? "auto_review",
31
+ loopMode: "on",
32
+ iterations: 0,
33
+ retryCount: 0,
34
+ stopRequested: false,
35
+ lastMessage: "Mission loop started.",
36
+ };
37
+ saveLoopSession(options.root, session);
38
+ return session;
39
+ }
40
+ export function getMissionLoopStatus(root) {
41
+ return readLoopSession(root);
42
+ }
43
+ export function stopMissionLoop(root) {
44
+ const session = readLoopSession(root) ?? defaultStoppedSession();
45
+ session.active = false;
46
+ session.stopRequested = true;
47
+ session.status = "stopped";
48
+ session.lastMessage = "Mission loop stop requested.";
49
+ saveLoopSession(root, session);
50
+ appendSessionLog(root, "Mission loop stopped.");
51
+ return session;
52
+ }
53
+ export function resumeMissionLoop(options) {
54
+ let session = readLoopSession(options.root);
55
+ if (!session) {
56
+ session = startMissionLoop({ ...options, request: options.request || "Continue the current Gaslighting mission." });
57
+ }
58
+ if (session.stopRequested) {
59
+ session.stopRequested = false;
60
+ session.active = true;
61
+ session.status = "ready";
62
+ }
63
+ const maxIterations = Math.max(1, options.maxIterations ?? 1);
64
+ for (let index = 0; index < maxIterations; index += 1) {
65
+ if (!session.active || session.stopRequested)
66
+ break;
67
+ session = runOneIteration(options.root, session, Boolean(options.approve), options.extraArgs);
68
+ if (session.status === "approval_required" || session.status === "failed")
69
+ break;
70
+ }
71
+ saveLoopSession(options.root, session);
72
+ return session;
73
+ }
74
+ function runOneIteration(root, session, approved, extraArgs) {
75
+ const adapter = getAgentRuntimeAdapter(session.runtime);
76
+ const action = adapter.buildCommand({
77
+ root,
78
+ request: `${session.request}\n\nWork only on ${session.currentTask}. Update Gaslighting loop state honestly.`,
79
+ runtime: session.runtime,
80
+ permissionMode: session.permissionMode,
81
+ loopMode: "on",
82
+ extraArgs,
83
+ });
84
+ const review = reviewPermission(session.permissionMode, action);
85
+ if (review.requiresApproval && !approved) {
86
+ return {
87
+ ...session,
88
+ status: "approval_required",
89
+ lastMessage: review.reason,
90
+ };
91
+ }
92
+ const spawnInput = adapter.buildSpawn({
93
+ root,
94
+ request: `${session.request}\n\nWork only on ${session.currentTask}. Update Gaslighting loop state honestly.`,
95
+ runtime: session.runtime,
96
+ permissionMode: session.permissionMode,
97
+ loopMode: "on",
98
+ extraArgs,
99
+ });
100
+ saveLoopSession(root, { ...session, status: "running", lastMessage: `Running ${session.currentTask} with ${adapter.label}.` });
101
+ const startedAt = new Date().toISOString();
102
+ const result = spawnSync(spawnInput.file, spawnInput.args, { cwd: spawnInput.cwd, encoding: "utf8", stdio: "pipe" });
103
+ const endedAt = new Date().toISOString();
104
+ const ok = result.status === 0;
105
+ const nextSession = {
106
+ ...session,
107
+ iterations: session.iterations + 1,
108
+ retryCount: ok ? 0 : session.retryCount + 1,
109
+ status: ok ? "ready" : "failed",
110
+ lastMessage: ok ? `${session.currentTask} iteration completed. Verification still required before claiming done.` : `${session.currentTask} iteration failed.`,
111
+ };
112
+ writeIteration(root, nextSession.iterations, {
113
+ task: session.currentTask,
114
+ runtime: session.runtime,
115
+ command: action,
116
+ startedAt,
117
+ endedAt,
118
+ exitCode: result.status,
119
+ stdout: redact(result.stdout ?? ""),
120
+ stderr: redact(result.stderr ?? ""),
121
+ });
122
+ writeVerification(root, ok, nextSession.lastMessage ?? "");
123
+ appendSessionLog(root, nextSession.lastMessage ?? "Loop iteration completed.");
124
+ return nextSession;
125
+ }
126
+ function readLoopSession(root) {
127
+ const path = join(root, sessionFile);
128
+ if (!existsSync(path))
129
+ return undefined;
130
+ return JSON.parse(readFileSync(path, "utf8"));
131
+ }
132
+ function saveLoopSession(root, session) {
133
+ writeJson(join(root, sessionFile), session);
134
+ }
135
+ function writeIteration(root, iteration, data) {
136
+ writeJson(join(root, ".gaslighting", "loops", "iterations", `${String(iteration).padStart(4, "0")}.json`), data);
137
+ }
138
+ function writeVerification(root, ok, message) {
139
+ writeText(join(root, ".gaslighting", "verification", "latest-report.md"), `# Latest Verification Report
140
+
141
+ - Date: ${decisionDate()}
142
+ - Status: ${ok ? "pass" : "fail"}
143
+ - Message: ${message}
144
+
145
+ Loop verification confirms process exit only. The agent must still run project-specific build, test, lint, and browser checks before declaring final completion.
146
+ `);
147
+ }
148
+ function appendSessionLog(root, message) {
149
+ const path = join(root, ".gaslighting", "memory", "SESSION_LOG.md");
150
+ const existing = existsSync(path) ? readFileSync(path, "utf8") : "# Session Log\n";
151
+ writeText(path, `${existing.trimEnd()}\n- ${decisionDate()}: ${message}\n`);
152
+ }
153
+ function writeJson(path, data) {
154
+ writeText(path, `${JSON.stringify(data, null, 2)}\n`);
155
+ }
156
+ function writeText(path, content) {
157
+ mkdirSync(dirname(path), { recursive: true });
158
+ writeFileSync(path, content, "utf8");
159
+ }
160
+ function defaultStoppedSession() {
161
+ return {
162
+ active: false,
163
+ status: "stopped",
164
+ request: "No loop session exists.",
165
+ currentTask: "TASK-0001",
166
+ runtime: "codex",
167
+ permissionMode: "auto_review",
168
+ loopMode: "off",
169
+ iterations: 0,
170
+ retryCount: 0,
171
+ stopRequested: true,
172
+ };
173
+ }
174
+ function redact(value) {
175
+ return value
176
+ .replace(/npm_[A-Za-z0-9]+/g, "[REDACTED_NPM_TOKEN]")
177
+ .replace(/sk-[A-Za-z0-9_-]+/g, "[REDACTED_API_KEY]")
178
+ .slice(0, 20_000);
179
+ }