pgserve 2.1.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -0
- package/README.md +105 -1
- package/bin/autopg-wrapper.cjs +16 -0
- package/bin/pgserve-wrapper.cjs +31 -6
- package/bin/postgres-server.js +80 -7
- package/console/README.md +131 -0
- package/console/api.js +173 -0
- package/console/app.jsx +483 -0
- package/console/colors_and_type.css +227 -0
- package/console/components.jsx +167 -0
- package/console/console.css +1666 -0
- package/console/data.jsx +350 -0
- package/console/index.html +31 -0
- package/console/screens/databases.jsx +5 -0
- package/console/screens/health.jsx +5 -0
- package/console/screens/ingress.jsx +5 -0
- package/console/screens/optimizer.jsx +5 -0
- package/console/screens/rlm-sim.jsx +5 -0
- package/console/screens/rlm-trace.jsx +5 -0
- package/console/screens/security.jsx +5 -0
- package/console/screens/settings.jsx +611 -0
- package/console/screens/sql.jsx +5 -0
- package/console/screens/sync.jsx +5 -0
- package/console/screens/tables.jsx +5 -0
- package/console/tweaks-panel.jsx +425 -0
- package/package.json +11 -1
- package/src/cli-config.cjs +310 -0
- package/src/cli-install.cjs +98 -11
- package/src/cli-restart.cjs +228 -0
- package/src/cli-ui.cjs +580 -0
- package/src/cluster.js +43 -38
- package/src/postgres.js +141 -19
- package/src/settings-loader.cjs +235 -0
- package/src/settings-migrate.cjs +212 -0
- package/src/settings-pg-args.cjs +146 -0
- package/src/settings-schema.cjs +422 -0
- package/src/settings-validator.cjs +416 -0
- package/src/settings-writer.cjs +288 -0
- package/.claude/context/windows-debug.md +0 -119
- package/.genie/AGENTS.md +0 -15
- package/.genie/agents/README.md +0 -110
- package/.genie/agents/analyze.md +0 -176
- package/.genie/agents/forge.md +0 -290
- package/.genie/agents/garbage-cleaner.md +0 -324
- package/.genie/agents/garbage-collector.md +0 -596
- package/.genie/agents/github-issue-gc.md +0 -618
- package/.genie/agents/review.md +0 -380
- package/.genie/agents/semantic-analyzer/find-duplicates.md +0 -90
- package/.genie/agents/semantic-analyzer/find-orphans.md +0 -99
- package/.genie/agents/semantic-analyzer.md +0 -101
- package/.genie/agents/update.md +0 -182
- package/.genie/agents/wish.md +0 -357
- package/.genie/brainstorms/pgserve-v2/DESIGN.md +0 -174
- package/.genie/code/AGENTS.md +0 -694
- package/.genie/code/agents/audit/risk.md +0 -173
- package/.genie/code/agents/audit/security.md +0 -189
- package/.genie/code/agents/audit.md +0 -145
- package/.genie/code/agents/challenge.md +0 -230
- package/.genie/code/agents/change-reviewer.md +0 -295
- package/.genie/code/agents/code-garbage-collector.md +0 -425
- package/.genie/code/agents/code-quality.md +0 -410
- package/.genie/code/agents/commit-suggester.md +0 -255
- package/.genie/code/agents/commit.md +0 -124
- package/.genie/code/agents/consensus.md +0 -204
- package/.genie/code/agents/daily-standup.md +0 -722
- package/.genie/code/agents/docgen.md +0 -48
- package/.genie/code/agents/explore.md +0 -79
- package/.genie/code/agents/fix.md +0 -100
- package/.genie/code/agents/git/commit-advisory.md +0 -219
- package/.genie/code/agents/git/workflows/issue.md +0 -244
- package/.genie/code/agents/git/workflows/pr.md +0 -179
- package/.genie/code/agents/git/workflows/release.md +0 -460
- package/.genie/code/agents/git/workflows/report.md +0 -342
- package/.genie/code/agents/git.md +0 -432
- package/.genie/code/agents/implementor.md +0 -161
- package/.genie/code/agents/install.md +0 -515
- package/.genie/code/agents/issue-creator.md +0 -344
- package/.genie/code/agents/polish.md +0 -116
- package/.genie/code/agents/qa.md +0 -653
- package/.genie/code/agents/refactor.md +0 -294
- package/.genie/code/agents/release.md +0 -1129
- package/.genie/code/agents/roadmap.md +0 -885
- package/.genie/code/agents/tests.md +0 -557
- package/.genie/code/agents/tracer.md +0 -50
- package/.genie/code/agents/update/upstream-update.md +0 -85
- package/.genie/code/agents/update/versions/generic-update.md +0 -305
- package/.genie/code/agents/vibe.md +0 -1317
- package/.genie/code/spells/agent-configuration.md +0 -58
- package/.genie/code/spells/automated-rc-publishing.md +0 -106
- package/.genie/code/spells/branch-tracker-guidance.md +0 -28
- package/.genie/code/spells/debug.md +0 -320
- package/.genie/code/spells/emoji-naming-convention.md +0 -303
- package/.genie/code/spells/evidence-storage.md +0 -26
- package/.genie/code/spells/file-naming-rules.md +0 -35
- package/.genie/code/spells/forge-code-blueprints.md +0 -195
- package/.genie/code/spells/genie-integration.md +0 -153
- package/.genie/code/spells/publishing-protocol.md +0 -61
- package/.genie/code/spells/team-consultation-protocol.md +0 -284
- package/.genie/code/spells/tool-requirements.md +0 -20
- package/.genie/code/spells/triad-maintenance-protocol.md +0 -154
- package/.genie/code/teams/tech-council/council.md +0 -328
- package/.genie/code/teams/tech-council/jt.md +0 -352
- package/.genie/code/teams/tech-council/nayr.md +0 -305
- package/.genie/code/teams/tech-council/oettam.md +0 -375
- package/.genie/neurons/README.md +0 -193
- package/.genie/neurons/forge.md +0 -106
- package/.genie/neurons/genie.md +0 -63
- package/.genie/neurons/review.md +0 -106
- package/.genie/neurons/wish.md +0 -104
- package/.genie/product/README.md +0 -20
- package/.genie/product/cli-automation.md +0 -359
- package/.genie/product/environment.md +0 -60
- package/.genie/product/mission.md +0 -60
- package/.genie/product/roadmap.md +0 -44
- package/.genie/product/tech-stack.md +0 -34
- package/.genie/product/templates/context-template.md +0 -218
- package/.genie/product/templates/qa-done-report-template.md +0 -68
- package/.genie/product/templates/review-report-template.md +0 -89
- package/.genie/product/templates/wish-template.md +0 -120
- package/.genie/scripts/helpers/analyze-commit.js +0 -195
- package/.genie/scripts/helpers/bullet-counter.js +0 -194
- package/.genie/scripts/helpers/bullet-find.js +0 -289
- package/.genie/scripts/helpers/bullet-id.js +0 -244
- package/.genie/scripts/helpers/check-secrets.js +0 -237
- package/.genie/scripts/helpers/count-tokens.js +0 -200
- package/.genie/scripts/helpers/create-frontmatter.js +0 -456
- package/.genie/scripts/helpers/detect-markers.js +0 -293
- package/.genie/scripts/helpers/detect-todos.js +0 -267
- package/.genie/scripts/helpers/detect-unlabeled-blocks.js +0 -135
- package/.genie/scripts/helpers/embeddings.js +0 -344
- package/.genie/scripts/helpers/find-empty-sections.js +0 -158
- package/.genie/scripts/helpers/index.js +0 -319
- package/.genie/scripts/helpers/validate-frontmatter.js +0 -578
- package/.genie/scripts/helpers/validate-links.js +0 -207
- package/.genie/scripts/helpers/validate-paths.js +0 -373
- package/.genie/spells/README.md +0 -9
- package/.genie/spells/ace-protocol.md +0 -118
- package/.genie/spells/ask-one-at-a-time.md +0 -175
- package/.genie/spells/backup-analyzer.md +0 -542
- package/.genie/spells/blocker.md +0 -12
- package/.genie/spells/break-things-move-fast.md +0 -56
- package/.genie/spells/context-candidates.md +0 -72
- package/.genie/spells/context-critic.md +0 -51
- package/.genie/spells/defer-to-expertise.md +0 -278
- package/.genie/spells/delegate-dont-do.md +0 -292
- package/.genie/spells/error-investigation-protocol.md +0 -328
- package/.genie/spells/evidence-based-completion.md +0 -273
- package/.genie/spells/experiment.md +0 -65
- package/.genie/spells/file-creation-protocol.md +0 -229
- package/.genie/spells/forge-integration.md +0 -281
- package/.genie/spells/forge-orchestration.md +0 -514
- package/.genie/spells/gather-context.md +0 -18
- package/.genie/spells/global-health-check.md +0 -34
- package/.genie/spells/global-noop-roundtrip.md +0 -25
- package/.genie/spells/install-genie.md +0 -1232
- package/.genie/spells/install.md +0 -82
- package/.genie/spells/investigate-before-commit.md +0 -112
- package/.genie/spells/know-yourself.md +0 -288
- package/.genie/spells/learn.md +0 -828
- package/.genie/spells/mcp-diagnostic-protocol.md +0 -246
- package/.genie/spells/mcp-first.md +0 -124
- package/.genie/spells/multi-step-execution.md +0 -67
- package/.genie/spells/orchestration-boundary-protocol.md +0 -256
- package/.genie/spells/orchestrator-not-implementor.md +0 -189
- package/.genie/spells/prompt.md +0 -746
- package/.genie/spells/reflect.md +0 -404
- package/.genie/spells/routing-decision-matrix.md +0 -368
- package/.genie/spells/run-in-parallel.md +0 -12
- package/.genie/spells/session-state-updater-example.md +0 -196
- package/.genie/spells/session-state-updater.md +0 -220
- package/.genie/spells/track-long-running-tasks.md +0 -133
- package/.genie/spells/troubleshoot-infrastructure.md +0 -176
- package/.genie/spells/upgrade-genie.md +0 -415
- package/.genie/spells/url-presentation-protocol.md +0 -301
- package/.genie/spells/wish-initiation.md +0 -158
- package/.genie/spells/wish-issue-linkage.md +0 -410
- package/.genie/spells/wish-lifecycle.md +0 -100
- package/.genie/state/provider-status.json +0 -3
- package/.genie/state/version.json +0 -16
- package/.genie/wishes/canonical-pgserve-pm2-supervision/WISH.md +0 -290
- package/.genie/wishes/pgserve-v2/BRIEF-from-genie-pgserve.md +0 -99
- package/.genie/wishes/pgserve-v2/WISH.md +0 -442
- package/.genie/wishes/release-system-genie-pattern/WISH.md +0 -268
- package/.genie/wishes/release-system-genie-pattern/validation.md +0 -205
- package/.gitguardian.yaml +0 -29
- package/.gitguardianignore +0 -16
- package/.github/workflows/ci.yml +0 -122
- package/.github/workflows/release.yml +0 -289
- package/.github/workflows/version.yml +0 -228
- package/.husky/pre-commit +0 -2
- package/AGENTS.md +0 -433
- package/CLAUDE.md +0 -1
- package/Makefile +0 -285
- package/assets/icon.ico +0 -0
- package/bun.lock +0 -435
- package/bunfig.toml +0 -28
- package/ecosystem.config.cjs +0 -23
- package/eslint.config.js +0 -63
- package/examples/multi-tenant-demo.js +0 -104
- package/install.sh +0 -123
- package/knip.json +0 -9
- package/scripts/test-bun-self-heal.sh +0 -163
- package/scripts/test-npx.sh +0 -60
- package/tests/audit.test.js +0 -189
- package/tests/backpressure.test.js +0 -167
- package/tests/benchmarks/runner.js +0 -1197
- package/tests/benchmarks/vector-generator.js +0 -368
- package/tests/cli-install.test.js +0 -322
- package/tests/control-db.test.js +0 -285
- package/tests/daemon-control.test.js +0 -171
- package/tests/daemon-fingerprint-integration.test.js +0 -111
- package/tests/daemon-pr24-regression.test.js +0 -198
- package/tests/fingerprint.test.js +0 -263
- package/tests/fixtures/240-orphan-seed.sql +0 -30
- package/tests/multi-tenant.test.js +0 -374
- package/tests/orphan-cleanup.test.js +0 -390
- package/tests/pg-version-regex.test.js +0 -129
- package/tests/quick-bench.js +0 -135
- package/tests/router-handshake-retry.test.js +0 -119
- package/tests/router-handshake-watchdog.test.js +0 -110
- package/tests/sdk.test.js +0 -71
- package/tests/stale-postmaster-pid.test.js +0 -85
- package/tests/stress-test.js +0 -439
- package/tests/sync-perf-test.js +0 -150
- package/tests/tcp-listen.test.js +0 -368
- package/tests/tenancy.test.js +0 -403
- package/tests/wrapper-supervision.test.js +0 -107
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Validate Markdown Links Helper
|
|
5
|
-
*
|
|
6
|
-
* Check markdown links for broken references (files and anchors).
|
|
7
|
-
* Detects [text](path) links pointing to non-existent files or anchors.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* node validate-links.js <file-path> # Check links in file
|
|
11
|
-
* node validate-links.js <directory> # Check all .md files in directory
|
|
12
|
-
*
|
|
13
|
-
* Output:
|
|
14
|
-
* <file>:<line>: Broken link [text](path) - File not found
|
|
15
|
-
* <file>:<line>: Broken link [text](path#anchor) - Anchor not found
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const fs = require('fs');
|
|
19
|
-
const path = require('path');
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Extract markdown links from text
|
|
23
|
-
* Returns: [{ text, href, line }]
|
|
24
|
-
*/
|
|
25
|
-
function extractLinks(content) {
|
|
26
|
-
const lines = content.split('\n');
|
|
27
|
-
const links = [];
|
|
28
|
-
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
29
|
-
|
|
30
|
-
lines.forEach((line, idx) => {
|
|
31
|
-
let match;
|
|
32
|
-
while ((match = linkRegex.exec(line)) !== null) {
|
|
33
|
-
const text = match[1];
|
|
34
|
-
const href = match[2];
|
|
35
|
-
|
|
36
|
-
// Skip external URLs
|
|
37
|
-
if (href.startsWith('http://') || href.startsWith('https://')) {
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
links.push({ text, href, line: idx + 1 });
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return links;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Check if file exists
|
|
50
|
-
*/
|
|
51
|
-
function fileExists(filePath, basePath) {
|
|
52
|
-
const fullPath = path.resolve(path.dirname(basePath), filePath);
|
|
53
|
-
return fs.existsSync(fullPath);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Check if anchor exists in file
|
|
58
|
-
*/
|
|
59
|
-
function anchorExists(filePath, anchor, basePath) {
|
|
60
|
-
try {
|
|
61
|
-
const fullPath = path.resolve(path.dirname(basePath), filePath);
|
|
62
|
-
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
63
|
-
|
|
64
|
-
// Convert anchor to heading format
|
|
65
|
-
// #my-heading → ## My Heading or ### My Heading, etc.
|
|
66
|
-
const headingText = anchor.toLowerCase().replace(/-/g, ' ');
|
|
67
|
-
const headingRegex = new RegExp(`^#+\\s+${headingText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`, 'im');
|
|
68
|
-
|
|
69
|
-
return headingRegex.test(content);
|
|
70
|
-
} catch (err) {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Validate links in file
|
|
77
|
-
*/
|
|
78
|
-
function validateFile(filePath) {
|
|
79
|
-
try {
|
|
80
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
81
|
-
const links = extractLinks(content);
|
|
82
|
-
const issues = [];
|
|
83
|
-
|
|
84
|
-
links.forEach(({ text, href, line }) => {
|
|
85
|
-
// Split href into path and anchor
|
|
86
|
-
const [linkPath, anchor] = href.split('#');
|
|
87
|
-
|
|
88
|
-
// Check if it's just an anchor (same file)
|
|
89
|
-
if (!linkPath && anchor) {
|
|
90
|
-
if (!anchorExists(filePath, anchor, filePath)) {
|
|
91
|
-
issues.push({
|
|
92
|
-
file: filePath,
|
|
93
|
-
line,
|
|
94
|
-
text,
|
|
95
|
-
href,
|
|
96
|
-
error: `Anchor not found: #${anchor}`,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Check if file exists
|
|
103
|
-
if (!fileExists(linkPath, filePath)) {
|
|
104
|
-
issues.push({
|
|
105
|
-
file: filePath,
|
|
106
|
-
line,
|
|
107
|
-
text,
|
|
108
|
-
href,
|
|
109
|
-
error: 'File not found',
|
|
110
|
-
});
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// If anchor specified, check if it exists in target file
|
|
115
|
-
if (anchor && !anchorExists(linkPath, anchor, filePath)) {
|
|
116
|
-
issues.push({
|
|
117
|
-
file: filePath,
|
|
118
|
-
line,
|
|
119
|
-
text,
|
|
120
|
-
href,
|
|
121
|
-
error: `Anchor not found: #${anchor}`,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return issues;
|
|
127
|
-
} catch (err) {
|
|
128
|
-
return [{ file: filePath, error: `Failed to read file: ${err.message}` }];
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Validate all .md files in directory
|
|
134
|
-
*/
|
|
135
|
-
function validateDirectory(dirPath) {
|
|
136
|
-
const allIssues = [];
|
|
137
|
-
|
|
138
|
-
function scanDir(dir) {
|
|
139
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
140
|
-
|
|
141
|
-
entries.forEach(entry => {
|
|
142
|
-
const fullPath = path.join(dir, entry.name);
|
|
143
|
-
|
|
144
|
-
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
145
|
-
scanDir(fullPath);
|
|
146
|
-
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
147
|
-
const issues = validateFile(fullPath);
|
|
148
|
-
allIssues.push(...issues);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
scanDir(dirPath);
|
|
154
|
-
return allIssues;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Main
|
|
159
|
-
*/
|
|
160
|
-
function main() {
|
|
161
|
-
const args = process.argv.slice(2);
|
|
162
|
-
|
|
163
|
-
if (args.length === 0) {
|
|
164
|
-
console.error(`
|
|
165
|
-
Usage:
|
|
166
|
-
node validate-links.js <file-path> # Check links in single file
|
|
167
|
-
node validate-links.js <directory> # Check all .md files recursively
|
|
168
|
-
|
|
169
|
-
Output:
|
|
170
|
-
<file>:<line>: Broken link [text](path) - error description
|
|
171
|
-
|
|
172
|
-
Exit code:
|
|
173
|
-
0 = All links valid
|
|
174
|
-
1 = Broken links found
|
|
175
|
-
`);
|
|
176
|
-
process.exit(1);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const target = args[0];
|
|
180
|
-
|
|
181
|
-
if (!fs.existsSync(target)) {
|
|
182
|
-
console.error(`Error: Path not found: ${target}`);
|
|
183
|
-
process.exit(1);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const stat = fs.statSync(target);
|
|
187
|
-
const issues = stat.isDirectory()
|
|
188
|
-
? validateDirectory(target)
|
|
189
|
-
: validateFile(target);
|
|
190
|
-
|
|
191
|
-
if (issues.length === 0) {
|
|
192
|
-
console.log('All links valid');
|
|
193
|
-
process.exit(0);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
issues.forEach(issue => {
|
|
197
|
-
if (issue.line) {
|
|
198
|
-
console.log(`${issue.file}:${issue.line}: Broken link [${issue.text}](${issue.href}) - ${issue.error}`);
|
|
199
|
-
} else {
|
|
200
|
-
console.log(`${issue.file}: ${issue.error}`);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
process.exit(1);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
main();
|
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Path Validator - Scans codebase for broken LITERAL file path references
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* genie helper validate-paths [--verbose]
|
|
7
|
-
* genie helper validate-paths --staged (only scan staged files)
|
|
8
|
-
*
|
|
9
|
-
* Focuses on:
|
|
10
|
-
* - Literal file paths in strings (not imports)
|
|
11
|
-
* - File system operations (readFileSync, existsSync, etc.)
|
|
12
|
-
* - Configuration file paths
|
|
13
|
-
* - Documentation references
|
|
14
|
-
*
|
|
15
|
-
* Ignores:
|
|
16
|
-
* - import/require statements (handled by TypeScript)
|
|
17
|
-
* - Node.js built-in modules
|
|
18
|
-
* - npm packages
|
|
19
|
-
*
|
|
20
|
-
* Exit codes:
|
|
21
|
-
* 0 - All paths valid
|
|
22
|
-
* 1 - Broken paths found
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
const fs = require('fs');
|
|
26
|
-
const path = require('path');
|
|
27
|
-
const { execSync } = require('child_process');
|
|
28
|
-
|
|
29
|
-
const WORKSPACE_ROOT = process.cwd();
|
|
30
|
-
const VERBOSE = process.argv.includes('--verbose');
|
|
31
|
-
const STAGED_ONLY = process.argv.includes('--staged');
|
|
32
|
-
|
|
33
|
-
// Node.js built-in modules (to ignore)
|
|
34
|
-
const BUILTIN_MODULES = new Set([
|
|
35
|
-
'fs', 'path', 'os', 'util', 'events', 'stream', 'crypto', 'http', 'https',
|
|
36
|
-
'net', 'url', 'querystring', 'zlib', 'child_process', 'cluster', 'readline',
|
|
37
|
-
'assert', 'buffer', 'string_decoder', 'tty', 'vm', 'dns', 'dgram', 'timers',
|
|
38
|
-
'punycode', 'process', 'console', 'module', 'perf_hooks', 'worker_threads',
|
|
39
|
-
'v8', 'trace_events', 'async_hooks', 'inspector'
|
|
40
|
-
]);
|
|
41
|
-
|
|
42
|
-
// Results
|
|
43
|
-
const results = {
|
|
44
|
-
scanned: 0,
|
|
45
|
-
broken: [],
|
|
46
|
-
valid: [],
|
|
47
|
-
exceptions: [],
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Security: Validate resolved path is within workspace
|
|
52
|
-
* Allows relative paths that resolve inside workspace
|
|
53
|
-
*/
|
|
54
|
-
function isPathSafe(resolvedPath) {
|
|
55
|
-
try {
|
|
56
|
-
const relative = path.relative(WORKSPACE_ROOT, resolvedPath);
|
|
57
|
-
// Path is safe if it doesn't escape workspace
|
|
58
|
-
return !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
59
|
-
} catch {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Check if it's a module import (not a file path)
|
|
66
|
-
*/
|
|
67
|
-
function isModuleImport(pathStr) {
|
|
68
|
-
// Built-in module
|
|
69
|
-
if (BUILTIN_MODULES.has(pathStr)) return true;
|
|
70
|
-
|
|
71
|
-
// npm package (doesn't start with . or /)
|
|
72
|
-
if (!/^[./]/.test(pathStr)) return true;
|
|
73
|
-
|
|
74
|
-
// Relative import without extension (TypeScript module)
|
|
75
|
-
if (/^\.\.?\//.test(pathStr) && !/\.(js|ts|json|md|yaml|yml|html|css)$/.test(pathStr)) {
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Check if path is expected to not exist
|
|
84
|
-
*/
|
|
85
|
-
function isException(pathStr) {
|
|
86
|
-
const exceptions = {
|
|
87
|
-
runtime: [
|
|
88
|
-
'.genie/state/current-session.json',
|
|
89
|
-
'.genie/state/stats-history.json',
|
|
90
|
-
'.genie/state/forge.log',
|
|
91
|
-
'dist/cli/genie.js', // Built at compile time
|
|
92
|
-
'dist/mcp/server.js', // Built at compile time
|
|
93
|
-
],
|
|
94
|
-
userWorkspace: [
|
|
95
|
-
'.genie/cli/config.yaml',
|
|
96
|
-
'.genie/config.yaml',
|
|
97
|
-
'.mcp.json',
|
|
98
|
-
'.genie/CONTEXT.md',
|
|
99
|
-
'.genie/MASTER-PLAN.md',
|
|
100
|
-
'.genie/SESSION-STATE.md',
|
|
101
|
-
'.genie/TODO.md',
|
|
102
|
-
'.genie/sleepy-state.json',
|
|
103
|
-
],
|
|
104
|
-
examples: [
|
|
105
|
-
// Example paths in documentation
|
|
106
|
-
/^\/path\/to\//,
|
|
107
|
-
/^\.\/file\./,
|
|
108
|
-
/\bexample\b/i,
|
|
109
|
-
/\bmy-custom-/,
|
|
110
|
-
/\bcustom-deployment/,
|
|
111
|
-
/\bold-workflow/,
|
|
112
|
-
/\bdeprecated-spell/,
|
|
113
|
-
/\bprototype\./,
|
|
114
|
-
/\/wish\.md$/,
|
|
115
|
-
/\/identity\.md$/,
|
|
116
|
-
],
|
|
117
|
-
templates: [
|
|
118
|
-
/\$\{/, /<[^>]+>/, /\[.*?\]/,
|
|
119
|
-
],
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
if (exceptions.runtime.includes(pathStr)) return 'runtime';
|
|
123
|
-
if (exceptions.userWorkspace.includes(pathStr)) return 'user-workspace';
|
|
124
|
-
if (exceptions.examples.some(regex => regex.test(pathStr))) return 'example';
|
|
125
|
-
if (exceptions.templates.some(regex => regex.test(pathStr))) return 'template';
|
|
126
|
-
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Extract literal file paths from content
|
|
132
|
-
* Only paths that look like actual files (with extensions)
|
|
133
|
-
*/
|
|
134
|
-
function extractFilePaths(content, filePath) {
|
|
135
|
-
const paths = new Set();
|
|
136
|
-
|
|
137
|
-
// Skip import/require statements (they're handled by TypeScript/Node.js)
|
|
138
|
-
const contentWithoutImports = content
|
|
139
|
-
.replace(/^import\s+.*?from\s+['\"][^'\"]+['\"]/gm, '')
|
|
140
|
-
.replace(/^export\s+.*?from\s+['\"][^'\"]+['\"]/gm, '')
|
|
141
|
-
.replace(/require\(['\"][^'\"]+['\"][\),]/g, '');
|
|
142
|
-
|
|
143
|
-
// Pattern: file paths with extensions in strings
|
|
144
|
-
const filePathPattern = /['\"`]([^'\"`]*\.(?:md|json|yaml|yml|sh|html|css|txt|log|cjs))['\"]/g;
|
|
145
|
-
|
|
146
|
-
let match;
|
|
147
|
-
while ((match = filePathPattern.exec(contentWithoutImports)) !== null) {
|
|
148
|
-
const pathStr = match[1];
|
|
149
|
-
|
|
150
|
-
// Skip if it's clearly a module import (TypeScript modules without extension)
|
|
151
|
-
if (isModuleImport(pathStr)) continue;
|
|
152
|
-
|
|
153
|
-
// Skip URLs
|
|
154
|
-
if (/^https?:\/\//.test(pathStr)) continue;
|
|
155
|
-
|
|
156
|
-
// Skip very short paths (likely false positives like ".md" in endsWith('.md'))
|
|
157
|
-
if (pathStr.length < 5) continue;
|
|
158
|
-
|
|
159
|
-
// Skip template variables and patterns
|
|
160
|
-
if (/^\$\{|\}$/.test(pathStr)) continue;
|
|
161
|
-
|
|
162
|
-
// Skip if it's just an extension (e.g., ".md" from .endsWith('.md'))
|
|
163
|
-
if (/^\.[\w]+$/.test(pathStr)) continue;
|
|
164
|
-
|
|
165
|
-
// Skip glob patterns (**, *, ?, {, })
|
|
166
|
-
if (/[\*\?\{\}]/.test(pathStr)) continue;
|
|
167
|
-
|
|
168
|
-
// Skip template filenames (e.g., ".template.md")
|
|
169
|
-
if (/^\.template\./.test(pathStr)) continue;
|
|
170
|
-
|
|
171
|
-
paths.add(pathStr);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return Array.from(paths);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Validate a path
|
|
179
|
-
*/
|
|
180
|
-
function validatePath(pathStr, sourceFile) {
|
|
181
|
-
// Check exceptions first
|
|
182
|
-
const exceptionType = isException(pathStr);
|
|
183
|
-
if (exceptionType) {
|
|
184
|
-
results.exceptions.push({ path: pathStr, source: sourceFile, type: exceptionType });
|
|
185
|
-
return { valid: true, reason: exceptionType };
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Resolve path
|
|
189
|
-
let resolvedPath;
|
|
190
|
-
if (pathStr.startsWith('.genie/') || pathStr.startsWith('src/') || pathStr.startsWith('dist/')) {
|
|
191
|
-
// Workspace-relative paths (always resolve from workspace root)
|
|
192
|
-
resolvedPath = path.resolve(WORKSPACE_ROOT, pathStr);
|
|
193
|
-
} else if (pathStr.startsWith('./') || pathStr.startsWith('../')) {
|
|
194
|
-
// Relative to source file
|
|
195
|
-
resolvedPath = path.resolve(path.dirname(sourceFile), pathStr);
|
|
196
|
-
} else if (pathStr.startsWith('/')) {
|
|
197
|
-
// Absolute
|
|
198
|
-
resolvedPath = pathStr;
|
|
199
|
-
} else {
|
|
200
|
-
// Default: relative to workspace root
|
|
201
|
-
resolvedPath = path.resolve(WORKSPACE_ROOT, pathStr);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Security check (after resolving)
|
|
205
|
-
if (!isPathSafe(resolvedPath)) {
|
|
206
|
-
return { valid: false, reason: 'unsafe-path', resolvedPath };
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Check if exists
|
|
210
|
-
try {
|
|
211
|
-
fs.accessSync(resolvedPath, fs.constants.R_OK);
|
|
212
|
-
results.valid.push({ path: pathStr, source: sourceFile });
|
|
213
|
-
return { valid: true, resolvedPath };
|
|
214
|
-
} catch {
|
|
215
|
-
return { valid: false, reason: 'not-found', resolvedPath };
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Scan a file
|
|
221
|
-
*/
|
|
222
|
-
function scanFile(filePath) {
|
|
223
|
-
results.scanned++;
|
|
224
|
-
|
|
225
|
-
try {
|
|
226
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
227
|
-
const paths = extractFilePaths(content, filePath);
|
|
228
|
-
|
|
229
|
-
for (const pathStr of paths) {
|
|
230
|
-
const result = validatePath(pathStr, filePath);
|
|
231
|
-
|
|
232
|
-
if (!result.valid) {
|
|
233
|
-
results.broken.push({
|
|
234
|
-
path: pathStr,
|
|
235
|
-
source: filePath.replace(WORKSPACE_ROOT + '/', ''),
|
|
236
|
-
reason: result.reason,
|
|
237
|
-
resolved: result.resolvedPath,
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
} catch (err) {
|
|
242
|
-
if (VERBOSE) {
|
|
243
|
-
console.error(`Error scanning ${filePath}: ${err.message}`);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Scan directory recursively
|
|
250
|
-
*/
|
|
251
|
-
function scanDirectory(dir, extensions) {
|
|
252
|
-
try {
|
|
253
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
254
|
-
|
|
255
|
-
for (const entry of entries) {
|
|
256
|
-
const fullPath = path.join(dir, entry.name);
|
|
257
|
-
|
|
258
|
-
if (entry.isDirectory()) {
|
|
259
|
-
// Skip
|
|
260
|
-
if (['node_modules', '.git', 'dist'].includes(entry.name)) continue;
|
|
261
|
-
if (fullPath.includes('.genie/reports')) continue;
|
|
262
|
-
if (fullPath.includes('.genie/wishes')) continue;
|
|
263
|
-
if (fullPath.includes('.genie/qa')) continue;
|
|
264
|
-
|
|
265
|
-
scanDirectory(fullPath, extensions);
|
|
266
|
-
} else if (entry.isFile()) {
|
|
267
|
-
if (extensions.some(ext => entry.name.endsWith(ext))) {
|
|
268
|
-
scanFile(fullPath);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
} catch (err) {
|
|
273
|
-
if (VERBOSE) {
|
|
274
|
-
console.error(`Error scanning ${dir}: ${err.message}`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Get staged files only
|
|
281
|
-
*/
|
|
282
|
-
function getStagedFiles() {
|
|
283
|
-
try {
|
|
284
|
-
const output = execSync('git diff --cached --name-only --diff-filter=ACMR', {
|
|
285
|
-
encoding: 'utf8',
|
|
286
|
-
cwd: WORKSPACE_ROOT
|
|
287
|
-
});
|
|
288
|
-
return output.trim().split('\n').filter(Boolean).map(f => path.join(WORKSPACE_ROOT, f));
|
|
289
|
-
} catch {
|
|
290
|
-
return [];
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Main
|
|
296
|
-
*/
|
|
297
|
-
function main() {
|
|
298
|
-
console.log('🔍 Path Validator - Scanning for broken file references\n');
|
|
299
|
-
|
|
300
|
-
if (STAGED_ONLY) {
|
|
301
|
-
// Only scan staged files
|
|
302
|
-
console.log('📂 Scanning staged files only...');
|
|
303
|
-
const stagedFiles = getStagedFiles();
|
|
304
|
-
|
|
305
|
-
if (stagedFiles.length === 0) {
|
|
306
|
-
console.log('No staged files to scan\n');
|
|
307
|
-
process.exit(0);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
stagedFiles.forEach(file => {
|
|
311
|
-
if (fs.existsSync(file) && (file.endsWith('.ts') || file.endsWith('.js') || file.endsWith('.md'))) {
|
|
312
|
-
scanFile(file);
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
} else {
|
|
316
|
-
// Full codebase scan
|
|
317
|
-
console.log('📂 Scanning source files...');
|
|
318
|
-
scanDirectory(path.join(WORKSPACE_ROOT, 'src'), ['.ts', '.js']);
|
|
319
|
-
|
|
320
|
-
console.log('📂 Scanning documentation...');
|
|
321
|
-
scanDirectory(path.join(WORKSPACE_ROOT, '.genie'), ['.md']);
|
|
322
|
-
if (fs.existsSync(path.join(WORKSPACE_ROOT, 'docs'))) {
|
|
323
|
-
scanDirectory(path.join(WORKSPACE_ROOT, 'docs'), ['.md']);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Scan scripts
|
|
327
|
-
if (fs.existsSync(path.join(WORKSPACE_ROOT, '.genie/scripts'))) {
|
|
328
|
-
console.log('📂 Scanning scripts...');
|
|
329
|
-
scanDirectory(path.join(WORKSPACE_ROOT, '.genie/scripts'), ['.sh', '.js', '.cjs']);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Report
|
|
334
|
-
console.log(`\n✅ Scanned ${results.scanned} files\n`);
|
|
335
|
-
|
|
336
|
-
if (results.broken.length > 0) {
|
|
337
|
-
console.log(`❌ Found ${results.broken.length} broken path reference(s):\n`);
|
|
338
|
-
|
|
339
|
-
results.broken.forEach(({ path, source, reason, resolved }) => {
|
|
340
|
-
console.log(` 📄 ${path}`);
|
|
341
|
-
console.log(` Source: ${source}`);
|
|
342
|
-
console.log(` Reason: ${reason}`);
|
|
343
|
-
if (resolved && reason === 'not-found') {
|
|
344
|
-
console.log(` Expected: ${resolved}`);
|
|
345
|
-
}
|
|
346
|
-
console.log();
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
process.exit(1);
|
|
350
|
-
} else {
|
|
351
|
-
console.log('✅ No broken paths found!');
|
|
352
|
-
console.log(`✅ Validated ${results.valid.length} file path references`);
|
|
353
|
-
|
|
354
|
-
if (VERBOSE) {
|
|
355
|
-
console.log(`\nℹ️ Exceptions: ${results.exceptions.length} (runtime/user-workspace files)`);
|
|
356
|
-
|
|
357
|
-
// Show some examples
|
|
358
|
-
if (results.valid.length > 0) {
|
|
359
|
-
console.log(`\nℹ️ Sample valid paths:`);
|
|
360
|
-
results.valid.slice(0, 5).forEach(({ path }) => {
|
|
361
|
-
console.log(` ✓ ${path}`);
|
|
362
|
-
});
|
|
363
|
-
if (results.valid.length > 5) {
|
|
364
|
-
console.log(` ... and ${results.valid.length - 5} more`);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
process.exit(0);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
main();
|
package/.genie/spells/README.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# Forge Workflows (Global)
|
|
3
|
-
|
|
4
|
-
Global Forge workflows applicable across domains. Core `forge` agent delegates here when a domain-agnostic flow is sufficient. Domain-specific flows live under each collective (e.g., `code/workflows/forge.md`).
|
|
5
|
-
|
|
6
|
-
## Structure
|
|
7
|
-
- One file per workflow under `workflows/forge/`
|
|
8
|
-
- Keep flows atomic, with clear inputs, steps, and evidence
|
|
9
|
-
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# ACE Protocol - Evidence-Based Editing Requirements
|
|
2
|
-
|
|
3
|
-
**Purpose:** Mandatory behavioral triggers for all framework edits. ACE (Agentic Context Engineering) ensures data-driven optimization.
|
|
4
|
-
|
|
5
|
-
**Load Priority:** 2 (immediately after know-yourself.md)
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 🔴 MANDATORY: Before Editing ANY File
|
|
10
|
-
|
|
11
|
-
**Use semantic deduplication to prevent duplicate learnings:**
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
genie helper embeddings "new learning text" file.md "Section Name"
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
**Decision Rules:**
|
|
18
|
-
- `similarity > 0.85` → **DUPLICATE** - Merge with existing or skip
|
|
19
|
-
- `similarity 0.70-0.85` → **RELATED** - Evaluate carefully, usually merge
|
|
20
|
-
- `similarity < 0.70` → **DIFFERENT** - Safe to add new learning
|
|
21
|
-
|
|
22
|
-
**When to use:**
|
|
23
|
-
- Before adding ANY new learning to spells/agents
|
|
24
|
-
- When user teaches new pattern
|
|
25
|
-
- When learn agent is invoked
|
|
26
|
-
- Part of grow-and-refine protocol
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## 🔴 MANDATORY: Before Committing ANY Change
|
|
31
|
-
|
|
32
|
-
**Measure token impact of all framework changes:**
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
genie helper count-tokens file.md
|
|
36
|
-
|
|
37
|
-
# Compare before/after (for savings calculation)
|
|
38
|
-
genie helper count-tokens --before=old.md --after=new.md
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**Record in commit message:**
|
|
42
|
-
- Tokens before/after
|
|
43
|
-
- Net change (+/- tokens)
|
|
44
|
-
- Justify growth if adding content
|
|
45
|
-
|
|
46
|
-
**When to use:**
|
|
47
|
-
- Before every framework commit
|
|
48
|
-
- When validating token efficiency (Amendment #6)
|
|
49
|
-
- Required by Amendment #8
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## 🔴 MANDATORY: After Executing ANY QA Scenario
|
|
54
|
-
|
|
55
|
-
**Track learning effectiveness with counter updates:**
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# Record helpful outcome (scenario passed, learning helped)
|
|
59
|
-
genie helper bullet-counter learn-042 --helpful
|
|
60
|
-
|
|
61
|
-
# Record harmful outcome (scenario failed, learning caused issue)
|
|
62
|
-
genie helper bullet-counter learn-042 --harmful
|
|
63
|
-
|
|
64
|
-
# Query current counters
|
|
65
|
-
genie helper bullet-counter learn-042
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
**Value Ratio Formula:**
|
|
69
|
-
```
|
|
70
|
-
ratio = helpful / max(harmful, 1)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
**Categorization Thresholds:**
|
|
74
|
-
- `ratio ≥ 3.0` → **HIGH_VALUE** - Strengthen with examples, reinforce
|
|
75
|
-
- `ratio 1.0-3.0` → **MEDIUM_VALUE** - Keep as-is, working well
|
|
76
|
-
- `ratio 0.5-1.0` → **LOW_VALUE** - Refine wording or clarify
|
|
77
|
-
- `ratio < 0.5` → **HARMFUL** - Remove or completely rewrite
|
|
78
|
-
|
|
79
|
-
**When to use:**
|
|
80
|
-
- After manual QA scenario execution
|
|
81
|
-
- During multi-epoch testing (future automation)
|
|
82
|
-
- When gathering evidence for optimization decisions
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Why This Matters
|
|
87
|
-
|
|
88
|
-
**Without ACE:**
|
|
89
|
-
- Duplicate learnings accumulate → context bloat
|
|
90
|
-
- Framework grows without measurement → token waste
|
|
91
|
-
- Intuition-based optimization → no evidence
|
|
92
|
-
|
|
93
|
-
**With ACE:**
|
|
94
|
-
- Semantic dedup catches paraphrases → no duplicates
|
|
95
|
-
- Token measurement before commit → controlled growth
|
|
96
|
-
- Evidence-based optimization → data-driven improvements
|
|
97
|
-
|
|
98
|
-
**Current Status:**
|
|
99
|
-
- ✅ All ACE helpers operational (embeddings, bullet-counter, count-tokens)
|
|
100
|
-
- ✅ 912 learnings structured with counters `[id] helpful=N harmful=M: content`
|
|
101
|
-
- ⚠️ Multi-epoch automation pending (Phase 5: Issue #384)
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## Cross-References
|
|
106
|
-
|
|
107
|
-
**Related Amendments:**
|
|
108
|
-
- Amendment #6: Token Efficiency - Fast, Fit, Smart, Sexy
|
|
109
|
-
- Amendment #8: Token Counting Protocol - Official Helper Only
|
|
110
|
-
- Amendment #12: ACE Protocol - Evidence-Based Framework Optimization
|
|
111
|
-
|
|
112
|
-
**Related Spells:**
|
|
113
|
-
- `learn.md` - Detailed ACE workflows and grow-and-refine protocol
|
|
114
|
-
- `know-yourself.md` - Core identity and self-awareness
|
|
115
|
-
|
|
116
|
-
**Documentation:**
|
|
117
|
-
- ACE architecture: `/tmp/genie-ace-architecture-complete.md`
|
|
118
|
-
- Phase 5 automation: GitHub Issue #384
|