@evomap/evolver 1.92.0 → 1.94.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/CONTRIBUTING.md +12 -0
- package/README.ja-JP.md +1 -1
- package/README.ko-KR.md +1 -1
- package/README.md +17 -9
- package/README.zh-CN.md +1 -1
- package/SKILL.md +8 -8
- package/assets/gep/genes.seed.json +312 -0
- package/assets/logo.png +0 -0
- package/cli-options.js +73 -0
- package/index.js +30 -0
- package/package.json +2 -1
- package/scripts/harness-governance-check.js +147 -0
- package/src/adapters/scripts/_runtimePaths.js +10 -1
- package/src/adapters/scripts/evolver-session-end.js +10 -1
- package/src/evolve/guards.js +1 -1
- package/src/evolve/pipeline/collect.js +1 -1
- package/src/evolve/pipeline/dispatch.js +1 -1
- package/src/evolve/pipeline/enrich.js +1 -1
- package/src/evolve/pipeline/hub.js +1 -1
- package/src/evolve/pipeline/select.js +1 -1
- package/src/evolve/pipeline/signals.js +1 -1
- package/src/evolve/utils.js +1 -1
- package/src/evolve.js +1 -1
- package/src/experiment/triggerShift.js +132 -0
- package/src/gep/a2aProtocol.js +1 -1
- package/src/gep/antiAbuseTelemetry.js +1 -1
- package/src/gep/assetStore.js +67 -9
- package/src/gep/autoDistillConv.js +1 -1
- package/src/gep/autoDistillLlm.js +1 -1
- package/src/gep/candidateEval.js +1 -1
- package/src/gep/candidates.js +1 -1
- package/src/gep/contentHash.js +1 -1
- package/src/gep/contextRoutingGene.js +1 -0
- package/src/gep/conversationDistiller.js +1 -1
- package/src/gep/conversationSniffer.js +1 -1
- package/src/gep/crypto.js +1 -1
- package/src/gep/curriculum.js +1 -1
- package/src/gep/deviceId.js +1 -1
- package/src/gep/envFingerprint.js +1 -1
- package/src/gep/epigenetics.js +1 -1
- package/src/gep/execBridge.js +1 -1
- package/src/gep/explore.js +1 -1
- package/src/gep/feedbackEnvelope.js +1 -0
- package/src/gep/hash.js +1 -1
- package/src/gep/hubFetch.js +1 -1
- package/src/gep/hubReview.js +1 -1
- package/src/gep/hubSearch.js +1 -1
- package/src/gep/hubVerify.js +1 -1
- package/src/gep/learningSignals.js +1 -1
- package/src/gep/memoryGraph.js +1 -1
- package/src/gep/memoryGraphAdapter.js +1 -1
- package/src/gep/mutation.js +1 -1
- package/src/gep/narrativeMemory.js +1 -1
- package/src/gep/openPRRegistry.js +1 -1
- package/src/gep/personality.js +1 -1
- package/src/gep/policyCheck.js +1 -1
- package/src/gep/prompt.js +1 -1
- package/src/gep/recallInject.js +1 -1
- package/src/gep/recallVerifier.js +1 -1
- package/src/gep/reflection.js +1 -1
- package/src/gep/savingsCore.js +1 -1
- package/src/gep/selector.js +1 -1
- package/src/gep/signals.js +35 -0
- package/src/gep/skillDistiller.js +1 -1
- package/src/gep/solidify.js +1 -1
- package/src/gep/strategy.js +1 -1
- package/src/gep/syncAsset.js +1 -1
- package/src/gep/tokenSavings.js +1 -1
- package/src/gep/trajectoryExport.js +1 -1
- package/src/gep/validator/sandboxExecutor.js +28 -1
- package/src/gep/workspaceKeychain.js +1 -1
- package/src/proxy/extensions/traceControl.js +1 -1
- package/src/proxy/index.js +66 -6
- package/src/proxy/inject.js +1 -1
- package/src/proxy/server/settings.js +6 -0
- package/src/proxy/trace/extractor.js +1 -1
- package/src/proxy/trace/usage.js +1 -1
- package/assets/cover.png +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
const SENSITIVE_PATH_RE = /^(CONTRIBUTING\.md|\.github\/pull_request_template\.md|\.github\/workflows\/test\.yml|scripts\/harness-governance-check\.js|test\/harnessGovernanceCheck\.test\.js|src\/evolve\.js|src\/evolve\/|src\/adapters\/|src\/experiment\/|src\/gep\/|src\/proxy\/(router|trace)\/|src\/proxy\/inject\.js|assets\/gep\/)/;
|
|
7
|
+
|
|
8
|
+
function parseArgs(argv) {
|
|
9
|
+
const out = {};
|
|
10
|
+
for (let i = 2; i < argv.length; i += 1) {
|
|
11
|
+
const arg = argv[i];
|
|
12
|
+
if (arg === '--body') out.bodyFile = argv[++i];
|
|
13
|
+
else if (arg === '--changed') out.changedFile = argv[++i];
|
|
14
|
+
else if (arg === '--event') out.eventFile = argv[++i];
|
|
15
|
+
else if (arg === '--help' || arg === '-h') out.help = true;
|
|
16
|
+
else throw new Error('unknown argument: ' + arg);
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function stripHtmlComments(text) {
|
|
22
|
+
return String(text || '').replace(/<!--[\s\S]*?-->/g, '');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function readStdin() {
|
|
26
|
+
try {
|
|
27
|
+
return fs.readFileSync(0, 'utf8');
|
|
28
|
+
} catch (_) {
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function readBody(opts) {
|
|
34
|
+
if (opts.bodyFile) return fs.readFileSync(opts.bodyFile, 'utf8');
|
|
35
|
+
if (opts.eventFile) {
|
|
36
|
+
const event = JSON.parse(fs.readFileSync(opts.eventFile, 'utf8'));
|
|
37
|
+
return String(event && event.pull_request && event.pull_request.body || '');
|
|
38
|
+
}
|
|
39
|
+
if (process.env.PR_BODY_FILE) return fs.readFileSync(process.env.PR_BODY_FILE, 'utf8');
|
|
40
|
+
if (process.env.PR_BODY) return String(process.env.PR_BODY);
|
|
41
|
+
return readStdin();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function readChangedFiles(opts) {
|
|
45
|
+
let raw = '';
|
|
46
|
+
if (opts.changedFile) raw = fs.readFileSync(opts.changedFile, 'utf8');
|
|
47
|
+
else if (process.env.PR_CHANGED_FILES_FILE) raw = fs.readFileSync(process.env.PR_CHANGED_FILES_FILE, 'utf8');
|
|
48
|
+
else if (process.env.PR_CHANGED_FILES) raw = String(process.env.PR_CHANGED_FILES);
|
|
49
|
+
return raw.split(/\r?\n/).map(s => s.trim()).filter(Boolean).map(s => s.replace(/\\/g, '/'));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function changedFilesTouchGovernanceSurface(files) {
|
|
53
|
+
return files.some(f => SENSITIVE_PATH_RE.test(f));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function lineValue(body, label) {
|
|
57
|
+
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
58
|
+
const match = body.match(new RegExp('^' + escaped + ':\\s*(.*)$', 'im'));
|
|
59
|
+
return match ? match[1].trim() : null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isSubstantiveValue(value) {
|
|
63
|
+
if (!value) return false;
|
|
64
|
+
const normalized = value.trim();
|
|
65
|
+
if (!normalized) return false;
|
|
66
|
+
if (/[<>]/.test(normalized)) return false;
|
|
67
|
+
if (/^n\/?a\.?(?:$|[\s:;,.\-–—])/i.test(normalized)) return false;
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function valueMatches(body, label, valuePattern) {
|
|
72
|
+
const value = lineValue(body, label);
|
|
73
|
+
return isSubstantiveValue(value) && valuePattern.test(value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function validateGovernancePacket(body, changedFiles) {
|
|
77
|
+
const stripped = stripHtmlComments(body);
|
|
78
|
+
const errors = [];
|
|
79
|
+
if (!changedFilesTouchGovernanceSurface(changedFiles)) return errors;
|
|
80
|
+
|
|
81
|
+
if (!/^##+\s+Harness\/evaluator governance/im.test(stripped)) {
|
|
82
|
+
errors.push('missing ## Harness/evaluator governance — add the PR-template section from CONTRIBUTING.md');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const requiredValues = [
|
|
86
|
+
['Upstream governance surface', /\S/, 'name the Evolver harness/evaluator surface; template placeholders and bare N/A are not accepted for sensitive diffs'],
|
|
87
|
+
['Downstream EvoX impact', /\S/, 'state whether EvoX downstream behavior or contracts are affected; template placeholders and bare N/A are not accepted'],
|
|
88
|
+
['Rollout-local scope', /\S/, 'state the proposal/shadow/cohort boundary before promotion'],
|
|
89
|
+
['Promotion boundary', /\S/, 'state how rollout becomes default behavior'],
|
|
90
|
+
['Evaluator mismatch sets', /\S/, 'cover observation/action/repair/verification/evidence/belief deltas or explain why each is not changed'],
|
|
91
|
+
['Non-regression evidence', /\S/, 'link tests, shadow runs, replay, or doc-only rationale'],
|
|
92
|
+
['Fix-severity review', /^(low|medium|high|critical)\b/i, 'classify the strongest fix severity'],
|
|
93
|
+
['Owner approval', /\S/, 'name the owning module/reviewer requirement'],
|
|
94
|
+
['Security boundary', /\S/, 'state data/tool/host/network/secrets impact'],
|
|
95
|
+
['Rollback', /\S/, 'state how to disable/revert/quarantine'],
|
|
96
|
+
['Live promotion', /^no$/i, "state exactly 'Live promotion: no'"],
|
|
97
|
+
['Autonomous evaluator self-editing', /^no$/i, "state exactly 'Autonomous evaluator self-editing: no'"],
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
for (const [label, pattern, hint] of requiredValues) {
|
|
101
|
+
if (!valueMatches(stripped, label, pattern)) {
|
|
102
|
+
errors.push('missing ' + label + ' — ' + hint);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return errors;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function main() {
|
|
109
|
+
const opts = parseArgs(process.argv);
|
|
110
|
+
if (opts.help) {
|
|
111
|
+
console.log('usage: node scripts/harness-governance-check.js [--body file | --event file] --changed file');
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
const body = readBody(opts);
|
|
115
|
+
const changedFiles = readChangedFiles(opts);
|
|
116
|
+
const errors = validateGovernancePacket(body, changedFiles);
|
|
117
|
+
if (errors.length) {
|
|
118
|
+
console.error('Harness/evaluator governance gate FAILED.');
|
|
119
|
+
for (const err of errors) console.error('- ' + err);
|
|
120
|
+
console.error('Changed sensitive files:');
|
|
121
|
+
for (const f of changedFiles.filter(f => SENSITIVE_PATH_RE.test(f))) console.error('- ' + f);
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
if (changedFilesTouchGovernanceSurface(changedFiles)) {
|
|
125
|
+
console.log('Harness/evaluator governance gate: PASSED');
|
|
126
|
+
} else {
|
|
127
|
+
console.log('Harness/evaluator governance gate: not applicable');
|
|
128
|
+
}
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (require.main === module) {
|
|
133
|
+
try {
|
|
134
|
+
process.exitCode = main();
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error('Harness/evaluator governance gate ERROR: ' + (err && err.message || err));
|
|
137
|
+
process.exitCode = 2;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports = {
|
|
142
|
+
changedFilesTouchGovernanceSurface,
|
|
143
|
+
validateGovernancePacket,
|
|
144
|
+
stripHtmlComments,
|
|
145
|
+
isSubstantiveValue,
|
|
146
|
+
SENSITIVE_PATH_RE,
|
|
147
|
+
};
|
|
@@ -402,6 +402,15 @@ function findMemoryGraph(evolverRoot) {
|
|
|
402
402
|
return path.join(userDir, 'memory_graph.jsonl');
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
+
function gitExecutable() {
|
|
406
|
+
if (process.platform !== 'win32') {
|
|
407
|
+
const xcodeGit = '/Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git';
|
|
408
|
+
if (fs.existsSync(xcodeGit)) return xcodeGit;
|
|
409
|
+
if (fs.existsSync('/usr/bin/git')) return '/usr/bin/git';
|
|
410
|
+
}
|
|
411
|
+
return 'git';
|
|
412
|
+
}
|
|
413
|
+
|
|
405
414
|
// Is `dir` inside a git work tree? Cheap, no-shell `git rev-parse`. Returns
|
|
406
415
|
// false on any error (git missing, not a repo, timeout) and never throws.
|
|
407
416
|
// The session-start hook uses this only to decide whether to surface a
|
|
@@ -409,7 +418,7 @@ function findMemoryGraph(evolverRoot) {
|
|
|
409
418
|
// suppresses the notice rather than breaking anything.
|
|
410
419
|
function isGitWorkspace(dir) {
|
|
411
420
|
try {
|
|
412
|
-
const res = spawnSync(
|
|
421
|
+
const res = spawnSync(gitExecutable(), ['rev-parse', '--is-inside-work-tree'], {
|
|
413
422
|
cwd: dir,
|
|
414
423
|
encoding: 'utf8',
|
|
415
424
|
timeout: 5000,
|
|
@@ -24,12 +24,21 @@ const { findEvolverRoot, findMemoryGraph, resolveProjectDir, resolveWorkspaceId
|
|
|
24
24
|
// consistent with the review-time reader in src/evolve/pipeline/collect.js
|
|
25
25
|
// (Bugbot PR #109 round-1 MEDIUM; reader/writer drift flagged on PR #555).
|
|
26
26
|
|
|
27
|
+
function gitExecutable() {
|
|
28
|
+
if (process.platform !== 'win32') {
|
|
29
|
+
const xcodeGit = '/Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git';
|
|
30
|
+
if (fs.existsSync(xcodeGit)) return xcodeGit;
|
|
31
|
+
if (fs.existsSync('/usr/bin/git')) return '/usr/bin/git';
|
|
32
|
+
}
|
|
33
|
+
return 'git';
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
function runGit(args, cwd) {
|
|
28
37
|
// Argv-array form, no shell. Avoids POSIX `2>/dev/null` redirects that
|
|
29
38
|
// break on Windows cmd.exe (#537). Failures (e.g. no HEAD~1 in a fresh
|
|
30
39
|
// repo) are surfaced as a non-zero status; callers distinguish them
|
|
31
40
|
// from successful empty output via the `ok` flag (PR #94 round-6 LOW).
|
|
32
|
-
const res = spawnSync(
|
|
41
|
+
const res = spawnSync(gitExecutable(), args, {
|
|
33
42
|
cwd,
|
|
34
43
|
encoding: 'utf8',
|
|
35
44
|
timeout: 5000,
|