codex-genesis-harness 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codebase/ARCHITECTURE_REVIEW_COMPLETE.md +216 -216
- package/.codebase/CURRENT_STATE.md +8 -2
- package/.codebase/FILE_NAMING_CLARIFICATION.md +161 -161
- package/.codebase/HARNESS_COMPLETENESS_AUDIT.md +613 -613
- package/.codebase/IMPLEMENTATION_COMPLETE.md +429 -429
- package/.codebase/IMPLEMENTATION_HANDOFF.md +351 -351
- package/.codebase/IMPROVEMENTS_SUMMARY.md +419 -419
- package/.codebase/PHASE3_SKILLS_NAMING_COMPLETE.md +292 -292
- package/.codebase/PHASE_DEPENDENCY_MAP.md +486 -486
- package/.codebase/QUICK_START_SPEC_IMPACT.md +456 -456
- package/.codebase/README.md +139 -139
- package/.codebase/RECOVERY_POINTS.md +83 -438
- package/.codebase/beads.json +16 -0
- package/.codex/skills/genesis-ai-provider/SKILL.md +1 -1
- package/.codex/skills/genesis-api-contract/SKILL.md +1 -1
- package/.codex/skills/genesis-api-sync/SKILL.md +354 -354
- package/.codex/skills/genesis-api-sync/checklists/api-sync-checklist.md +101 -101
- package/.codex/skills/genesis-api-sync/templates/api-change-template.md +257 -257
- package/.codex/skills/genesis-architecture/SKILL.md +1 -1
- package/.codex/skills/genesis-codebase-map/SKILL.md +1 -1
- package/.codex/skills/genesis-debug-guide/SKILL.md +479 -479
- package/.codex/skills/genesis-debug-guide/checklists/flaky-test-investigation.md +339 -339
- package/.codex/skills/genesis-debug-guide/checklists/production-bug-debug.md +210 -210
- package/.codex/skills/genesis-debug-guide/checklists/test-failure-debug.md +158 -158
- package/.codex/skills/genesis-debug-guide/observability/debug-commands.md +365 -365
- package/.codex/skills/genesis-debug-guide/playbooks/unit-test-failures.md +289 -289
- package/.codex/skills/genesis-debug-guide/templates/debug-investigation-log.md +288 -288
- package/.codex/skills/genesis-design-spec/SKILL.md +3 -3
- package/.codex/skills/genesis-docs-automation/SKILL.md +1003 -1003
- package/.codex/skills/genesis-docs-automation/checklists/docs-validation.md +359 -359
- package/.codex/skills/genesis-docs-automation/checklists/spec-alignment.md +312 -312
- package/.codex/skills/genesis-docs-automation/observability/docs-tracking.md +382 -382
- package/.codex/skills/genesis-docs-automation/playbooks/auto-update-flow.md +851 -851
- package/.codex/skills/genesis-docs-automation/playbooks/changelog-generation.md +491 -491
- package/.codex/skills/genesis-docs-automation/templates/changelog-entry-template.md +187 -187
- package/.codex/skills/genesis-docs-automation/templates/handoff-template.md +297 -297
- package/.codex/skills/genesis-harness/SKILL.md +1428 -1427
- package/.codex/skills/genesis-harness/agents/openai.yaml +7 -7
- package/.codex/skills/genesis-harness/checklists/bug-fix-qa.md +169 -169
- package/.codex/skills/genesis-harness/checklists/new-feature-qa.md +157 -157
- package/.codex/skills/genesis-harness/checklists/refactor-qa.md +216 -216
- package/.codex/skills/genesis-harness/checklists/requirements-validation.md +211 -211
- package/.codex/skills/genesis-harness/references/planning-schema.md +35 -35
- package/.codex/skills/genesis-harness/references/quality-rubric.md +21 -21
- package/.codex/skills/genesis-harness/references/research-rubric.md +41 -41
- package/.codex/skills/genesis-harness/references/workflows.md +33 -33
- package/.codex/skills/genesis-harness/resources/agents-template.md +27 -27
- package/.codex/skills/genesis-harness/resources/api-docs-template.md +32 -32
- package/.codex/skills/genesis-harness/resources/architecture-template.md +30 -30
- package/.codex/skills/genesis-harness/resources/audit-template.md +26 -26
- package/.codex/skills/genesis-harness/resources/bug-template.md +34 -34
- package/.codex/skills/genesis-harness/resources/change-impact-matrix-template.md +204 -204
- package/.codex/skills/genesis-harness/resources/check-template.md +21 -21
- package/.codex/skills/genesis-harness/resources/conventions-template.md +42 -42
- package/.codex/skills/genesis-harness/resources/decision-template.md +33 -33
- package/.codex/skills/genesis-harness/resources/design-template.md +26 -26
- package/.codex/skills/genesis-harness/resources/escalation-template.md +21 -21
- package/.codex/skills/genesis-harness/resources/feature-template.md +49 -49
- package/.codex/skills/genesis-harness/resources/foundation-phase-template.md +131 -131
- package/.codex/skills/genesis-harness/resources/integrations-template.md +32 -32
- package/.codex/skills/genesis-harness/resources/journeys-template.md +13 -13
- package/.codex/skills/genesis-harness/resources/lessons-learned-template.md +12 -12
- package/.codex/skills/genesis-harness/resources/observability-template.md +34 -34
- package/.codex/skills/genesis-harness/resources/phase-00-foundation-template.md +76 -76
- package/.codex/skills/genesis-harness/resources/phase-template.md +34 -34
- package/.codex/skills/genesis-harness/resources/pitfalls-template.md +22 -22
- package/.codex/skills/genesis-harness/resources/planning-tree-template.md +39 -39
- package/.codex/skills/genesis-harness/resources/post-implementation-guide.md +347 -347
- package/.codex/skills/genesis-harness/resources/project-template.md +38 -38
- package/.codex/skills/genesis-harness/resources/quality-score-template.md +11 -11
- package/.codex/skills/genesis-harness/resources/requirements-template.md +26 -26
- package/.codex/skills/genesis-harness/resources/research-template.md +26 -26
- package/.codex/skills/genesis-harness/resources/review-template.md +22 -22
- package/.codex/skills/genesis-harness/resources/spec-changelog-template.md +6 -6
- package/.codex/skills/genesis-harness/resources/stack-template.md +33 -33
- package/.codex/skills/genesis-harness/resources/verification-template.md +26 -26
- package/.codex/skills/genesis-harness/scripts/check-architecture-boundaries.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/check-docs-sync.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/check-no-debug-logs.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/check-required-planning-files.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/check-spec-changelog.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/check-task-tracking.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/compact-context.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/create-adr.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/create-bug.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/create-feature.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/detect-stack.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/init-planning.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/list-changed-files.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/offload-log.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/run-verification.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/run-verify-loop.sh +0 -0
- package/.codex/skills/genesis-harness/scripts/update-state.sh +0 -0
- package/.codex/skills/genesis-harness-engineering/SKILL.md +1 -1
- package/.codex/skills/genesis-new-design/SKILL.md +2 -1
- package/.codex/skills/genesis-new-design/agents/openai.yaml +3 -3
- package/.codex/skills/genesis-observability-automation/checklists/.gitkeep +0 -0
- package/.codex/skills/genesis-observability-automation/observability/.gitkeep +0 -0
- package/.codex/skills/genesis-observability-automation/playbooks/.gitkeep +0 -0
- package/.codex/skills/genesis-observability-automation/templates/.gitkeep +0 -0
- package/.codex/skills/genesis-pipeline-orchestration/SKILL.md +1 -1
- package/.codex/skills/genesis-planning/SKILL.md +26 -1
- package/.codex/skills/genesis-planning/checklists/mvp-readiness.md +18 -0
- package/.codex/skills/genesis-planning/examples/5-phase-roadmap-example.md +43 -0
- package/.codex/skills/genesis-planning/templates/phase-1-core.md +17 -0
- package/.codex/skills/genesis-planning/templates/phase-2-auth.md +17 -0
- package/.codex/skills/genesis-planning/templates/phase-3-features.md +17 -0
- package/.codex/skills/genesis-planning/templates/phase-4-integrations.md +17 -0
- package/.codex/skills/genesis-planning/templates/phase-5-readiness.md +17 -0
- package/.codex/skills/genesis-release/SKILL.md +24 -1
- package/.codex/skills/{genesis-release-orchestration → genesis-release}/checklists/post-deployment-verification.md +274 -274
- package/.codex/skills/{genesis-release-orchestration → genesis-release}/checklists/pre-release-validation.md +220 -220
- package/.codex/skills/{genesis-release-orchestration → genesis-release}/observability/release-tracking.md +253 -253
- package/.codex/skills/{genesis-release-orchestration → genesis-release}/playbooks/canary-deployment-orchestration.md +472 -472
- package/.codex/skills/{genesis-release-orchestration → genesis-release}/playbooks/semantic-versioning-automation.md +494 -494
- package/.codex/skills/{genesis-release-orchestration → genesis-release}/templates/deployment-strategy-template.md +303 -303
- package/.codex/skills/{genesis-release-orchestration → genesis-release}/templates/release-runbook-template.md +420 -420
- package/.codex/skills/genesis-research-first/SKILL.md +237 -237
- package/.codex/skills/genesis-research-first/templates/.gitkeep +0 -0
- package/.codex/skills/genesis-spec-propagation/SKILL.md +534 -534
- package/.codex/skills/genesis-spec-propagation/checklists/phase-update-verification.md +384 -384
- package/.codex/skills/genesis-spec-propagation/checklists/spec-change-detection.md +257 -257
- package/.codex/skills/genesis-spec-propagation/observability/propagation-tracking.md +373 -373
- package/.codex/skills/genesis-spec-propagation/playbooks/breaking-change-propagation.md +692 -692
- package/.codex/skills/genesis-spec-propagation/playbooks/feature-change-propagation.md +434 -434
- package/.codex/skills/genesis-spec-propagation/templates/migration-guide-template.md +407 -407
- package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/SKILL.md +1 -1
- package/.codex/skills/genesis-upgrade-design/agents/openai.yaml +3 -3
- package/.codex/skills/spec-impact-engine/SKILL.md +504 -504
- package/.codex/skills/spec-impact-engine/detect-spec-changes.sh +0 -0
- package/.codex-plugin/plugin.json +19 -19
- package/CHANGELOG.md +56 -0
- package/LICENSE +22 -22
- package/README.EN.md +780 -730
- package/README.VI.md +772 -723
- package/README.md +102 -247
- package/VERSION +2 -2
- package/bin/genesis-harness.js +695 -92
- package/package.json +9 -3
- package/scripts/README.md +342 -342
- package/scripts/compact-context.sh +0 -0
- package/scripts/contract_integrity_gate.js +83 -0
- package/scripts/detect-changes.sh +0 -0
- package/scripts/healing_telemetry.js +118 -0
- package/scripts/install.sh +5 -6
- package/scripts/offload-log.sh +0 -0
- package/scripts/prompt_sentinel.js +84 -0
- package/scripts/run-evals.sh +20 -24
- package/scripts/run-verify-loop.sh +11 -0
- package/scripts/spec_visual_sync.js +157 -0
- package/scripts/test_generator.js +142 -0
- package/scripts/transition_state.sh +0 -0
- package/scripts/uninstall.sh +2 -5
- package/scripts/validation_gates.sh +40 -1
- package/scripts/verify.sh +6 -61
- package/tests/unit/contract_integrity_gate.test.js +74 -0
- package/tests/unit/healing_telemetry.test.js +58 -0
- package/tests/unit/prompt_sentinel.test.js +50 -0
- package/tests/unit/spec_visual_sync.test.js +77 -0
- package/tests/unit/test_generator.test.js +62 -0
- package/.codex/skills/genesis-docs/SKILL.md +0 -46
- package/.codex/skills/genesis-docs/agents/openai.yaml +0 -7
- package/.codex/skills/genesis-release-orchestration/SKILL.md +0 -653
- package/.codex/skills/genesis-release-orchestration/agents/openai.yaml +0 -7
- package/.codex/skills/genesis-research/SKILL.md +0 -46
- package/.codex/skills/genesis-research/agents/openai.yaml +0 -7
- /package/.codex/skills/{genesis-docs/checklists/checklist.md → genesis-docs-automation/checklists/manual-docs-checklist.md} +0 -0
- /package/.codex/skills/{genesis-docs/examples/example.md → genesis-docs-automation/examples/manual-docs-example.md} +0 -0
- /package/.codex/skills/{genesis-docs → genesis-docs-automation}/templates/docs-update-template.md +0 -0
- /package/.codex/skills/{genesis-state-machine/SKILL.md → genesis-harness/references/state-machine.md} +0 -0
- /package/.codex/skills/{genesis-release-orchestration/examples/example.md → genesis-release/examples/orchestration-example.md} +0 -0
- /package/.codex/skills/{genesis-research → genesis-research-first}/checklists/checklist.md +0 -0
- /package/.codex/skills/{genesis-research/examples/example.md → genesis-research-first/examples/manual-research-example.md} +0 -0
- /package/.codex/skills/{genesis-research → genesis-research-first}/templates/research-note-template.md +0 -0
- /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/agents/openai.yaml +0 -0
- /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/checklists/checklist.md +0 -0
- /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/examples/example.md +0 -0
- /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/templates/playwright-test-template.md +0 -0
package/bin/genesis-harness.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const path = require("path");
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
6
|
const { spawnSync } = require("child_process");
|
|
7
7
|
|
|
8
8
|
const packageRoot = path.resolve(__dirname, "..");
|
|
@@ -15,21 +15,18 @@ const skillNames = [
|
|
|
15
15
|
"genesis-codebase-map",
|
|
16
16
|
"genesis-design-spec",
|
|
17
17
|
"genesis-api-contract",
|
|
18
|
-
"ui-ux-test
|
|
18
|
+
"genesis-ui-ux-test",
|
|
19
19
|
"genesis-harness-engineering",
|
|
20
20
|
"genesis-ai-provider",
|
|
21
21
|
"genesis-pipeline-orchestration",
|
|
22
|
-
"genesis-research",
|
|
23
|
-
"genesis-docs",
|
|
24
|
-
"genesis-release",
|
|
25
22
|
"genesis-api-sync",
|
|
26
23
|
"genesis-debug-guide",
|
|
27
24
|
"genesis-docs-automation",
|
|
28
25
|
"genesis-spec-propagation",
|
|
29
|
-
"genesis-release-orchestration",
|
|
30
26
|
"genesis-performance-profiling",
|
|
31
27
|
"genesis-observability-automation",
|
|
32
28
|
"genesis-research-first",
|
|
29
|
+
"genesis-release",
|
|
33
30
|
"spec-impact-engine"
|
|
34
31
|
];
|
|
35
32
|
const legacySkillNames = ["project-genesis-harness"];
|
|
@@ -38,31 +35,38 @@ const codexHome = process.env.CODEX_HOME || path.join(process.env.HOME || "", ".
|
|
|
38
35
|
const agentsHome = process.env.GENESIS_HARNESS_HOME || path.join(process.env.HOME || "", ".agents");
|
|
39
36
|
const legacySkillsRoot = path.join(codexHome, "skills");
|
|
40
37
|
const agentsSkillsRoot = path.join(agentsHome, "skills");
|
|
41
|
-
|
|
42
|
-
function usage(exitCode = 0) {
|
|
43
|
-
const text = `
|
|
44
|
-
Project Genesis Harness
|
|
45
|
-
|
|
46
|
-
Usage:
|
|
47
|
-
genesis-harness install [--target agents|legacy|both]
|
|
48
|
-
genesis-harness verify [--target agents|legacy|both]
|
|
49
|
-
genesis-harness uninstall [--target agents|legacy|both]
|
|
50
|
-
genesis-harness path
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
console
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
38
|
+
|
|
39
|
+
function usage(exitCode = 0) {
|
|
40
|
+
const text = `
|
|
41
|
+
Project Genesis Harness
|
|
42
|
+
|
|
43
|
+
Usage:
|
|
44
|
+
genesis-harness install [--target agents|legacy|both]
|
|
45
|
+
genesis-harness verify [--target agents|legacy|both]
|
|
46
|
+
genesis-harness uninstall [--target agents|legacy|both]
|
|
47
|
+
genesis-harness path
|
|
48
|
+
genesis-harness status Show implementation status & skills inventory
|
|
49
|
+
genesis-harness docs Show API contracts & documentation sync report
|
|
50
|
+
genesis-harness remember [cat] "<msg>" Remember a persistent project fact/insight (Bead)
|
|
51
|
+
genesis-harness recall [query] Recall and search remembered project facts
|
|
52
|
+
genesis-harness forget <id> Forget/delete a fact by its unique 6-char ID
|
|
53
|
+
genesis-harness prime Generate the token-minimized Agent Priming Prompt
|
|
54
|
+
genesis-harness view-mockup [slug] Interactive console UI to search & view mockups
|
|
55
|
+
|
|
56
|
+
Environment:
|
|
57
|
+
CODEX_HOME=/custom/.codex Override Codex home
|
|
58
|
+
GENESIS_HARNESS_HOME=/custom/.agents Override modern skills home
|
|
59
|
+
GENESIS_HARNESS_SKIP_POSTINSTALL=1 Skip npm postinstall auto-install
|
|
60
|
+
`;
|
|
61
|
+
console.log(text.trim());
|
|
62
|
+
process.exit(exitCode);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function fail(message) {
|
|
66
|
+
console.error(`genesis-harness: ${message}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
66
70
|
function ensureSource() {
|
|
67
71
|
for (const skillName of skillNames) {
|
|
68
72
|
const skillFile = path.join(sourceRoot, skillName, "SKILL.md");
|
|
@@ -71,21 +75,21 @@ function ensureSource() {
|
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
|
-
|
|
75
|
-
function parseTarget(args, fallback = "both") {
|
|
76
|
-
let target = fallback;
|
|
77
|
-
for (let i = 0; i < args.length; i++) {
|
|
78
|
-
if (args[i] === "--target") {
|
|
79
|
-
target = args[i + 1];
|
|
80
|
-
i++;
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
usage(2);
|
|
84
|
-
}
|
|
85
|
-
if (!["agents", "legacy", "both"].includes(target)) usage(2);
|
|
86
|
-
return target;
|
|
87
|
-
}
|
|
88
|
-
|
|
78
|
+
|
|
79
|
+
function parseTarget(args, fallback = "both") {
|
|
80
|
+
let target = fallback;
|
|
81
|
+
for (let i = 0; i < args.length; i++) {
|
|
82
|
+
if (args[i] === "--target") {
|
|
83
|
+
target = args[i + 1];
|
|
84
|
+
i++;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
usage(2);
|
|
88
|
+
}
|
|
89
|
+
if (!["agents", "legacy", "both"].includes(target)) usage(2);
|
|
90
|
+
return target;
|
|
91
|
+
}
|
|
92
|
+
|
|
89
93
|
function targetRoots(target) {
|
|
90
94
|
if (target === "agents") return [agentsSkillsRoot];
|
|
91
95
|
if (target === "legacy") return [legacySkillsRoot];
|
|
@@ -101,7 +105,9 @@ function copySkills({ quiet = false, target = "both" } = {}) {
|
|
|
101
105
|
const dir = path.join(root, skillName);
|
|
102
106
|
|
|
103
107
|
if (fs.existsSync(dir)) {
|
|
104
|
-
const
|
|
108
|
+
const backupParent = path.join(root, "..", "backups");
|
|
109
|
+
fs.mkdirSync(backupParent, { recursive: true });
|
|
110
|
+
const backupDir = path.join(backupParent, `${skillName}.backup.${timestamp()}`);
|
|
105
111
|
fs.renameSync(dir, backupDir);
|
|
106
112
|
if (!quiet) console.log(`Existing skill backed up to: ${backupDir}`);
|
|
107
113
|
}
|
|
@@ -129,7 +135,7 @@ function uninstallSkills(target = "both") {
|
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
|
-
|
|
138
|
+
|
|
133
139
|
function verifySkill(target = "both") {
|
|
134
140
|
const verifyScript = path.join(packageRoot, "scripts", "verify.sh");
|
|
135
141
|
if (!fs.existsSync(verifyScript)) fail(`missing verify script at ${verifyScript}`);
|
|
@@ -158,41 +164,617 @@ function resolveBash() {
|
|
|
158
164
|
}
|
|
159
165
|
return "bash";
|
|
160
166
|
}
|
|
161
|
-
|
|
162
|
-
function chmodScripts(dir) {
|
|
163
|
-
if (!fs.existsSync(dir)) return;
|
|
164
|
-
for (const entry of fs.readdirSync(dir)) {
|
|
165
|
-
const file = path.join(dir, entry);
|
|
166
|
-
if (entry.endsWith(".sh") && fs.statSync(file).isFile()) {
|
|
167
|
-
fs.chmodSync(file, 0o755);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function timestamp() {
|
|
173
|
-
const date = new Date();
|
|
174
|
-
const pad = (value) => String(value).padStart(2, "0");
|
|
175
|
-
return [
|
|
176
|
-
date.getFullYear(),
|
|
177
|
-
pad(date.getMonth() + 1),
|
|
178
|
-
pad(date.getDate()),
|
|
179
|
-
pad(date.getHours()),
|
|
180
|
-
pad(date.getMinutes()),
|
|
181
|
-
pad(date.getSeconds())
|
|
182
|
-
].join("");
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
167
|
+
|
|
168
|
+
function chmodScripts(dir) {
|
|
169
|
+
if (!fs.existsSync(dir)) return;
|
|
170
|
+
for (const entry of fs.readdirSync(dir)) {
|
|
171
|
+
const file = path.join(dir, entry);
|
|
172
|
+
if (entry.endsWith(".sh") && fs.statSync(file).isFile()) {
|
|
173
|
+
fs.chmodSync(file, 0o755);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function timestamp() {
|
|
179
|
+
const date = new Date();
|
|
180
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
181
|
+
return [
|
|
182
|
+
date.getFullYear(),
|
|
183
|
+
pad(date.getMonth() + 1),
|
|
184
|
+
pad(date.getDate()),
|
|
185
|
+
pad(date.getHours()),
|
|
186
|
+
pad(date.getMinutes()),
|
|
187
|
+
pad(date.getSeconds())
|
|
188
|
+
].join("");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function showStatus() {
|
|
192
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m");
|
|
193
|
+
console.log("\x1b[1m\x1b[36m GENESIS HARNESS - STATUS REPORT \x1b[0m");
|
|
194
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m");
|
|
195
|
+
|
|
196
|
+
// 1. Current State
|
|
197
|
+
const currentStateFile = path.join(packageRoot, ".codebase", "CURRENT_STATE.md");
|
|
198
|
+
if (fs.existsSync(currentStateFile)) {
|
|
199
|
+
const content = fs.readFileSync(currentStateFile, "utf8");
|
|
200
|
+
console.log("\n\x1b[1m\x1b[32m[+] Repository State (.codebase/CURRENT_STATE.md):\x1b[0m");
|
|
201
|
+
const lines = content.split("\n");
|
|
202
|
+
for (const line of lines) {
|
|
203
|
+
if (line.startsWith("# ") || line.startsWith("## ") || line.startsWith("- ")) {
|
|
204
|
+
console.log(" " + line.trim());
|
|
205
|
+
} else if (line.trim()) {
|
|
206
|
+
console.log(" " + line.trim());
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
console.log("\n\x1b[1m\x1b[31m[-] Repository State:\x1b[0m .codebase/CURRENT_STATE.md not found.");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 2. Active Planning & Task Tracking
|
|
214
|
+
const stateFile = path.join(packageRoot, ".planning", "STATE.md");
|
|
215
|
+
const roadmapFile = path.join(packageRoot, ".planning", "ROADMAP.md");
|
|
216
|
+
if (fs.existsSync(stateFile) || fs.existsSync(roadmapFile)) {
|
|
217
|
+
console.log("\n\x1b[1m\x1b[32m[+] FSM Active Planning & Task Tracking (.planning/):\x1b[0m");
|
|
218
|
+
if (fs.existsSync(stateFile)) {
|
|
219
|
+
console.log(" \x1b[1m- Current Execution State (.planning/STATE.md):\x1b[0m");
|
|
220
|
+
const content = fs.readFileSync(stateFile, "utf8");
|
|
221
|
+
const lines = content.split("\n");
|
|
222
|
+
for (const line of lines) {
|
|
223
|
+
if (line.includes("Current project state:") || line.includes("Current phase:") || line.includes("Current feature or bug:") || line.includes("Next task:") || line.includes("Latest verification result:")) {
|
|
224
|
+
console.log(` ${line.replace("#", "").trim()}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (fs.existsSync(roadmapFile)) {
|
|
229
|
+
console.log("\n \x1b[1m- 5-Phase Roadmap Status (.planning/ROADMAP.md):\x1b[0m");
|
|
230
|
+
const content = fs.readFileSync(roadmapFile, "utf8");
|
|
231
|
+
const lines = content.split("\n");
|
|
232
|
+
for (const line of lines) {
|
|
233
|
+
if (line.match(/^-\s*\[[ x~!]\]/)) {
|
|
234
|
+
console.log(` ${line.trim()}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
console.log("\n\x1b[1m\x1b[33m[-] FSM Active Planning:\x1b[0m No active .planning/ session found. Run `/genesis-init` in Codex to initialize.");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// 3. Skills Inventory
|
|
243
|
+
console.log("\n\x1b[1m\x1b[32m[+] Skills Inventory Check (Exactly 21 core skills):\x1b[0m");
|
|
244
|
+
let found = 0;
|
|
245
|
+
let mismatched = 0;
|
|
246
|
+
for (const skillName of skillNames) {
|
|
247
|
+
const skillDir = path.join(sourceRoot, skillName);
|
|
248
|
+
const skillFile = path.join(skillDir, "SKILL.md");
|
|
249
|
+
if (fs.existsSync(skillFile)) {
|
|
250
|
+
found++;
|
|
251
|
+
const content = fs.readFileSync(skillFile, "utf8");
|
|
252
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
253
|
+
const name = nameMatch ? nameMatch[1].trim() : "";
|
|
254
|
+
if (name !== skillName) {
|
|
255
|
+
mismatched++;
|
|
256
|
+
console.log(` \x1b[31m[-] Mismatch:\x1b[0m folder '${skillName}' has frontmatter name '${name}'`);
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
console.log(` \x1b[31m[-] Missing:\x1b[0m ${skillName} (SKILL.md not found)`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (found === skillNames.length && mismatched === 0) {
|
|
264
|
+
console.log(` \x1b[32m✓ Success:\x1b[0m All ${skillNames.length} skill folders perfectly standard and synchronized!`);
|
|
265
|
+
} else {
|
|
266
|
+
console.log(` \x1b[31m⚠️ Alert:\x1b[0m Found ${found}/${skillNames.length} skills. Mismatches: ${mismatched}.`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// 4. Verification Test Run Status
|
|
270
|
+
console.log("\n\x1b[1m\x1b[32m[+] Quick Pipeline Commands:\x1b[0m");
|
|
271
|
+
console.log(" - Run structural checks: \x1b[33m./scripts/verify.sh\x1b[0m");
|
|
272
|
+
console.log(" - Run regression tests: \x1b[33m./scripts/run-evals.sh\x1b[0m");
|
|
273
|
+
console.log(" - Run package checks: \x1b[33mnpm run pack:check\x1b[0m");
|
|
274
|
+
|
|
275
|
+
console.log("\n\x1b[1m\x1b[36m======================================================================\x1b[0m\n");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function showDocsStatus() {
|
|
279
|
+
console.log("\x1b[1m\x1b[35m======================================================================\x1b[0m");
|
|
280
|
+
console.log("\x1b[1m\x1b[35m GENESIS HARNESS - DOCUMENTATION REPORT \x1b[0m");
|
|
281
|
+
console.log("\x1b[1m\x1b[35m======================================================================\x1b[0m");
|
|
282
|
+
|
|
283
|
+
// 1. Architecture Summary
|
|
284
|
+
const archFile = path.join(packageRoot, ".codebase", "ARCHITECTURE.md");
|
|
285
|
+
if (fs.existsSync(archFile)) {
|
|
286
|
+
console.log("\n\x1b[1m\x1b[32m[+] System Architecture (.codebase/ARCHITECTURE.md):\x1b[0m");
|
|
287
|
+
const content = fs.readFileSync(archFile, "utf8");
|
|
288
|
+
console.log(" " + content.trim().split("\n").filter(l => l.trim() && !l.startsWith("#")).join("\n "));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// 2. API Contracts & Specs
|
|
292
|
+
console.log("\n\x1b[1m\x1b[32m[+] API Contracts & Specs (contracts/api/):\x1b[0m");
|
|
293
|
+
const apiDir = path.join(packageRoot, "contracts", "api");
|
|
294
|
+
if (fs.existsSync(apiDir)) {
|
|
295
|
+
const endpoints = fs.readdirSync(apiDir).filter(f => fs.statSync(path.join(apiDir, f)).isDirectory());
|
|
296
|
+
if (endpoints.length > 0) {
|
|
297
|
+
for (const endpoint of endpoints) {
|
|
298
|
+
console.log(` - \x1b[1m${endpoint}\x1b[0m`);
|
|
299
|
+
const files = ["request.json", "response.json", "schema.json", "example.json", "error.json"];
|
|
300
|
+
const found = [];
|
|
301
|
+
for (const file of files) {
|
|
302
|
+
if (fs.existsSync(path.join(apiDir, endpoint, file))) {
|
|
303
|
+
found.push(file.replace(".json", ""));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
console.log(` Files: \x1b[33m${found.join(", ")}\x1b[0m`);
|
|
307
|
+
|
|
308
|
+
// Print request structure preview if request.json exists
|
|
309
|
+
const reqPath = path.join(apiDir, endpoint, "request.json");
|
|
310
|
+
if (fs.existsSync(reqPath)) {
|
|
311
|
+
try {
|
|
312
|
+
const req = JSON.parse(fs.readFileSync(reqPath, "utf8"));
|
|
313
|
+
console.log(` Request: \x1b[90m${JSON.stringify(req).slice(0, 80)}...\x1b[0m`);
|
|
314
|
+
} catch(e) {}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
} else {
|
|
318
|
+
console.log(" No API endpoint contracts defined under contracts/api/.");
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
console.log(" contracts/api/ directory not found.");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// 3. Documentation Density
|
|
325
|
+
console.log("\n\x1b[1m\x1b[32m[+] Documentation Density Stats:\x1b[0m");
|
|
326
|
+
const countMd = (dir) => {
|
|
327
|
+
let count = 0;
|
|
328
|
+
if (!fs.existsSync(dir)) return 0;
|
|
329
|
+
const walk = (d) => {
|
|
330
|
+
for (const f of fs.readdirSync(d)) {
|
|
331
|
+
const full = path.join(d, f);
|
|
332
|
+
if (fs.statSync(full).isDirectory()) {
|
|
333
|
+
walk(full);
|
|
334
|
+
} else if (f.endsWith(".md")) {
|
|
335
|
+
count++;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
walk(dir);
|
|
340
|
+
return count;
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const codebaseMd = countMd(path.join(packageRoot, ".codebase"));
|
|
344
|
+
const skillsMd = countMd(path.join(packageRoot, ".codex", "skills"));
|
|
345
|
+
console.log(` - Memory documents (.codebase/): \x1b[36m${codebaseMd} Markdown files\x1b[0m`);
|
|
346
|
+
console.log(` - Skill playbooks (.codex/skills/): \x1b[36m${skillsMd} Markdown files\x1b[0m`);
|
|
347
|
+
|
|
348
|
+
// 4. Git Documentation Sync Check
|
|
349
|
+
console.log("\n\x1b[1m\x1b[32m[+] Git Documentation Sync Status:\x1b[0m");
|
|
350
|
+
try {
|
|
351
|
+
const diff = spawnSync("git", ["diff", "--name-only", "HEAD"], { encoding: "utf8" });
|
|
352
|
+
const changed = diff.stdout ? diff.stdout.trim().split("\n").filter(Boolean) : [];
|
|
353
|
+
if (changed.length > 0) {
|
|
354
|
+
const codeChanged = changed.filter(f => !f.match(/^(\.planning\/|docs\/|README|AGENTS\.md)/));
|
|
355
|
+
const docsChanged = changed.filter(f => f.match(/^(\.planning\/|docs\/|README|AGENTS\.md)/));
|
|
356
|
+
if (codeChanged.length > 0 && docsChanged.length === 0) {
|
|
357
|
+
console.log(" \x1b[31m⚠️ Warning:\x1b[0m Code files changed but no documentation/planning files updated.");
|
|
358
|
+
console.log(` Changed code files: \x1b[90m${codeChanged.slice(0, 3).join(", ")}${codeChanged.length > 3 ? "..." : ""}\x1b[0m`);
|
|
359
|
+
} else {
|
|
360
|
+
console.log(" \x1b[32m✓ Synchronized:\x1b[0m Code and documentation changes are perfectly synchronized!");
|
|
361
|
+
}
|
|
362
|
+
} else {
|
|
363
|
+
console.log(" \x1b[32m✓ Clean:\x1b[0m No uncommitted changes. Documentation is 100% in sync.");
|
|
364
|
+
}
|
|
365
|
+
} catch(e) {
|
|
366
|
+
console.log(" Git status check unavailable.");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
console.log("\n\x1b[1m\x1b[35m======================================================================\x1b[0m\n");
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const beadsPath = path.join(packageRoot, ".codebase", "beads.json");
|
|
373
|
+
|
|
374
|
+
function getGitCommit() {
|
|
375
|
+
try {
|
|
376
|
+
const git = spawnSync("git", ["rev-parse", "--short", "HEAD"], { encoding: "utf8" });
|
|
377
|
+
if (git.status === 0 && git.stdout) {
|
|
378
|
+
return git.stdout.trim();
|
|
379
|
+
}
|
|
380
|
+
} catch (e) {}
|
|
381
|
+
return "no-git";
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function readBeads() {
|
|
385
|
+
if (!fs.existsSync(beadsPath)) return [];
|
|
386
|
+
try {
|
|
387
|
+
return JSON.parse(fs.readFileSync(beadsPath, "utf8")) || [];
|
|
388
|
+
} catch (e) {
|
|
389
|
+
return [];
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function writeBeads(beads) {
|
|
394
|
+
const codebaseDir = path.dirname(beadsPath);
|
|
395
|
+
if (!fs.existsSync(codebaseDir)) {
|
|
396
|
+
fs.mkdirSync(codebaseDir, { recursive: true });
|
|
397
|
+
}
|
|
398
|
+
fs.writeFileSync(beadsPath, JSON.stringify(beads, null, 2), "utf8");
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function generateUniqueId(beads) {
|
|
402
|
+
const existing = new Set(beads.map(b => b.id));
|
|
403
|
+
while (true) {
|
|
404
|
+
const id = Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0");
|
|
405
|
+
if (!existing.has(id)) return id;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function rememberFact(arg1, arg2) {
|
|
410
|
+
let category = "general";
|
|
411
|
+
let fact = "";
|
|
412
|
+
|
|
413
|
+
if (!arg1) {
|
|
414
|
+
console.error("\x1b[31mError: You must provide a fact/insight to remember.\x1b[0m");
|
|
415
|
+
console.log("Usage: genesis-harness remember [category] \"<fact>\"");
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (arg2) {
|
|
420
|
+
category = arg1.toLowerCase().trim();
|
|
421
|
+
fact = arg2.trim();
|
|
422
|
+
} else {
|
|
423
|
+
fact = arg1.trim();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const beads = readBeads();
|
|
427
|
+
const bead = {
|
|
428
|
+
id: generateUniqueId(beads),
|
|
429
|
+
category,
|
|
430
|
+
fact,
|
|
431
|
+
timestamp: new Date().toISOString(),
|
|
432
|
+
git_commit: getGitCommit()
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
beads.push(bead);
|
|
436
|
+
writeBeads(beads);
|
|
437
|
+
|
|
438
|
+
console.log(`\n\x1b[1m\x1b[32m[+] Remembered (Bead Added):\x1b[0m`);
|
|
439
|
+
console.log(` \x1b[1mID:\x1b[0m \x1b[33m[${bead.id}]\x1b[0m`);
|
|
440
|
+
console.log(` \x1b[1mCategory:\x1b[0m \x1b[36m${bead.category}\x1b[0m`);
|
|
441
|
+
console.log(` \x1b[1mFact:\x1b[0m ${bead.fact}`);
|
|
442
|
+
console.log(` \x1b[1mGit Commit:\x1b[0m \x1b[90m${bead.git_commit}\x1b[0m\n`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function recallFacts(query) {
|
|
446
|
+
const beads = readBeads();
|
|
447
|
+
if (beads.length === 0) {
|
|
448
|
+
console.log("\n\x1b[33m[-] No remembered facts found in database (.codebase/beads.json).\x1b[0m\n");
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
let filtered = beads;
|
|
453
|
+
if (query) {
|
|
454
|
+
const q = query.toLowerCase().trim();
|
|
455
|
+
filtered = beads.filter(
|
|
456
|
+
b => b.category === q || b.fact.toLowerCase().includes(q) || b.id === q
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m");
|
|
461
|
+
console.log("\x1b[1m\x1b[36m GENESIS HARNESS - RECALLED MEMORIES \x1b[0m");
|
|
462
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m");
|
|
463
|
+
|
|
464
|
+
if (filtered.length === 0) {
|
|
465
|
+
console.log(`\n No memories found matching: \x1b[31m"${query}"\x1b[0m\n`);
|
|
466
|
+
} else {
|
|
467
|
+
console.log("");
|
|
468
|
+
for (const bead of filtered) {
|
|
469
|
+
console.log(` • \x1b[1m\x1b[33m[${bead.id}]\x1b[0m [\x1b[36m${bead.category}\x1b[0m] ${bead.fact} \x1b[90m(${bead.git_commit})\x1b[0m`);
|
|
470
|
+
}
|
|
471
|
+
console.log("");
|
|
472
|
+
}
|
|
473
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m\n");
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function forgetFact(id) {
|
|
477
|
+
if (!id) {
|
|
478
|
+
console.error("\x1b[31mError: You must specify a 6-character unique ID to forget.\x1b[0m");
|
|
479
|
+
console.log("Usage: genesis-harness forget <id>");
|
|
480
|
+
process.exit(1);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const targetId = id.toLowerCase().trim();
|
|
484
|
+
const beads = readBeads();
|
|
485
|
+
const index = beads.findIndex(b => b.id === targetId);
|
|
486
|
+
|
|
487
|
+
if (index === -1) {
|
|
488
|
+
console.error(`\x1b[31mError: No remembered fact found with ID [${targetId}].\x1b[0m`);
|
|
489
|
+
process.exit(1);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const removed = beads.splice(index, 1)[0];
|
|
493
|
+
writeBeads(beads);
|
|
494
|
+
|
|
495
|
+
console.log(`\n\x1b[1m\x1b[32m[+] Forgotten (Bead Deleted):\x1b[0m`);
|
|
496
|
+
console.log(` Successfully removed fact \x1b[33m[${removed.id}]\x1b[0m from category \x1b[36m"${removed.category}"\x1b[0m.\n`);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function primeContext() {
|
|
500
|
+
const out = [];
|
|
501
|
+
out.push("# 🤖 AGENT MEMORY PRIMING BOOTSTRAP");
|
|
502
|
+
out.push("");
|
|
503
|
+
out.push("This prompt initializes your active context and project memory to prevent task drift.");
|
|
504
|
+
out.push("");
|
|
505
|
+
out.push("---");
|
|
506
|
+
out.push("");
|
|
507
|
+
|
|
508
|
+
// 1. Coordinates
|
|
509
|
+
out.push("## 📍 1. Session Coordinates");
|
|
510
|
+
out.push(`- **Local Time**: ${new Date().toISOString()}`);
|
|
511
|
+
out.push(`- **Workspace Path**: \`${packageRoot}\``);
|
|
512
|
+
const gitCommit = getGitCommit();
|
|
513
|
+
out.push(`- **Git Commit**: \`${gitCommit}\``);
|
|
514
|
+
out.push("");
|
|
515
|
+
|
|
516
|
+
// 2. Active FSM State
|
|
517
|
+
out.push("## 🔄 2. Active Execution State");
|
|
518
|
+
const stateFile = path.join(packageRoot, ".planning", "STATE.md");
|
|
519
|
+
if (fs.existsSync(stateFile)) {
|
|
520
|
+
const content = fs.readFileSync(stateFile, "utf8");
|
|
521
|
+
const lines = content.split("\n");
|
|
522
|
+
for (const line of lines) {
|
|
523
|
+
if (line.includes("Current project state:") || line.includes("Current phase:") || line.includes("Current feature or bug:") || line.includes("Next task:")) {
|
|
524
|
+
out.push(`- ${line.replace("#", "").trim()}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
// Fallback to .codebase/state.json
|
|
529
|
+
const stateJsonFile = path.join(packageRoot, ".codebase", "state.json");
|
|
530
|
+
if (fs.existsSync(stateJsonFile)) {
|
|
531
|
+
try {
|
|
532
|
+
const stateObj = JSON.parse(fs.readFileSync(stateJsonFile, "utf8"));
|
|
533
|
+
out.push(`- **Current project state**: \`${stateObj.current_state || "INIT"}\``);
|
|
534
|
+
} catch(e) {}
|
|
535
|
+
} else {
|
|
536
|
+
out.push("- *No active planning session is currently running.*");
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
out.push("");
|
|
540
|
+
|
|
541
|
+
// 3. Active Roadmap (Token-Optimized)
|
|
542
|
+
out.push("## 🗺️ 3. Active & Pending Roadmap Tasks");
|
|
543
|
+
const roadmapFile = path.join(packageRoot, ".planning", "ROADMAP.md");
|
|
544
|
+
if (fs.existsSync(roadmapFile)) {
|
|
545
|
+
const content = fs.readFileSync(roadmapFile, "utf8");
|
|
546
|
+
const lines = content.split("\n");
|
|
547
|
+
let taskCount = 0;
|
|
548
|
+
for (const line of lines) {
|
|
549
|
+
if (line.match(/^-\s*\[[ ~!]\]/)) {
|
|
550
|
+
out.push(` ${line.trim()}`);
|
|
551
|
+
taskCount++;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (taskCount === 0) {
|
|
555
|
+
out.push(" - *All roadmap tasks are currently marked completed or none are active.*");
|
|
556
|
+
}
|
|
557
|
+
} else {
|
|
558
|
+
out.push("- *Roadmap file (.planning/ROADMAP.md) not found.*");
|
|
559
|
+
}
|
|
560
|
+
out.push("");
|
|
561
|
+
|
|
562
|
+
// 4. Memory Beads / Persistent Insights
|
|
563
|
+
out.push("## 🧬 4. Memory Beads (Stored Core Insights)");
|
|
564
|
+
const beads = readBeads();
|
|
565
|
+
if (beads.length > 0) {
|
|
566
|
+
for (const bead of beads) {
|
|
567
|
+
out.push(`- **[${bead.id}]** [${bead.category}]: ${bead.fact} *(${bead.git_commit})*`);
|
|
568
|
+
}
|
|
569
|
+
} else {
|
|
570
|
+
out.push("- *No persistent facts or insights have been registered yet.*");
|
|
571
|
+
}
|
|
572
|
+
out.push("");
|
|
573
|
+
|
|
574
|
+
// 5. API Contracts Index
|
|
575
|
+
out.push("## 🔌 5. Active API Contracts Map");
|
|
576
|
+
const apiDir = path.join(packageRoot, "contracts", "api");
|
|
577
|
+
if (fs.existsSync(apiDir)) {
|
|
578
|
+
const endpoints = fs.readdirSync(apiDir).filter(f => fs.statSync(path.join(apiDir, f)).isDirectory());
|
|
579
|
+
if (endpoints.length > 0) {
|
|
580
|
+
for (const endpoint of endpoints) {
|
|
581
|
+
out.push(`- Endpoint: \`/api/${endpoint}\``);
|
|
582
|
+
}
|
|
583
|
+
} else {
|
|
584
|
+
out.push("- *No active API endpoints registered.*");
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
out.push("- *No contracts/api directory found.*");
|
|
588
|
+
}
|
|
589
|
+
out.push("");
|
|
590
|
+
|
|
591
|
+
// 6. Zero-Drift Playbook Rules
|
|
592
|
+
out.push("## 🛡️ 6. Zero-Drift Playbook Rules");
|
|
593
|
+
out.push("Always adhere strictly to these operational constraints:");
|
|
594
|
+
out.push("1. **Verify first**: Run `./scripts/verify.sh` to check FSM validation and structure.");
|
|
595
|
+
out.push("2. **Update memory**: Ensure `.codebase/CURRENT_STATE.md` is updated at the end of every turn.");
|
|
596
|
+
out.push("3. **Single source**: Avoid duplicating plans across multi-line markdown logs; use `genesis-harness remember` to store critical project coordinates.");
|
|
597
|
+
out.push("4. **TDD Pattern**: Create or update failing tests in `tests/` before making changes to public behaviors.");
|
|
598
|
+
out.push("");
|
|
599
|
+
out.push("---");
|
|
600
|
+
out.push("");
|
|
601
|
+
|
|
602
|
+
console.log(out.join("\n"));
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function openFileNatively(filePath) {
|
|
606
|
+
if (process.platform === "win32") {
|
|
607
|
+
const cp = spawnSync("cmd.exe", ["/c", "start", "", filePath], { shell: true });
|
|
608
|
+
return cp.status === 0;
|
|
609
|
+
}
|
|
610
|
+
let cmd = "open";
|
|
611
|
+
if (process.platform === "linux") {
|
|
612
|
+
cmd = "xdg-open";
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const cp = spawnSync(cmd, [filePath]);
|
|
616
|
+
return cp.status === 0;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
function discoverMockups(rootPath = packageRoot) {
|
|
620
|
+
const mockups = [];
|
|
621
|
+
const featuresDir = path.join(rootPath, ".planning", "features");
|
|
622
|
+
const bugsDir = path.join(rootPath, ".planning", "bugs");
|
|
623
|
+
|
|
624
|
+
const scanDir = (dir, type) => {
|
|
625
|
+
if (!fs.existsSync(dir)) return;
|
|
626
|
+
const entries = fs.readdirSync(dir);
|
|
627
|
+
for (const entry of entries) {
|
|
628
|
+
const fullPath = path.join(dir, entry);
|
|
629
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
630
|
+
const files = fs.readdirSync(fullPath);
|
|
631
|
+
for (const file of files) {
|
|
632
|
+
const ext = path.extname(file).toLowerCase();
|
|
633
|
+
if ([".png", ".jpg", ".jpeg", ".webp"].includes(ext)) {
|
|
634
|
+
mockups.push({
|
|
635
|
+
id: `${type}-${entry}-${file}`,
|
|
636
|
+
title: `${type === "feature" ? "[Feature]" : "[Bug]"} ${entry}`,
|
|
637
|
+
folder: entry,
|
|
638
|
+
fileName: file,
|
|
639
|
+
fullPath: path.join(fullPath, file)
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
scanDir(featuresDir, "feature");
|
|
648
|
+
scanDir(bugsDir, "bug");
|
|
649
|
+
return mockups;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function viewMockupsInteractive(arg) {
|
|
653
|
+
if (arg) {
|
|
654
|
+
if (fs.existsSync(arg) && fs.statSync(arg).isFile()) {
|
|
655
|
+
console.log(`\n\x1b[1m\x1b[32m[+] Opening direct file:\x1b[0m ${arg}`);
|
|
656
|
+
openFileNatively(arg);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
const mockups = discoverMockups();
|
|
661
|
+
const found = mockups.find(m => m.folder === arg || m.id === arg);
|
|
662
|
+
if (found) {
|
|
663
|
+
console.log(`\n\x1b[1m\x1b[32m[+] Opening mockup for ${found.title}:\x1b[0m ${found.fileName}`);
|
|
664
|
+
openFileNatively(found.fullPath);
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
console.error(`\x1b[31mError: No mockup found matching direct path or slug "${arg}".\x1b[0m`);
|
|
669
|
+
process.exit(1);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const mockups = discoverMockups();
|
|
673
|
+
if (mockups.length === 0) {
|
|
674
|
+
console.log("\n\x1b[33m[-] No mockup images (.png, .jpg, .webp) found under .planning/features/ or .planning/bugs/.\x1b[0m\n");
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
let selectedIndex = 0;
|
|
679
|
+
let currentView = "LIST"; // "LIST" or "DETAIL"
|
|
680
|
+
|
|
681
|
+
const renderMenu = () => {
|
|
682
|
+
console.clear();
|
|
683
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m");
|
|
684
|
+
console.log("\x1b[1m\x1b[36m GENESIS HARNESS - MOCKUP GALLERY VIEWER \x1b[0m");
|
|
685
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m\n");
|
|
686
|
+
|
|
687
|
+
if (currentView === "LIST") {
|
|
688
|
+
console.log(" \x1b[1mUse Up/Down Arrow to navigate, Right Arrow (or Enter) to view.\x1b[0m");
|
|
689
|
+
console.log(" \x1b[90mPress Esc or Ctrl+C to exit.\x1b[0m\n");
|
|
690
|
+
console.log(" \x1b[1mDISCOVERED SCREENS / MOCKUPS:\x1b[0m");
|
|
691
|
+
console.log(" ------------------------------------------------------------------");
|
|
692
|
+
|
|
693
|
+
mockups.forEach((mockup, idx) => {
|
|
694
|
+
if (idx === selectedIndex) {
|
|
695
|
+
console.log(` \x1b[1m\x1b[36m➔ ${mockup.title} (${mockup.fileName})\x1b[0m`);
|
|
696
|
+
} else {
|
|
697
|
+
console.log(` \x1b[90m${mockup.title} (${mockup.fileName})\x1b[0m`);
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
console.log(" ------------------------------------------------------------------\n");
|
|
701
|
+
} else if (currentView === "DETAIL") {
|
|
702
|
+
const selected = mockups[selectedIndex];
|
|
703
|
+
console.log(" \x1b[1m\x1b[32m[+] LAUNCHED SYSTEM VIEW FOR:\x1b[0m \x1b[1m" + selected.title + "\x1b[0m\n");
|
|
704
|
+
console.log(` - \x1b[1mMockup File:\x1b[0m ${selected.fileName}`);
|
|
705
|
+
console.log(` - \x1b[1mFolder Path:\x1b[0m ${path.dirname(selected.fullPath)}`);
|
|
706
|
+
|
|
707
|
+
let sizeText = "Unknown";
|
|
708
|
+
try {
|
|
709
|
+
const stats = fs.statSync(selected.fullPath);
|
|
710
|
+
sizeText = `${(stats.size / 1024).toFixed(1)} KB`;
|
|
711
|
+
} catch (e) {}
|
|
712
|
+
console.log(` - \x1b[1mFile Size:\x1b[0m ${sizeText}`);
|
|
713
|
+
console.log("");
|
|
714
|
+
console.log(" ==================================================================");
|
|
715
|
+
console.log(" \x1b[36m[OS SYSTEM PREVIEW LAUNCHED]\x1b[0m");
|
|
716
|
+
console.log(" The mockup has been opened in your system's native image viewer.");
|
|
717
|
+
console.log(" ==================================================================\n");
|
|
718
|
+
console.log(" \x1b[1m\x1b[33m← Press Left Arrow to go BACK to list.\x1b[0m");
|
|
719
|
+
console.log(" \x1b[90mPress Esc or Ctrl+C to exit.\x1b[0m\n");
|
|
720
|
+
}
|
|
721
|
+
console.log("\x1b[1m\x1b[36m======================================================================\x1b[0m");
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
process.stdin.setRawMode(true);
|
|
725
|
+
process.stdin.resume();
|
|
726
|
+
process.stdin.setEncoding("utf8");
|
|
727
|
+
|
|
728
|
+
const cleanExit = () => {
|
|
729
|
+
process.stdin.setRawMode(false);
|
|
730
|
+
process.stdin.pause();
|
|
731
|
+
console.clear();
|
|
732
|
+
console.log("\n\x1b[32m[+] Exited Mockup Gallery Viewer.\x1b[0m\n");
|
|
733
|
+
process.exit(0);
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
renderMenu();
|
|
737
|
+
|
|
738
|
+
process.stdin.on("data", (key) => {
|
|
739
|
+
if (key === "\u0003" || key === "\u001b") {
|
|
740
|
+
cleanExit();
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (currentView === "LIST") {
|
|
744
|
+
if (key === "\u001b[A") {
|
|
745
|
+
selectedIndex = (selectedIndex - 1 + mockups.length) % mockups.length;
|
|
746
|
+
renderMenu();
|
|
747
|
+
}
|
|
748
|
+
else if (key === "\u001b[B") {
|
|
749
|
+
selectedIndex = (selectedIndex + 1) % mockups.length;
|
|
750
|
+
renderMenu();
|
|
751
|
+
}
|
|
752
|
+
else if (key === "\u001b[C" || key === "\r") {
|
|
753
|
+
currentView = "DETAIL";
|
|
754
|
+
const selected = mockups[selectedIndex];
|
|
755
|
+
openFileNatively(selected.fullPath);
|
|
756
|
+
renderMenu();
|
|
757
|
+
}
|
|
758
|
+
} else if (currentView === "DETAIL") {
|
|
759
|
+
if (key === "\u001b[D") {
|
|
760
|
+
currentView = "LIST";
|
|
761
|
+
renderMenu();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
const command = process.argv[2] || "help";
|
|
768
|
+
const args = process.argv.slice(3);
|
|
769
|
+
|
|
770
|
+
switch (command) {
|
|
189
771
|
case "install":
|
|
190
772
|
copySkills({ target: parseTarget(args, "both") });
|
|
191
773
|
break;
|
|
192
|
-
case "postinstall":
|
|
193
|
-
if (process.env.GENESIS_HARNESS_SKIP_POSTINSTALL === "1") {
|
|
194
|
-
process.exit(0);
|
|
195
|
-
}
|
|
774
|
+
case "postinstall":
|
|
775
|
+
if (process.env.GENESIS_HARNESS_SKIP_POSTINSTALL === "1") {
|
|
776
|
+
process.exit(0);
|
|
777
|
+
}
|
|
196
778
|
copySkills({ quiet: true, target: "both" });
|
|
197
779
|
break;
|
|
198
780
|
case "verify":
|
|
@@ -208,11 +790,32 @@ switch (command) {
|
|
|
208
790
|
}
|
|
209
791
|
}
|
|
210
792
|
break;
|
|
211
|
-
case "
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
793
|
+
case "status":
|
|
794
|
+
showStatus();
|
|
795
|
+
break;
|
|
796
|
+
case "docs":
|
|
797
|
+
showDocsStatus();
|
|
798
|
+
break;
|
|
799
|
+
case "remember":
|
|
800
|
+
rememberFact(args[0], args[1]);
|
|
801
|
+
break;
|
|
802
|
+
case "recall":
|
|
803
|
+
recallFacts(args[0]);
|
|
804
|
+
break;
|
|
805
|
+
case "forget":
|
|
806
|
+
forgetFact(args[0]);
|
|
807
|
+
break;
|
|
808
|
+
case "prime":
|
|
809
|
+
primeContext();
|
|
810
|
+
break;
|
|
811
|
+
case "view-mockup":
|
|
812
|
+
viewMockupsInteractive(args[0]);
|
|
813
|
+
break;
|
|
814
|
+
case "help":
|
|
815
|
+
case "--help":
|
|
816
|
+
case "-h":
|
|
817
|
+
usage(0);
|
|
818
|
+
break;
|
|
819
|
+
default:
|
|
820
|
+
usage(2);
|
|
821
|
+
}
|