codex-genesis-harness 0.1.7 → 0.1.8
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/COMPRESSED_CONTEXT.md +80 -0
- package/.codebase/CURRENT_STATE.md +37 -11
- package/.codebase/DEPENDENCY_GRAPH.md +14 -1
- package/.codebase/IMPLEMENTATION_HANDOFF.md +34 -336
- package/.codebase/KNOWN_PROBLEMS.md +54 -3
- package/.codebase/MODULE_INDEX.md +8 -0
- package/.codebase/PIPELINE_FLOW.md +7 -5
- package/.codebase/RECOVERY_POINTS.md +17 -78
- package/.codebase/TECH_DEBT.md +6 -0
- package/.codebase/TEST_MATRIX.md +4 -3
- package/.codebase/VISUAL_GRAPH.md +127 -0
- package/.codebase/context-policy.json +68 -0
- package/.codebase/memories/lessons_learned.md +21 -0
- package/.codebase/memories/preferences.md +17 -0
- package/.codebase/state.json +45 -24
- package/.codex/skills/genesis-architecture/SKILL.md +5 -0
- package/.codex/skills/genesis-debug-guide/SKILL.md +10 -4
- package/.codex/skills/genesis-docs-automation/SKILL.md +52 -973
- package/.codex/skills/genesis-executing-plans/SKILL.md +54 -0
- package/.codex/skills/genesis-executing-plans/agents/openai.yaml +6 -0
- package/.codex/skills/genesis-executing-plans/checklists/.gitkeep +0 -0
- package/.codex/skills/genesis-executing-plans/examples/.gitkeep +0 -0
- package/.codex/skills/genesis-executing-plans/templates/.gitkeep +0 -0
- package/.codex/skills/genesis-harness/SKILL.md +64 -1385
- package/.codex/skills/genesis-harness/scripts/check-docs-sync.sh +3 -3
- package/.codex/skills/genesis-harness/scripts/init-planning.sh +1 -1
- package/.codex/skills/genesis-new-design/SKILL.md +4 -1
- package/.codex/skills/genesis-new-design/agents/openai.yaml +2 -0
- package/.codex/skills/genesis-observability-automation/SKILL.md +69 -303
- package/.codex/skills/genesis-observability-automation/references/common-mistakes-and-recovery.md +84 -0
- package/.codex/skills/genesis-observability-automation/references/workflow-phases.md +78 -0
- package/.codex/skills/genesis-performance-profiling/SKILL.md +1 -22
- package/.codex/skills/genesis-performance-profiling/agents/openai.yaml +1 -1
- package/.codex/skills/genesis-planning/SKILL.md +6 -1
- package/.codex/skills/genesis-release/SKILL.md +5 -0
- package/.codex/skills/genesis-research-first/SKILL.md +6 -0
- package/.codex/skills/genesis-spec-propagation/SKILL.md +52 -504
- package/.codex/skills/genesis-test-driven-development/SKILL.md +55 -0
- package/.codex/skills/genesis-test-driven-development/agents/openai.yaml +6 -0
- package/.codex/skills/genesis-test-driven-development/checklists/.gitkeep +0 -0
- package/.codex/skills/genesis-test-driven-development/examples/.gitkeep +0 -0
- package/.codex/skills/genesis-test-driven-development/templates/.gitkeep +0 -0
- package/.codex/skills/genesis-upgrade-design/SKILL.md +4 -2
- package/.codex/skills/genesis-upgrade-design/agents/openai.yaml +2 -0
- package/.codex/skills/genesis-using-git-worktrees/SKILL.md +54 -0
- package/.codex/skills/genesis-using-git-worktrees/agents/openai.yaml +6 -0
- package/.codex/skills/genesis-using-git-worktrees/checklists/.gitkeep +0 -0
- package/.codex/skills/genesis-using-git-worktrees/examples/.gitkeep +0 -0
- package/.codex/skills/genesis-using-git-worktrees/templates/.gitkeep +0 -0
- package/.codex/skills/genesis-verification-before-completion/SKILL.md +53 -0
- package/.codex/skills/genesis-verification-before-completion/agents/openai.yaml +6 -0
- package/.codex/skills/genesis-verification-before-completion/checklists/.gitkeep +0 -0
- package/.codex/skills/genesis-verification-before-completion/examples/.gitkeep +0 -0
- package/.codex/skills/genesis-verification-before-completion/templates/.gitkeep +0 -0
- package/.codex/skills/spec-impact-engine/SKILL.md +77 -500
- package/.codex/skills/spec-impact-engine/checklists/checklist.md +10 -0
- package/.codex-plugin/plugin.json +3 -4
- package/CHANGELOG.md +4 -1
- package/README.EN.md +32 -17
- package/README.VI.md +35 -19
- package/README.md +48 -10
- package/VERSION +1 -1
- package/bin/genesis-harness.js +735 -5
- package/contracts/features/registry-schema.json +15 -0
- package/contracts/observability/agent-run-schema.json +34 -0
- package/contracts/observability/failure-schema.json +35 -0
- package/contracts/ui/auth/login-screen-contract.json +43 -0
- package/features/REGISTRY.md +63 -0
- package/features/SCOPE-template.md +65 -0
- package/fixtures/planning/MOCKUP_PROMPT_TEMPLATE.md +16 -0
- package/observability/agent-runs/sample-run.json +13 -0
- package/observability/decision-logs/sample-decision.md +43 -0
- package/observability/failures/sample-failure.json +12 -0
- package/package.json +9 -3
- package/playwright/e2e/app-template.spec.js +37 -0
- package/playwright/e2e/auth/login-screen.spec.js +65 -0
- package/playwright/e2e/web-template.spec.js +28 -0
- package/scripts/check-scope.sh +100 -0
- package/scripts/cold-start-check.js +133 -0
- package/scripts/install.sh +4 -0
- package/scripts/prompt_sentinel.js +35 -4
- package/scripts/run-evals.sh +119 -3
- package/scripts/scratch_parser.js +49 -0
- package/scripts/spec_visual_sync.js +1 -1
- package/scripts/test_generator.js +2 -2
- package/scripts/uninstall.sh +4 -0
- package/scripts/verify.sh +16 -1
- package/tests/integration/cli-smoke.test.js +103 -0
- package/tests/unit/feature_registry.test.js +152 -0
- package/tests/unit/prompt_sentinel.test.js +1 -1
- package/tests/unit/spec_visual_sync.test.js +1 -1
- package/tests/unit/test_generator.test.js +1 -1
- package/playwright/e2e/e2e-template.md +0 -4
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* cold-start-check.js
|
|
6
|
+
* L03 – Repository is the Single Source of Truth
|
|
7
|
+
*
|
|
8
|
+
* Automated cold-start test: verifies a brand-new agent can answer the
|
|
9
|
+
* 5 fundamental questions from the repository alone, without external knowledge.
|
|
10
|
+
*
|
|
11
|
+
* Usage: node scripts/cold-start-check.js
|
|
12
|
+
* Exit: 0 = all 5 questions answerable, 1 = gap detected
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require("fs");
|
|
16
|
+
const path = require("path");
|
|
17
|
+
|
|
18
|
+
const repoRoot = path.resolve(__dirname, "..");
|
|
19
|
+
|
|
20
|
+
const fail = (msg) => {
|
|
21
|
+
console.error(`cold-start FAIL: ${msg}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const check = (condition, failMsg) => {
|
|
26
|
+
if (!condition) fail(failMsg);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const readFile = (relPath) => {
|
|
30
|
+
const abs = path.join(repoRoot, relPath);
|
|
31
|
+
if (!fs.existsSync(abs)) fail(`Required file missing: ${relPath}`);
|
|
32
|
+
return fs.readFileSync(abs, "utf8");
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
console.log("Running cold-start check (L03 — Repo as Source of Truth)...\n");
|
|
36
|
+
|
|
37
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
38
|
+
// Q1: What is this project?
|
|
39
|
+
// Answer must be findable in AGENTS.md or README.md
|
|
40
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
console.log("Q1: What is this project?");
|
|
42
|
+
const agents = readFile("AGENTS.md");
|
|
43
|
+
check(
|
|
44
|
+
agents.length > 100,
|
|
45
|
+
"Q1 FAIL: AGENTS.md is too short to answer 'what is this project?'"
|
|
46
|
+
);
|
|
47
|
+
const readme = readFile("README.md");
|
|
48
|
+
check(
|
|
49
|
+
readme.includes("genesis-harness") || readme.includes("Genesis"),
|
|
50
|
+
"Q1 FAIL: README.md does not describe the project by name"
|
|
51
|
+
);
|
|
52
|
+
console.log(" ✅ Answerable from AGENTS.md + README.md\n");
|
|
53
|
+
|
|
54
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
55
|
+
// Q2: How do I run it?
|
|
56
|
+
// Answer must be findable in AGENTS.md with npm run commands
|
|
57
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
58
|
+
console.log("Q2: How do I run/verify it?");
|
|
59
|
+
check(
|
|
60
|
+
agents.includes("npm run verify") || agents.includes("scripts/verify.sh"),
|
|
61
|
+
"Q2 FAIL: AGENTS.md does not document how to run verification"
|
|
62
|
+
);
|
|
63
|
+
const pkg = JSON.parse(readFile("package.json"));
|
|
64
|
+
check(
|
|
65
|
+
pkg.scripts && pkg.scripts.verify,
|
|
66
|
+
"Q2 FAIL: package.json missing 'verify' script"
|
|
67
|
+
);
|
|
68
|
+
console.log(" ✅ Answerable from AGENTS.md + package.json\n");
|
|
69
|
+
|
|
70
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
71
|
+
// Q3: How do I test it?
|
|
72
|
+
// Answer must be findable in TEST_MATRIX.md
|
|
73
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
74
|
+
console.log("Q3: How do I run the tests?");
|
|
75
|
+
const testMatrix = readFile(".codebase/TEST_MATRIX.md");
|
|
76
|
+
check(
|
|
77
|
+
testMatrix.includes("verify.sh") && testMatrix.includes("run-evals.sh"),
|
|
78
|
+
"Q3 FAIL: TEST_MATRIX.md does not document test commands"
|
|
79
|
+
);
|
|
80
|
+
check(
|
|
81
|
+
fs.existsSync(path.join(repoRoot, "scripts", "verify.sh")),
|
|
82
|
+
"Q3 FAIL: scripts/verify.sh does not exist"
|
|
83
|
+
);
|
|
84
|
+
check(
|
|
85
|
+
fs.existsSync(path.join(repoRoot, "scripts", "run-evals.sh")),
|
|
86
|
+
"Q3 FAIL: scripts/run-evals.sh does not exist"
|
|
87
|
+
);
|
|
88
|
+
console.log(" ✅ Answerable from TEST_MATRIX.md + scripts/\n");
|
|
89
|
+
|
|
90
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
91
|
+
// Q4: What is the high-level architecture?
|
|
92
|
+
// Answer must be findable in MODULE_INDEX.md + VISUAL_GRAPH.md
|
|
93
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
94
|
+
console.log("Q4: What is the architecture?");
|
|
95
|
+
const moduleIndex = readFile(".codebase/MODULE_INDEX.md");
|
|
96
|
+
check(
|
|
97
|
+
moduleIndex.includes(".codex/skills/") && moduleIndex.includes("contracts/"),
|
|
98
|
+
"Q4 FAIL: MODULE_INDEX.md does not describe key architectural components"
|
|
99
|
+
);
|
|
100
|
+
const visualGraph = readFile(".codebase/VISUAL_GRAPH.md");
|
|
101
|
+
check(
|
|
102
|
+
visualGraph.includes("```mermaid"),
|
|
103
|
+
"Q4 FAIL: VISUAL_GRAPH.md does not contain a Mermaid architecture diagram"
|
|
104
|
+
);
|
|
105
|
+
console.log(" ✅ Answerable from MODULE_INDEX.md + VISUAL_GRAPH.md\n");
|
|
106
|
+
|
|
107
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
108
|
+
// Q5: Where am I / what's the current state?
|
|
109
|
+
// Answer must be findable in CURRENT_STATE.md + state.json
|
|
110
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
111
|
+
console.log("Q5: Where are we / what is the current state?");
|
|
112
|
+
const currentState = readFile(".codebase/CURRENT_STATE.md");
|
|
113
|
+
check(
|
|
114
|
+
currentState.includes("2026"),
|
|
115
|
+
"Q5 FAIL: CURRENT_STATE.md does not have a current-year timestamp (may be stale)"
|
|
116
|
+
);
|
|
117
|
+
const stateJson = JSON.parse(readFile(".codebase/state.json"));
|
|
118
|
+
check(
|
|
119
|
+
stateJson.current_state,
|
|
120
|
+
"Q5 FAIL: state.json missing 'current_state' field"
|
|
121
|
+
);
|
|
122
|
+
check(
|
|
123
|
+
stateJson.completed_at || stateJson.active_work,
|
|
124
|
+
"Q5 FAIL: state.json missing completion/active state markers"
|
|
125
|
+
);
|
|
126
|
+
console.log(" ✅ Answerable from CURRENT_STATE.md + state.json\n");
|
|
127
|
+
|
|
128
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
129
|
+
// Summary
|
|
130
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
131
|
+
console.log("━".repeat(50));
|
|
132
|
+
console.log("cold-start check passed — all 5 questions answerable");
|
|
133
|
+
console.log("Repository passes L03: Single Source of Truth test.");
|
package/scripts/install.sh
CHANGED
|
@@ -24,6 +24,10 @@ skill_names=(
|
|
|
24
24
|
genesis-research-first
|
|
25
25
|
genesis-release
|
|
26
26
|
spec-impact-engine
|
|
27
|
+
genesis-executing-plans
|
|
28
|
+
genesis-test-driven-development
|
|
29
|
+
genesis-verification-before-completion
|
|
30
|
+
genesis-using-git-worktrees
|
|
27
31
|
)
|
|
28
32
|
source_root="$repo_root/.codex/skills"
|
|
29
33
|
codex_home="${CODEX_HOME:-$HOME/.codex}"
|
|
@@ -2,13 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Pre-emptive Prompt Sentinel
|
|
5
|
-
* Part of Genesis Codex Harness v0.1.
|
|
5
|
+
* Part of Genesis Codex Harness v0.1.8
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const { execSync } = require('child_process');
|
|
11
11
|
|
|
12
|
+
function readJsonIfExists(filePath) {
|
|
13
|
+
if (!fs.existsSync(filePath)) return null;
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function loadContextPolicy() {
|
|
22
|
+
const defaultPolicy = {
|
|
23
|
+
token_budget: 12000,
|
|
24
|
+
compact_at: 0.7,
|
|
25
|
+
hard_stop_at: 0.85
|
|
26
|
+
};
|
|
27
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
28
|
+
const packagedPolicy = readJsonIfExists(path.join(packageRoot, '.codebase', 'context-policy.json'));
|
|
29
|
+
const projectPolicy = readJsonIfExists(path.resolve(process.cwd(), '.codebase', 'context-policy.json'));
|
|
30
|
+
return {
|
|
31
|
+
...defaultPolicy,
|
|
32
|
+
...(packagedPolicy || {}),
|
|
33
|
+
...(projectPolicy || {})
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
12
37
|
function printUsage() {
|
|
13
38
|
console.log('Usage:');
|
|
14
39
|
console.log(' node scripts/prompt_sentinel.js --check <file-or-log-path> [--threshold <tokens>]');
|
|
@@ -21,7 +46,8 @@ if (args.length < 2 || args[0] !== '--check') {
|
|
|
21
46
|
}
|
|
22
47
|
|
|
23
48
|
const targetPath = path.resolve(process.cwd(), args[1]);
|
|
24
|
-
|
|
49
|
+
const policy = loadContextPolicy();
|
|
50
|
+
let threshold = Math.round(Number(policy.token_budget || 12000) * Number(policy.compact_at || 0.7));
|
|
25
51
|
|
|
26
52
|
const thresholdIndex = args.indexOf('--threshold');
|
|
27
53
|
if (thresholdIndex !== -1 && args[thresholdIndex + 1]) {
|
|
@@ -40,6 +66,7 @@ const estimatedTokens = Math.ceil(fileSizeChars / 4);
|
|
|
40
66
|
console.log(`[Prompt Sentinel] Evaluating token load for: ${path.basename(targetPath)}`);
|
|
41
67
|
console.log(` - File size: ${fileSizeChars} characters`);
|
|
42
68
|
console.log(` - Estimated token payload: ${estimatedTokens} tokens (Safety threshold: ${threshold})`);
|
|
69
|
+
console.log(` - LeanCTX policy budget: ${policy.token_budget || 12000} tokens`);
|
|
43
70
|
|
|
44
71
|
if (estimatedTokens > threshold) {
|
|
45
72
|
console.warn(`\n[WARNING] [PROMPT SENTINEL] Payload of ${estimatedTokens} tokens exceeds the safety threshold of ${threshold}!`);
|
|
@@ -47,8 +74,12 @@ if (estimatedTokens > threshold) {
|
|
|
47
74
|
console.warn(`[ACTION] Automatically triggering context compaction and log optimization...\n`);
|
|
48
75
|
|
|
49
76
|
// Trigger compact-context script if it exists
|
|
50
|
-
const
|
|
51
|
-
|
|
77
|
+
const compactionScriptCandidates = [
|
|
78
|
+
path.resolve(process.cwd(), 'scripts/compact-context.sh'),
|
|
79
|
+
path.resolve(__dirname, '..', '.codex', 'skills', 'genesis-harness', 'scripts', 'compact-context.sh')
|
|
80
|
+
];
|
|
81
|
+
const compactionScript = compactionScriptCandidates.find(candidate => fs.existsSync(candidate));
|
|
82
|
+
if (compactionScript) {
|
|
52
83
|
try {
|
|
53
84
|
console.log(`Executing: ${compactionScript}`);
|
|
54
85
|
const output = execSync(`bash "${compactionScript}"`, { encoding: 'utf8' });
|
package/scripts/run-evals.sh
CHANGED
|
@@ -26,6 +26,10 @@ skill_names=(
|
|
|
26
26
|
genesis-research-first
|
|
27
27
|
genesis-release
|
|
28
28
|
spec-impact-engine
|
|
29
|
+
genesis-executing-plans
|
|
30
|
+
genesis-test-driven-development
|
|
31
|
+
genesis-verification-before-completion
|
|
32
|
+
genesis-using-git-worktrees
|
|
29
33
|
)
|
|
30
34
|
|
|
31
35
|
fail() {
|
|
@@ -40,12 +44,44 @@ assert_file() {
|
|
|
40
44
|
assert_contains() {
|
|
41
45
|
local file="$1"
|
|
42
46
|
local text="$2"
|
|
43
|
-
grep -
|
|
47
|
+
grep -Fq -- "$text" "$file" || fail "missing '$text' in ${file#$repo_root/}"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
assert_not_contains() {
|
|
51
|
+
local file="$1"
|
|
52
|
+
local text="$2"
|
|
53
|
+
! grep -Fq -- "$text" "$file" || fail "unexpected '$text' in ${file#$repo_root/}"
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
assert_file "$repo_root/.codex-plugin/plugin.json"
|
|
47
57
|
assert_contains "$repo_root/.codex-plugin/plugin.json" '"skills"'
|
|
48
58
|
assert_contains "$repo_root/.codex-plugin/plugin.json" '"genesis-skill-set"'
|
|
59
|
+
assert_contains "$repo_root/.codex-plugin/plugin.json" '$genesis-pipeline-orchestration'
|
|
60
|
+
assert_contains "$repo_root/.codex-plugin/plugin.json" '$genesis-api-contract'
|
|
61
|
+
assert_not_contains "$repo_root/.codex-plugin/plugin.json" '$pipeline-orchestration-skill'
|
|
62
|
+
assert_not_contains "$repo_root/.codex-plugin/plugin.json" '$api-contract-skill'
|
|
63
|
+
assert_contains "$harness_dir/SKILL.md" '/genesis-init'
|
|
64
|
+
assert_contains "$repo_root/.codex/SKILLS_INDEX.md" '/genesis-init'
|
|
65
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness docs-gate'
|
|
66
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'check-docs-sync.sh'
|
|
67
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'npx genesis-harness docs-gate'
|
|
68
|
+
assert_contains "$harness_dir/scripts/check-docs-sync.sh" '.codebase/'
|
|
69
|
+
assert_contains "$harness_dir/scripts/check-docs-sync.sh" 'README(\.[A-Z]{2})?\.md'
|
|
70
|
+
assert_contains "$repo_root/.codebase/VISUAL_GRAPH.md" 'genesis-harness'
|
|
71
|
+
assert_contains "$repo_root/.codebase/PIPELINE_FLOW.md" 'fixture --> contracts["Update contracts when behavior changes"]'
|
|
72
|
+
assert_contains "$repo_root/.codebase/PIPELINE_FLOW.md" 'contracts --> impl'
|
|
73
|
+
assert_not_contains "$repo_root/.codebase/VISUAL_GRAPH.md" 'Đăng nhập'
|
|
74
|
+
assert_not_contains "$repo_root/.codebase/VISUAL_GRAPH.md" 'src/auth.js'
|
|
75
|
+
assert_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'Harness Drift Gate Hardening'
|
|
76
|
+
assert_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" '2026-06-03'
|
|
77
|
+
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" '_[Name and reference]_'
|
|
78
|
+
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'Feature A'
|
|
79
|
+
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'YYYY-MM-DD'
|
|
80
|
+
assert_contains "$repo_root/.codebase/state.json" '"completed_at": "2026-06-03'
|
|
81
|
+
assert_contains "$repo_root/.codebase/CURRENT_STATE.md" '2026-06-03'
|
|
82
|
+
assert_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'npm run eval'
|
|
83
|
+
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'rtk '
|
|
84
|
+
assert_not_contains "$repo_root/.codebase/state.json" 'rtk '
|
|
49
85
|
|
|
50
86
|
for ref in workflows.md planning-schema.md research-rubric.md quality-rubric.md; do
|
|
51
87
|
assert_file "$harness_dir/references/$ref"
|
|
@@ -64,6 +100,7 @@ assert_contains "$repo_root/bin/genesis-harness.js" '--target agents|legacy|both
|
|
|
64
100
|
assert_contains "$repo_root/package.json" '".codex-plugin"'
|
|
65
101
|
assert_contains "$repo_root/package.json" '".codebase"'
|
|
66
102
|
assert_contains "$repo_root/package.json" '"contracts"'
|
|
103
|
+
assert_contains "$repo_root/package.json" '"features"'
|
|
67
104
|
assert_contains "$repo_root/package.json" '"fixtures"'
|
|
68
105
|
assert_contains "$repo_root/package.json" '"playwright"'
|
|
69
106
|
assert_contains "$repo_root/package.json" '"observability"'
|
|
@@ -94,21 +131,100 @@ for skill_name in "${skill_names[@]}" project-genesis-harness; do
|
|
|
94
131
|
[ ! -e "$tmp/codex/skills/$skill_name" ] || fail "legacy uninstall target remains: $skill_name"
|
|
95
132
|
done
|
|
96
133
|
|
|
134
|
+
install_seed_tmp="$(mktemp -d)"
|
|
135
|
+
printf '{"name":"leanctx-install-fixture"}\n' > "$install_seed_tmp/package.json"
|
|
136
|
+
(
|
|
137
|
+
cd "$install_seed_tmp"
|
|
138
|
+
CODEX_HOME="$tmp/codex" GENESIS_HARNESS_HOME="$tmp/agents" node "$repo_root/bin/genesis-harness.js" install --target agents >/dev/null
|
|
139
|
+
)
|
|
140
|
+
assert_file "$install_seed_tmp/.codebase/context-policy.json"
|
|
141
|
+
assert_contains "$install_seed_tmp/.codebase/context-policy.json" '"token_budget": 12000'
|
|
142
|
+
|
|
97
143
|
assert_contains "$repo_root/bin/genesis-harness.js" "genesis-harness remember"
|
|
98
144
|
assert_contains "$repo_root/bin/genesis-harness.js" "genesis-harness recall"
|
|
99
|
-
assert_contains "$repo_root/bin/genesis-harness.js"
|
|
100
|
-
assert_contains "$repo_root/bin/genesis-harness.js"
|
|
145
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness docs-gate'
|
|
146
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness verify-gate'
|
|
147
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness cold-start'
|
|
148
|
+
assert_contains "$repo_root/bin/genesis-harness.js" "genesis-harness remember"
|
|
149
|
+
assert_contains "$repo_root/bin/genesis-harness.js" "genesis-harness leanctx"
|
|
150
|
+
assert_contains "$repo_root/bin/genesis-harness.js" "seedLeanCtxPolicy"
|
|
101
151
|
assert_contains "$repo_root/bin/genesis-harness.js" "genesis-harness view-mockup"
|
|
152
|
+
assert_file "$repo_root/.codebase/context-policy.json"
|
|
153
|
+
assert_contains "$repo_root/.codebase/context-policy.json" '"token_budget"'
|
|
154
|
+
assert_contains "$repo_root/scripts/prompt_sentinel.js" 'context-policy.json'
|
|
155
|
+
assert_contains "$repo_root/README.md" 'LeanCTX'
|
|
156
|
+
assert_contains "$repo_root/README.VI.md" 'LeanCTX'
|
|
157
|
+
assert_contains "$repo_root/README.EN.md" 'LeanCTX'
|
|
102
158
|
|
|
103
159
|
# Test Beads Memory Commands
|
|
104
160
|
node "$repo_root/bin/genesis-harness.js" remember evalsmoke "Verify that evals can store facts." >/dev/null
|
|
105
161
|
node "$repo_root/bin/genesis-harness.js" recall evalsmoke | grep -q "Verify that evals" || fail "recall failed to find test fact"
|
|
106
162
|
node "$repo_root/bin/genesis-harness.js" prime | grep -q "Verify that evals" || fail "prime failed to include test fact"
|
|
163
|
+
node "$repo_root/bin/genesis-harness.js" leanctx | grep -q "rtk optional" || fail "leanctx must keep rtk optional"
|
|
107
164
|
|
|
108
165
|
# Find the ID of the stored fact to forget it
|
|
109
166
|
bead_id=$(node "$repo_root/bin/genesis-harness.js" recall evalsmoke | grep -o "\[[0-9a-f]\{6\}\]" | head -n 1 | tr -d '[]')
|
|
110
167
|
node "$repo_root/bin/genesis-harness.js" forget "$bead_id" >/dev/null
|
|
111
168
|
node "$repo_root/bin/genesis-harness.js" recall evalsmoke | grep -q "Verify that evals" && fail "forget failed to delete test fact" || true
|
|
112
169
|
|
|
170
|
+
for unit_test in "$repo_root"/tests/unit/*.test.js; do
|
|
171
|
+
node "$unit_test" >/dev/null
|
|
172
|
+
done
|
|
173
|
+
|
|
174
|
+
node "$repo_root/tests/integration/cli-smoke.test.js" >/dev/null
|
|
175
|
+
|
|
176
|
+
sync_tmp="$(mktemp -d)"
|
|
177
|
+
mkdir -p "$sync_tmp/.codebase" "$sync_tmp/src"
|
|
178
|
+
printf '# Current State: Sync Fixture\n' > "$sync_tmp/.codebase/CURRENT_STATE.md"
|
|
179
|
+
printf 'export const answer = 42;\n' > "$sync_tmp/src/index.js"
|
|
180
|
+
(
|
|
181
|
+
cd "$sync_tmp"
|
|
182
|
+
node "$repo_root/bin/genesis-harness.js" sync >/dev/null
|
|
183
|
+
)
|
|
184
|
+
assert_contains "$sync_tmp/.codebase/VISUAL_GRAPH.md" 'Harness Relationship Map'
|
|
185
|
+
assert_contains "$sync_tmp/.codebase/VISUAL_GRAPH.md" 'genesis-harness docs-gate'
|
|
186
|
+
assert_contains "$sync_tmp/.codebase/VISUAL_GRAPH.md" '```mermaid'
|
|
187
|
+
assert_not_contains "$sync_tmp/.codebase/VISUAL_GRAPH.md" 'Đăng nhập'
|
|
188
|
+
assert_not_contains "$sync_tmp/.codebase/VISUAL_GRAPH.md" 'src/auth.js'
|
|
189
|
+
|
|
190
|
+
# Test Packaged Install (Tarball)
|
|
191
|
+
echo "Running tarball smoke test..."
|
|
192
|
+
pack_tmp="$(mktemp -d)"
|
|
193
|
+
npm pack --pack-destination "$pack_tmp" >/dev/null
|
|
194
|
+
tarball_path=$(ls "$pack_tmp"/*.tgz | head -n 1)
|
|
195
|
+
[ -f "$tarball_path" ] || fail "npm pack failed to produce tarball"
|
|
196
|
+
(
|
|
197
|
+
cd "$pack_tmp"
|
|
198
|
+
tar xzf "$tarball_path"
|
|
199
|
+
cd package
|
|
200
|
+
bash scripts/verify.sh .codex/skills >/dev/null || exit 1
|
|
201
|
+
) || fail "verification failed on packaged tarball"
|
|
202
|
+
rm -rf "$pack_tmp"
|
|
203
|
+
|
|
204
|
+
# L08 — Feature Registry as Harness Primitive
|
|
205
|
+
# Ensures features/REGISTRY.md exists and is schema-valid with verify_cmd per feature.
|
|
206
|
+
assert_file "$repo_root/features/REGISTRY.md"
|
|
207
|
+
assert_contains "$repo_root/features/REGISTRY.md" "| id |"
|
|
208
|
+
assert_contains "$repo_root/features/REGISTRY.md" "| status |"
|
|
209
|
+
assert_contains "$repo_root/features/REGISTRY.md" "| verify_cmd |"
|
|
210
|
+
assert_file "$repo_root/contracts/features/registry-schema.json"
|
|
211
|
+
assert_contains "$repo_root/contracts/features/registry-schema.json" '"required_columns"'
|
|
212
|
+
assert_contains "$repo_root/.codebase/MODULE_INDEX.md" "features/REGISTRY.md"
|
|
213
|
+
|
|
214
|
+
# L11 — Observability Live Data
|
|
215
|
+
# Ensures observability directories contain actual schema-backed data, not empty scaffolding.
|
|
216
|
+
assert_file "$repo_root/contracts/observability/agent-run-schema.json"
|
|
217
|
+
assert_contains "$repo_root/contracts/observability/agent-run-schema.json" '"required_fields"'
|
|
218
|
+
assert_file "$repo_root/contracts/observability/failure-schema.json"
|
|
219
|
+
assert_contains "$repo_root/contracts/observability/failure-schema.json" '"required_fields"'
|
|
220
|
+
assert_file "$repo_root/observability/agent-runs/sample-run.json"
|
|
221
|
+
assert_contains "$repo_root/observability/agent-runs/sample-run.json" '"session_id"'
|
|
222
|
+
assert_contains "$repo_root/observability/agent-runs/sample-run.json" '"outcome"'
|
|
223
|
+
assert_file "$repo_root/observability/failures/sample-failure.json"
|
|
224
|
+
assert_contains "$repo_root/observability/failures/sample-failure.json" '"error_type"'
|
|
225
|
+
assert_file "$repo_root/observability/decision-logs/sample-decision.md"
|
|
226
|
+
# Must be a real decision, not the blank template
|
|
227
|
+
! grep -Fq "What changed." "$repo_root/observability/decision-logs/sample-decision.md" \
|
|
228
|
+
|| fail "L11: decision-logs/sample-decision.md must be a real decision, not a blank template"
|
|
113
229
|
|
|
114
230
|
echo "evals passed"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const parser = require('@babel/parser');
|
|
3
|
+
const traverse = require('@babel/traverse').default;
|
|
4
|
+
|
|
5
|
+
const code = `
|
|
6
|
+
import { something } from './my-module';
|
|
7
|
+
const x = require('another-module');
|
|
8
|
+
export class MyClass {}
|
|
9
|
+
export function myFunc() {}
|
|
10
|
+
export const myArrow = async () => {};
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
const ast = parser.parse(code, {
|
|
14
|
+
sourceType: 'module',
|
|
15
|
+
plugins: ['typescript']
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const exportsList = [];
|
|
19
|
+
const importsList = [];
|
|
20
|
+
|
|
21
|
+
traverse(ast, {
|
|
22
|
+
ExportNamedDeclaration(path) {
|
|
23
|
+
const decl = path.node.declaration;
|
|
24
|
+
if (decl) {
|
|
25
|
+
if (decl.type === 'ClassDeclaration' && decl.id) {
|
|
26
|
+
exportsList.push('class ' + decl.id.name);
|
|
27
|
+
} else if (decl.type === 'FunctionDeclaration' && decl.id) {
|
|
28
|
+
exportsList.push('function ' + decl.id.name);
|
|
29
|
+
} else if (decl.type === 'VariableDeclaration') {
|
|
30
|
+
decl.declarations.forEach(d => {
|
|
31
|
+
if (d.id) exportsList.push('const ' + d.id.name);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
ImportDeclaration(path) {
|
|
37
|
+
importsList.push(path.node.source.value);
|
|
38
|
+
},
|
|
39
|
+
CallExpression(path) {
|
|
40
|
+
if (path.node.callee.name === 'require' && path.node.arguments.length > 0) {
|
|
41
|
+
if (path.node.arguments[0].type === 'StringLiteral') {
|
|
42
|
+
importsList.push(path.node.arguments[0].value);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
console.log('Exports:', exportsList);
|
|
49
|
+
console.log('Imports:', importsList);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Contract-Driven Test Auto-Generator
|
|
5
|
-
* Part of Genesis Codex Harness v0.1.
|
|
5
|
+
* Part of Genesis Codex Harness v0.1.8
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const fs = require('fs');
|
|
@@ -62,7 +62,7 @@ const requiredFields = schema.required || Object.keys(properties);
|
|
|
62
62
|
// Construct test cases content
|
|
63
63
|
let testSuiteCode = `/**
|
|
64
64
|
* Integration Test for Endpoint: /api/${endpoint}
|
|
65
|
-
* Automatically generated by Genesis Contract-Driven Test Generator (v0.1.
|
|
65
|
+
* Automatically generated by Genesis Contract-Driven Test Generator (v0.1.8)
|
|
66
66
|
* Strictly Enforces TDD Contract Compliance.
|
|
67
67
|
*/
|
|
68
68
|
|
package/scripts/uninstall.sh
CHANGED
|
@@ -23,6 +23,10 @@ skill_names=(
|
|
|
23
23
|
genesis-research-first
|
|
24
24
|
genesis-release
|
|
25
25
|
spec-impact-engine
|
|
26
|
+
genesis-executing-plans
|
|
27
|
+
genesis-test-driven-development
|
|
28
|
+
genesis-verification-before-completion
|
|
29
|
+
genesis-using-git-worktrees
|
|
26
30
|
project-genesis-harness
|
|
27
31
|
)
|
|
28
32
|
codex_home="${CODEX_HOME:-$HOME/.codex}"
|
package/scripts/verify.sh
CHANGED
|
@@ -25,6 +25,10 @@ skill_names=(
|
|
|
25
25
|
genesis-research-first
|
|
26
26
|
genesis-release
|
|
27
27
|
spec-impact-engine
|
|
28
|
+
genesis-executing-plans
|
|
29
|
+
genesis-test-driven-development
|
|
30
|
+
genesis-verification-before-completion
|
|
31
|
+
genesis-using-git-worktrees
|
|
28
32
|
)
|
|
29
33
|
|
|
30
34
|
required_memory_files=(
|
|
@@ -117,7 +121,14 @@ required_scripts=(
|
|
|
117
121
|
run-verify-loop.sh
|
|
118
122
|
)
|
|
119
123
|
|
|
124
|
+
max_skill_lines=500
|
|
125
|
+
|
|
120
126
|
fail() {
|
|
127
|
+
if [ "${VIBE_MODE:-0}" = "1" ]; then
|
|
128
|
+
echo "verify WARN (VIBE_MODE): $*" >&2
|
|
129
|
+
echo "- [$(date -u +"%Y-%m-%dT%H:%M:%SZ")] VIBE_MODE Bypass: Verify check failed - $*" >> "$repo_root/.codebase/TECH_DEBT.md"
|
|
130
|
+
return 0
|
|
131
|
+
fi
|
|
121
132
|
echo "verify failed: $*" >&2
|
|
122
133
|
exit 1
|
|
123
134
|
}
|
|
@@ -172,9 +183,12 @@ verify_repository_harness
|
|
|
172
183
|
verify_skill_metadata() {
|
|
173
184
|
local skill_dir="$1"
|
|
174
185
|
local expected_name="$2"
|
|
186
|
+
local skill_lines
|
|
175
187
|
|
|
176
188
|
[ -f "$skill_dir/SKILL.md" ] || fail "missing SKILL.md: $skill_dir"
|
|
177
189
|
[ -f "$skill_dir/agents/openai.yaml" ] || fail "missing agents/openai.yaml: $skill_dir"
|
|
190
|
+
skill_lines="$(wc -l < "$skill_dir/SKILL.md" | tr -d ' ')"
|
|
191
|
+
[ "$skill_lines" -le "$max_skill_lines" ] || fail "SKILL.md exceeds ${max_skill_lines} lines ($skill_lines): $skill_dir"
|
|
178
192
|
grep -q "^name: $expected_name[[:space:]]*$" "$skill_dir/SKILL.md" || fail "invalid skill name frontmatter (expected 'name: $expected_name'): $skill_dir"
|
|
179
193
|
grep -q '^description:' "$skill_dir/SKILL.md" || fail "missing description frontmatter: $skill_dir"
|
|
180
194
|
grep -q 'default_prompt:' "$skill_dir/agents/openai.yaml" || fail "missing default_prompt: $skill_dir"
|
|
@@ -246,6 +260,7 @@ verify_minimal_skill() {
|
|
|
246
260
|
local skill_dir="$1"
|
|
247
261
|
|
|
248
262
|
[ -d "$skill_dir/templates" ] || fail "missing templates/: $skill_dir"
|
|
263
|
+
[ -d "$skill_dir/checklists" ] || fail "missing checklists/: $skill_dir"
|
|
249
264
|
[ -d "$skill_dir/examples" ] || fail "missing examples/: $skill_dir"
|
|
250
265
|
}
|
|
251
266
|
|
|
@@ -264,7 +279,7 @@ verify_one() {
|
|
|
264
279
|
genesis-new-design|genesis-upgrade-design)
|
|
265
280
|
verify_design_skill "$skill_dir" "$dir_name"
|
|
266
281
|
;;
|
|
267
|
-
genesis-architecture|genesis-planning|genesis-codebase-map|genesis-design-spec|genesis-api-contract|genesis-ui-ux-test|genesis-harness-engineering|genesis-ai-provider|genesis-pipeline-orchestration|genesis-api-sync)
|
|
282
|
+
genesis-architecture|genesis-planning|genesis-codebase-map|genesis-design-spec|genesis-api-contract|genesis-ui-ux-test|genesis-harness-engineering|genesis-ai-provider|genesis-pipeline-orchestration|genesis-api-sync|genesis-executing-plans|genesis-test-driven-development|genesis-verification-before-completion|genesis-using-git-worktrees)
|
|
268
283
|
verify_skill_metadata "$skill_dir" "$dir_name"
|
|
269
284
|
verify_skill_protocol "$skill_dir"
|
|
270
285
|
;;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const assert = require("assert");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const { execFileSync } = require("child_process");
|
|
9
|
+
|
|
10
|
+
const repoRoot = path.resolve(__dirname, "..", "..");
|
|
11
|
+
const cli = path.join(repoRoot, "bin", "genesis-harness.js");
|
|
12
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "genesis-cli-smoke-"));
|
|
13
|
+
|
|
14
|
+
function run(args, cwd = tmp) {
|
|
15
|
+
return execFileSync(process.execPath, [cli, ...args], {
|
|
16
|
+
cwd,
|
|
17
|
+
env: {
|
|
18
|
+
...process.env,
|
|
19
|
+
CODEX_HOME: path.join(tmp, "codex-home"),
|
|
20
|
+
GENESIS_HARNESS_HOME: path.join(tmp, "agents-home"),
|
|
21
|
+
GENESIS_HARNESS_SKIP_POSTINSTALL: "1"
|
|
22
|
+
},
|
|
23
|
+
encoding: "utf8"
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function runPostinstall(initCwd) {
|
|
28
|
+
return execFileSync(process.execPath, [cli, "postinstall"], {
|
|
29
|
+
cwd: repoRoot,
|
|
30
|
+
env: {
|
|
31
|
+
...process.env,
|
|
32
|
+
CODEX_HOME: path.join(initCwd, "codex-postinstall-home"),
|
|
33
|
+
GENESIS_HARNESS_HOME: path.join(initCwd, "agents-postinstall-home"),
|
|
34
|
+
INIT_CWD: initCwd
|
|
35
|
+
},
|
|
36
|
+
encoding: "utf8"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fs.mkdirSync(path.join(tmp, ".codebase"), { recursive: true });
|
|
41
|
+
fs.mkdirSync(path.join(tmp, ".planning"), { recursive: true });
|
|
42
|
+
fs.writeFileSync(path.join(tmp, ".codebase", "CURRENT_STATE.md"), "# Current State: TEST\n");
|
|
43
|
+
fs.writeFileSync(path.join(tmp, ".codebase", "API_CONTRACTS.md"), "# API Contracts\n");
|
|
44
|
+
fs.writeFileSync(path.join(tmp, ".planning", "SPEC_CHANGELOG.md"), "# Spec Changelog\n");
|
|
45
|
+
fs.writeFileSync(path.join(tmp, "package.json"), JSON.stringify({ name: "smoke-fixture" }, null, 2));
|
|
46
|
+
|
|
47
|
+
run(["install", "--target", "agents"]);
|
|
48
|
+
const seededPolicyPath = path.join(tmp, ".codebase", "context-policy.json");
|
|
49
|
+
assert(fs.existsSync(seededPolicyPath), "install should seed LeanCTX policy into project .codebase");
|
|
50
|
+
const seededPolicy = JSON.parse(fs.readFileSync(seededPolicyPath, "utf8"));
|
|
51
|
+
assert.strictEqual(seededPolicy.token_budget, 12000, "seeded LeanCTX policy should use package default");
|
|
52
|
+
|
|
53
|
+
fs.writeFileSync(
|
|
54
|
+
seededPolicyPath,
|
|
55
|
+
JSON.stringify({ token_budget: 8000, compact_at: 0.7, hard_stop_at: 0.9 }, null, 2)
|
|
56
|
+
);
|
|
57
|
+
run(["install", "--target", "agents"]);
|
|
58
|
+
const preservedPolicy = JSON.parse(fs.readFileSync(seededPolicyPath, "utf8"));
|
|
59
|
+
assert.strictEqual(preservedPolicy.token_budget, 8000, "install must not overwrite customized LeanCTX policy");
|
|
60
|
+
|
|
61
|
+
const postinstallTmp = fs.mkdtempSync(path.join(os.tmpdir(), "genesis-postinstall-smoke-"));
|
|
62
|
+
fs.writeFileSync(path.join(postinstallTmp, "package.json"), JSON.stringify({ name: "postinstall-fixture" }, null, 2));
|
|
63
|
+
runPostinstall(postinstallTmp);
|
|
64
|
+
assert(
|
|
65
|
+
fs.existsSync(path.join(postinstallTmp, ".codebase", "context-policy.json")),
|
|
66
|
+
"postinstall should seed LeanCTX policy when npm exposes INIT_CWD"
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const pathOutput = run(["path"]);
|
|
70
|
+
assert(pathOutput.includes("genesis-harness"), "path should include installed skill paths");
|
|
71
|
+
|
|
72
|
+
const statusOutput = run(["status"]);
|
|
73
|
+
assert(statusOutput.includes("GENESIS HARNESS - STATUS REPORT"), "status should render status report");
|
|
74
|
+
|
|
75
|
+
const docsOutput = run(["docs"]);
|
|
76
|
+
assert(docsOutput.includes("GENESIS HARNESS - DOCUMENTATION REPORT"), "docs should render docs report");
|
|
77
|
+
|
|
78
|
+
const leanCtxOutput = run(["leanctx"]);
|
|
79
|
+
assert(leanCtxOutput.includes("LeanCTX Policy"), "leanctx should render policy report");
|
|
80
|
+
assert(leanCtxOutput.includes("Token budget: 8000"), "leanctx should read project policy");
|
|
81
|
+
assert(leanCtxOutput.includes("Command wrapper:"), "leanctx should report command wrapper detection");
|
|
82
|
+
assert(leanCtxOutput.includes("rtk optional"), "leanctx should treat rtk as optional");
|
|
83
|
+
assert(leanCtxOutput.includes("genesis-harness sync"), "leanctx should include portable sync command");
|
|
84
|
+
|
|
85
|
+
const primeOutput = run(["prime"]);
|
|
86
|
+
assert(primeOutput.includes("LeanCTX Policy"), "prime should include LeanCTX policy");
|
|
87
|
+
assert(primeOutput.includes("rtk optional"), "prime should document optional wrapper behavior");
|
|
88
|
+
|
|
89
|
+
const gateOutput = run(["docs-gate"]);
|
|
90
|
+
assert(
|
|
91
|
+
gateOutput.includes("Docs sync check passed") || gateOutput.includes("docs sync check is limited"),
|
|
92
|
+
"docs-gate should pass in fixture"
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
run(["sync"]);
|
|
96
|
+
const visual = fs.readFileSync(path.join(tmp, ".codebase", "VISUAL_GRAPH.md"), "utf8");
|
|
97
|
+
assert(visual.includes("Harness Relationship Map"), "sync should generate harness relationship map");
|
|
98
|
+
assert(visual.includes("genesis-harness docs-gate"), "sync graph should include docs-gate");
|
|
99
|
+
assert(!visual.includes("Đăng nhập"), "sync graph must not emit stale sample roadmap");
|
|
100
|
+
assert(!visual.includes("src/auth.js"), "sync graph must not emit stale sample source path");
|
|
101
|
+
assert(visual.includes("```mermaid"), "sync graph should contain mermaid fences");
|
|
102
|
+
|
|
103
|
+
console.log("cli smoke passed");
|