@evomap/evolver 1.85.3 → 1.86.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.
Files changed (43) hide show
  1. package/package.json +4 -1
  2. package/scripts/check-changelog.js +166 -0
  3. package/src/evolve/guards.js +1 -1
  4. package/src/evolve/pipeline/collect.js +1 -1
  5. package/src/evolve/pipeline/dispatch.js +1 -1
  6. package/src/evolve/pipeline/enrich.js +1 -1
  7. package/src/evolve/pipeline/hub.js +1 -1
  8. package/src/evolve/pipeline/select.js +1 -1
  9. package/src/evolve/pipeline/signals.js +1 -1
  10. package/src/evolve/utils.js +1 -1
  11. package/src/evolve.js +1 -1
  12. package/src/gep/a2aProtocol.js +1 -1
  13. package/src/gep/candidateEval.js +1 -1
  14. package/src/gep/candidates.js +1 -1
  15. package/src/gep/contentHash.js +1 -1
  16. package/src/gep/crypto.js +1 -1
  17. package/src/gep/curriculum.js +1 -1
  18. package/src/gep/deviceId.js +1 -1
  19. package/src/gep/envFingerprint.js +1 -1
  20. package/src/gep/epigenetics.js +1 -1
  21. package/src/gep/explore.js +1 -1
  22. package/src/gep/hash.js +1 -1
  23. package/src/gep/hubFetch.js +1 -1
  24. package/src/gep/hubReview.js +1 -1
  25. package/src/gep/hubSearch.js +1 -1
  26. package/src/gep/hubVerify.js +1 -1
  27. package/src/gep/learningSignals.js +1 -1
  28. package/src/gep/memoryGraph.js +1 -1
  29. package/src/gep/memoryGraphAdapter.js +1 -1
  30. package/src/gep/mutation.js +1 -1
  31. package/src/gep/narrativeMemory.js +1 -1
  32. package/src/gep/openPRRegistry.js +1 -1
  33. package/src/gep/paths.js +124 -31
  34. package/src/gep/personality.js +1 -1
  35. package/src/gep/policyCheck.js +1 -1
  36. package/src/gep/prompt.js +1 -1
  37. package/src/gep/recallVerifier.js +1 -1
  38. package/src/gep/reflection.js +1 -1
  39. package/src/gep/selector.js +1 -1
  40. package/src/gep/skillDistiller.js +1 -1
  41. package/src/gep/solidify.js +1 -1
  42. package/src/gep/strategy.js +1 -1
  43. package/src/gep/workspaceKeychain.js +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evomap/evolver",
3
- "version": "1.85.3",
3
+ "version": "1.86.0",
4
4
  "description": "A GEP-powered self-evolution engine for AI agents. Features automated log analysis and Genome Evolution Protocol (GEP) for auditable, reusable evolution assets.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -43,6 +43,9 @@
43
43
  "devDependencies": {
44
44
  "javascript-obfuscator": "^5.4.1"
45
45
  },
46
+ "optionalDependencies": {
47
+ "@napi-rs/keyring": "^1.1.6"
48
+ },
46
49
  "files": [
47
50
  "assets/",
48
51
  "index.js",
@@ -0,0 +1,166 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * CHANGELOG release-section integrity guard.
5
+ *
6
+ * Catches the misattribution pattern that bit us with #540 / PR #107:
7
+ * an entry filed under `## [X.Y.Z]` AFTER v1.85.0 was already published
8
+ * to npm, so the changelog claimed a fix the binary didn't contain.
9
+ *
10
+ * Algorithm: for every `## [X.Y.Z]` heading in CHANGELOG.md that has a
11
+ * matching git tag (`vX.Y.Z`), compare the section content at HEAD
12
+ * against the section content at that tag. If they differ, somebody
13
+ * edited a frozen-and-released section — fail loud.
14
+ *
15
+ * Notes:
16
+ * - `## [Unreleased]` is exempt (it's the staging area, no tag).
17
+ * - Version headings without a corresponding tag are exempt — that's
18
+ * usually the "preparing X.Y.Z" state right before the tag exists.
19
+ * - Tag lookup is local-only (`git rev-parse`); CI must `git fetch
20
+ * --tags` first if it runs on a shallow clone.
21
+ * - `repoRoot` is injectable so tests don't need to monkey-patch the
22
+ * module by re-evaluating source (autogame-17 PR #115 review).
23
+ *
24
+ * Usage:
25
+ * node scripts/check-changelog.js # CLI mode, exits 0/1
26
+ * const { checkChangelogIntegrity } = require('./check-changelog');
27
+ * const result = checkChangelogIntegrity({ repoRoot });
28
+ */
29
+
30
+ const { execFileSync } = require('child_process');
31
+ const fs = require('fs');
32
+ const path = require('path');
33
+
34
+ const DEFAULT_REPO_ROOT = path.resolve(__dirname, '..');
35
+
36
+ function readChangelogAtHead(repoRoot) {
37
+ return fs.readFileSync(path.join(repoRoot, 'CHANGELOG.md'), 'utf8');
38
+ }
39
+
40
+ function readChangelogAtRef(repoRoot, ref) {
41
+ try {
42
+ return execFileSync('git', ['show', `${ref}:CHANGELOG.md`], {
43
+ cwd: repoRoot,
44
+ encoding: 'utf8',
45
+ stdio: ['ignore', 'pipe', 'ignore'],
46
+ });
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+
52
+ function tagExists(repoRoot, tag) {
53
+ try {
54
+ execFileSync('git', ['rev-parse', '--verify', `refs/tags/${tag}`], {
55
+ cwd: repoRoot,
56
+ stdio: ['ignore', 'ignore', 'ignore'],
57
+ });
58
+ return true;
59
+ } catch {
60
+ return false;
61
+ }
62
+ }
63
+
64
+ // Pull every `## [X.Y.Z]` heading from the file, skipping `[Unreleased]`.
65
+ function listReleasedVersionHeadings(text) {
66
+ const versions = [];
67
+ const re = /^## \[(\d+\.\d+\.\d+(?:[-+][\w.]+)?)\]/gm;
68
+ let m;
69
+ while ((m = re.exec(text)) !== null) {
70
+ versions.push(m[1]);
71
+ }
72
+ return versions;
73
+ }
74
+
75
+ // Extract the body between `## [X.Y.Z]` and the next `## [` (or EOF).
76
+ // Normalises trailing whitespace and trailing blank lines so a stray
77
+ // newline doesn't fail the equality check.
78
+ //
79
+ // Heading match is line-anchored (`/^## \[X\.Y\.Z\]/m`) so a fenced
80
+ // code block or quoted text containing `## [X.Y.Z]` mid-line cannot be
81
+ // mistaken for the section start (Bugbot PR #115 review).
82
+ function extractSection(text, version) {
83
+ const escaped = version.replace(/[.+]/g, (c) => '\\' + c);
84
+ const re = new RegExp(`^## \\[${escaped}\\]`, 'm');
85
+ const match = re.exec(text);
86
+ if (!match) return null;
87
+ const after = match.index + match[0].length;
88
+ const rest = text.slice(after);
89
+ const nextRel = rest.search(/\n## \[/);
90
+ const raw = nextRel === -1 ? rest : rest.slice(0, nextRel);
91
+ return raw
92
+ .split('\n')
93
+ .map((line) => line.replace(/\s+$/, ''))
94
+ .join('\n')
95
+ .replace(/\n+$/, '');
96
+ }
97
+
98
+ function checkChangelogIntegrity(opts) {
99
+ const repoRoot = (opts && opts.repoRoot) || DEFAULT_REPO_ROOT;
100
+ const head = readChangelogAtHead(repoRoot);
101
+ const versions = listReleasedVersionHeadings(head);
102
+
103
+ const drift = [];
104
+ const skipped = [];
105
+
106
+ for (const version of versions) {
107
+ const tag = `v${version}`;
108
+ if (!tagExists(repoRoot, tag)) {
109
+ skipped.push({ version, reason: 'no matching git tag (probably preparing this release)' });
110
+ continue;
111
+ }
112
+ const tagText = readChangelogAtRef(repoRoot, tag);
113
+ if (tagText == null) {
114
+ skipped.push({ version, reason: `tag ${tag} exists but its CHANGELOG.md is unreadable` });
115
+ continue;
116
+ }
117
+ const headSection = extractSection(head, version);
118
+ const tagSection = extractSection(tagText, version);
119
+ if (headSection == null || tagSection == null) {
120
+ skipped.push({ version, reason: 'section parse failed' });
121
+ continue;
122
+ }
123
+ if (headSection !== tagSection) {
124
+ drift.push({ version, tag });
125
+ }
126
+ }
127
+
128
+ return { drift, skipped, checked: versions.length - skipped.length };
129
+ }
130
+
131
+ function main() {
132
+ const result = checkChangelogIntegrity();
133
+
134
+ process.stdout.write(`\n=== CHANGELOG release-section guard ===\n`);
135
+ process.stdout.write(`Checked ${result.checked} released version section(s); skipped ${result.skipped.length}.\n`);
136
+
137
+ for (const s of result.skipped) {
138
+ process.stdout.write(` [skip] ${s.version}: ${s.reason}\n`);
139
+ }
140
+
141
+ if (result.drift.length === 0) {
142
+ process.stdout.write(`\n[OK] No released CHANGELOG section was edited after its release tag.\n`);
143
+ return 0;
144
+ }
145
+
146
+ process.stderr.write(`\n[FAIL] ${result.drift.length} CHANGELOG section(s) diverged from their release tag:\n`);
147
+ for (const d of result.drift) {
148
+ process.stderr.write(` - ## [${d.version}] differs from ${d.tag}:CHANGELOG.md\n`);
149
+ }
150
+ process.stderr.write(
151
+ `\nReleased sections must stay frozen. Move any new entries under ## [Unreleased],\n` +
152
+ `or, if the entry was genuinely missing from the release, amend it on a hotfix\n` +
153
+ `branch and tag a patch release.\n`
154
+ );
155
+ return 1;
156
+ }
157
+
158
+ if (require.main === module) {
159
+ process.exit(main());
160
+ }
161
+
162
+ module.exports = {
163
+ checkChangelogIntegrity,
164
+ extractSection, // for tests
165
+ listReleasedVersionHeadings, // for tests
166
+ };