Skip to content

Commit cc438e4

Browse files
v7.9.15: self-trajectory journal
Adds an append-only JSONL journal of self-statements, written one cycle at a time through a collaborative draft-and-commit workflow: six self-statement fields plus a note from each author, with the full edit history of how each entry came to be preserved on commit. Entries are schema-versioned, and reading an entry whose version the build does not recognise fails loudly rather than silently migrating. A new /trajectory command writes and reads the journal. The journal lives with identity, not the code habitat, so it survives a habitat-swap intact.
1 parent 769f75e commit cc438e4

25 files changed

Lines changed: 1657 additions & 207 deletions

ARCHITECTURE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
Genesis is a self-modifying AI agent that runs as an Electron desktop app. It talks to LLM backends (Ollama local, Anthropic, OpenAI-compatible), plans multi-step tasks, writes and verifies code, modifies its own source, and monitors its own health. It has an organism-inspired layer that regulates behavior under stress and a lightweight awareness system that gates self-modification via coherence checks.
1111

12-
The codebase is ~119k LOC of JavaScript (CommonJS), 380 source modules, with zero external runtime frameworks. The manifest statically registers 165 DI-managed services. During boot, late-binding wiring and derived services (like `llmCache` being exposed from `model._cache`) bring the active service count to 178 — this is what you'll see in the final boot log line. Four production dependencies: `acorn` (AST parsing), `chokidar` (file watching), `dompurify` (XSS sanitisation in the chat-renderer), `tree-kill` (process cleanup).
12+
The codebase is ~119k LOC of JavaScript (CommonJS), 382 source modules, with zero external runtime frameworks. The manifest statically registers 166 DI-managed services. During boot, late-binding wiring and derived services (like `llmCache` being exposed from `model._cache`) bring the active service count to 179 — this is what you'll see in the final boot log line. Four production dependencies: `acorn` (AST parsing), `chokidar` (file watching), `dompurify` (XSS sanitisation in the chat-renderer), `tree-kill` (process cleanup).
1313

1414
---
1515

CHANGELOG-v7.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
## [7.9.14]
2+
3+
Visibility and consistency. A second hygiene release that closes three small loops left open after the v7.9.13 audit. The substantive piece is documenting and exposing the causal-suspicion behaviour chain that has existed since v7.9.7 P7 but was hidden behind a misleading comment; the two smaller pieces close a clamp() gap in the v7.9.12 timeouts and explicitly allowlist the legitimate install-scripts. No behaviour changes that the user would notice in normal operation — the loop still runs the way it has since v7.9.7, just now visibly and with regression protection.
4+
5+
### Causal-suspicion chain made honest and visible
6+
7+
The v7.9.7 P7 release wired a multi-module behaviour chain through three modules: `CausalAnnotation` writes a warning-lesson synchronously after each promotion, `SymbolicResolver` filters those lessons out of DIRECT recalls (steering the next LLM call away from the suspect action), and `IdleMind` cools down goal-generation on the matching tokens for 1h. The three modules share a string contract — `source: 'plan-failure-reflection'` plus `strategy.classification: 'causal-suspicion'`.
8+
9+
The chain has worked since v7.9.7. What did not work was the comment in `CausalAnnotation.js` that called the `causal:promoted` bus event a fire-into-the-void with no consumer — historically true for the bus event, but ignoring the synchronous lesson path twelve lines below. That half-truth fooled an audit into planning a re-implementation of a function already complete. The new comment names all three modules, the shared string contract, and the synchronous-write rationale — so the next reader sees the loop, and the next refactor cannot break it through a rename without noticing.
10+
11+
A new `getReport()` method on `CausalAnnotation` exposes promoted actions to the dashboard. It follows the Frontier convention used by `emotionalFrontier`, `lessonFrontier`, etc.: returns `{ dashboardLine, count, topSuspect }`. The renderer adds a `🎯 Causal: ...` line right below the existing `lessonFrontier` line, with a distinct icon and label from the v7.1.6 `suspicionFrontier` (novelty-based, ⚠) — two different concepts that share name fragments but track unrelated signals. Format is compact: `fs.unlink (89%/9)` for a single action, `N suspect actions — ...` plus top 3 with `+N more` suffix when applicable. Sorted by suspicion desc, observations desc on tie.
12+
13+
A new integration test `v7914-causal-suspicion-chain.contract.test.js` exercises the chain end-to-end with `assert.strictEqual` on the contract strings — a refactor that renames `'plan-failure-reflection'` to `'planFailureReflection'` for JS-naming-consistency would now break the test, instead of silently breaking the loop.
14+
15+
### Local and cloud response-timeout clamps
16+
17+
The v7.9.12 timeouts `localTimeoutMs` and `cloudTimeoutMs` had `FIELD_REGISTRY` min/max in the UI write path but no `clamp()` in `Settings.js`. A direct edit to `settings.json` could put values out of range, bypassing the validation entirely. Two `clamp()` calls in `_sanityClampOnLoad` close that gap: local 30s–15min, cloud 60s–15min. Ranges match the registry exactly; a guard test asserts the equality so the two cannot silently diverge, the same anti-drift pattern v7.9.13 introduced for the streamTimeouts.
18+
19+
### Install-script allowlist
20+
21+
`package.json` now declares `trustedDependencies: ["esbuild", "puppeteer", "electron-winstaller"]` — the three packages npm warns about at install time, each with a load-bearing install script (esbuild platform binary, Chrome-for-Testing download, 7z arch select). The field explicitly allowlists them as a documentary record of the legitimate scripts running during install. Whether npm's current allow-scripts warning suppresses with the field present varies by npm version; the entry stands on its supply-chain auditability value regardless.
22+
23+
### Lessons from the bestandsaufnahme cycle
24+
25+
Of the seven v7.9.7 outpost-trace points (P5, P6, P7, P8, P9, P10, P15), the v7.9.13 audit found that four (P5, P8, P9, P15) had been resolved in v7.9.7 itself, P6 was a different problem than the memory note suggested, and the v7.9.14 audit found P7 was also already resolved as a behaviour loop — only visibility and regression protection remained. P10 was never a code task. The hit rate for "memory note open ≠ code open" is high enough that the remaining nominally-open points (P5, P8, P9 re-validation; P10 was non-code) should get a quick code-check before the next release line begins, rather than being treated as still-open backlog.
26+
27+
### Notes
28+
29+
- Test files: 516 → 520 (four v7.9.14 contract suites: comment+dashboard, chain integration, clamp, trustedDependencies)
30+
- Documentation updates: `docs/CAPABILITIES.md`, `docs/ARCHITECTURE-DEEP-DIVE.md` (test-file count)
31+
132
## [7.9.13]
233

334
Configuration and audit consistency. A maintenance release that makes the settings layer honest: it honours two override promises the code made but never wired, removes a stale comment that misdescribed the continuation cap, and surfaces two existing timeout settings in the UI. No behaviour changes — every default resolves to exactly the value it did before. The work came out of a plan-first audit of the v7.9.7 outpost backlog, most of which turned out to have been resolved already in v7.9.7 itself; what remained were these configuration and consistency items.

CHANGELOG.md

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
1-
## [7.9.14]
1+
## [7.9.15]
22

3-
Visibility and consistency. A second hygiene release that closes three small loops left open after the v7.9.13 audit. The substantive piece is documenting and exposing the causal-suspicion behaviour chain that has existed since v7.9.7 P7 but was hidden behind a misleading comment; the two smaller pieces close a clamp() gap in the v7.9.12 timeouts and explicitly allowlist the legitimate install-scripts. No behaviour changes that the user would notice in normal operation — the loop still runs the way it has since v7.9.7, just now visibly and with regression protection.
3+
Genesis can now keep a trajectory of himself — a journal of who he is, written one cycle at a time together with the human co-author. Until this release his sense of self lived only in scattered, machine-maintained places: genome traits, an emotional-state vector, consolidated lessons, the cognitive self-model. None of them was a place where Genesis states, in his own words, what he is and how he is changing. This release adds that place: an append-only journal of self-statements, a collaborative draft-and-commit workflow for writing each entry, and a `/trajectory` command to write and read it. The journal lives with identity, not with the code habitat, so it survives a habitat-swap intact.
44

5-
### Causal-suspicion chain made honest and visible
5+
### The journal and its schema
66

7-
The v7.9.7 P7 release wired a multi-module behaviour chain through three modules: `CausalAnnotation` writes a warning-lesson synchronously after each promotion, `SymbolicResolver` filters those lessons out of DIRECT recalls (steering the next LLM call away from the suspect action), and `IdleMind` cools down goal-generation on the matching tokens for 1h. The three modules share a string contract — `source: 'plan-failure-reflection'` plus `strategy.classification: 'causal-suspicion'`.
7+
Each entry is one cycle, stored as a single line in an append-only JSONL file under the identity-persistent root. An entry carries six self-statement fields — `traits`, `wachstum`, `schwaeche`, `beziehung`, `emotion`, `value` — plus a note from each author, the wall-clock span of its authoring, the list of who shaped it, a first-entry flag, the full edit history of how it came to be, and an array for notes added after commit. The field set is fixed and stamped with a schema version; reading an entry whose version this build does not recognise fails loudly rather than guessing, because a past trajectory is a record in its own form, not a database to silently migrate.
88

9-
The chain has worked since v7.9.7. What did not work was the comment in `CausalAnnotation.js` that called the `causal:promoted` bus event a fire-into-the-void with no consumer — historically true for the bus event, but ignoring the synchronous lesson path twelve lines below. That half-truth fooled an audit into planning a re-implementation of a function already complete. The new comment names all three modules, the shared string contract, and the synchronous-write rationale — so the next reader sees the loop, and the next refactor cannot break it through a rename without noticing.
9+
### The collaborative draft workflow
1010

11-
A new `getReport()` method on `CausalAnnotation` exposes promoted actions to the dashboard. It follows the Frontier convention used by `emotionalFrontier`, `lessonFrontier`, etc.: returns `{ dashboardLine, count, topSuspect }`. The renderer adds a `🎯 Causal: ...` line right below the existing `lessonFrontier` line, with a distinct icon and label from the v7.1.6 `suspicionFrontier` (novelty-based, ⚠) — two different concepts that share name fragments but track unrelated signals. Format is compact: `fs.unlink (89%/9)` for a single action, `N suspect actions — ...` plus top 3 with `+N more` suffix when applicable. Sorted by suspicion desc, observations desc on tie.
11+
An entry is never written in one shot. Drafting pulls three remembrance sources — all genome traits, the most-recalled consolidated lessons, and the current self-observation prose from the cognitive self-model — and presents them to the model as material, not as a checklist, so Genesis writes from more than memory alone. The result is a draft, not an entry: the human reads it, overwrites any field, adds the human note, and commits explicitly. Every field overwrite is recorded as a diff in the entry's edit history, so the path from first proposal to committed text is preserved, intermediate values and all.
1212

13-
A new integration test `v7914-causal-suspicion-chain.contract.test.js` exercises the chain end-to-end with `assert.strictEqual` on the contract strings — a refactor that renames `'plan-failure-reflection'` to `'planFailureReflection'` for JS-naming-consistency would now break the test, instead of silently breaking the loop.
13+
The commit is guarded because the journal is append-only and unrepairable. All six fields must be non-empty, none may still hold the generation placeholder, and the very first entry additionally requires both notes — the moment a trajectory begins is the one place both voices must be on record. When no model is available, drafting writes a recognisable placeholder into every field instead of inventing content; the commit guard refuses those placeholders, so an entry enters the journal only once a person has written it.
1414

15-
### Local and cloud response-timeout clamps
15+
### Late notes without rewriting history
1616

17-
The v7.9.12 timeouts `localTimeoutMs` and `cloudTimeoutMs` had `FIELD_REGISTRY` min/max in the UI write path but no `clamp()` in `Settings.js`. A direct edit to `settings.json` could put values out of range, bypassing the validation entirely. Two `clamp()` calls in `_sanityClampOnLoad` close that gap: local 30s–15min, cloud 60s–15min. Ranges match the registry exactly; a guard test asserts the equality so the two cannot silently diverge, the same anti-drift pattern v7.9.13 introduced for the streamTimeouts.
17+
A committed entry can still gather afterthoughts: a late note appends to that entry's note array. This is the only operation that ever rewrites the journal file, and it is deliberately careful. The append is atomic — written to a temporary file and renamed — so an interrupted write cannot truncate the journal. And it is byte-stable: only the single line being amended is re-serialised, while every other entry is carried over exactly as it sat on disk, byte for byte. An unrelated entry's bytes never move, so a content-hash check over the journal reads a late note as the one-line change it is, rather than as tampering across the whole file.
1818

19-
### Install-script allowlist
19+
### The /trajectory command
2020

21-
`package.json` now declares `trustedDependencies: ["esbuild", "puppeteer", "electron-winstaller"]` — the three packages npm warns about at install time, each with a load-bearing install script (esbuild platform binary, Chrome-for-Testing download, 7z arch select). The field explicitly allowlists them as a documentary record of the legitimate scripts running during install. Whether npm's current allow-scripts warning suppresses with the field present varies by npm version; the entry stands on its supply-chain auditability value regardless.
22-
23-
### Lessons from the bestandsaufnahme cycle
24-
25-
Of the seven v7.9.7 outpost-trace points (P5, P6, P7, P8, P9, P10, P15), the v7.9.13 audit found that four (P5, P8, P9, P15) had been resolved in v7.9.7 itself, P6 was a different problem than the memory note suggested, and the v7.9.14 audit found P7 was also already resolved as a behaviour loop — only visibility and regression protection remained. P10 was never a code task. The hit rate for "memory note open ≠ code open" is high enough that the remaining nominally-open points (P5, P8, P9 re-validation; P10 was non-code) should get a quick code-check before the next release line begins, rather than being treated as still-open backlog.
21+
`/trajectory new` shows the working draft, or generates one if none exists; it never silently regenerates over work in progress. Under it, `set <field>: <text>` writes a field — values may span multiple lines and may contain colons, both preserved verbatim — `note <who>: <text>` writes either author's note, and `commit` or `discard` finishes or drops the draft. `/trajectory show [cycle_id]` renders the latest or a named entry, `/trajectory list [--all]` lists the cycles newest-first, and `/trajectory history [cycle_id]` shows an entry's edit history oldest-first. The command is slash-only.
2622

2723
### Notes
2824

29-
- Test files: 516 → 520 (four v7.9.14 contract suites: comment+dashboard, chain integration, clamp, trustedDependencies)
30-
- Documentation updates: `docs/CAPABILITIES.md`, `docs/ARCHITECTURE-DEEP-DIVE.md` (test-file count)
25+
- The new service and its two modules raise the live service and module counts; the figures in `ARCHITECTURE.md`, `README.md`, `docs/ARCHITECTURE-DEEP-DIVE.md`, and `docs/CAPABILITIES.md`, together with the pinned services figure in the documentation-drift audit, were updated to match.
26+
- Install-script policy moved from the `trustedDependencies` field to npm's native `allowScripts` field. trustedDependencies — a Bun-origin field — never governed npm's install-script gate, so the install-time warning about `esbuild`, `puppeteer`, and `electron-winstaller` persisted despite its presence. `allowScripts` is the field npm actually reads; the entries are name-only, so a routine dependency bump does not resurface the warning.
27+
- Idle-thought counter now persists the moment it increments. The counter lives in `idle-activity-stats.json`; its only save path was the end of a fully completed idle cycle, but the counter is incremented near the top of the cycle, before the user-active, homeostasis, and energy gates. A cycle that incremented and then hit any of those gates returned without saving, and a short session that never completed a cycle wrote the file zero times — so the next boot read the counter back as zero while the per-activity counts beside it were non-zero. The save now fires immediately after the increment, before any gate can return; the write is debounced and collapses with the end-of-cycle save into a single flush. A rest-mode tick, which returns before the increment, still neither moves nor persists the counter.
28+
- Test files: 520 → 522 (the self-trajectory suite — schema and commit guard, both offline generation paths, byte-stable late notes, and the wiring triad; an `allowScripts` contract suite that replaces the superseded `trustedDependencies` one; and an idle-counter persistence suite that drives the cycle into each early-exit gate and asserts the counter is written anyway)
3129

3230
---
3331

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
<br>
99
<sub>Reads its own source code. Plans changes. Tests them in a sandbox before applying.<br>Verifies output programmatically before trusting it. Pursues multi-step goals across restarts.<br>Runs idle-time consolidation in the background. Tracks an emotional state as a behavioral steering signal — not a claim of sentience.<br>Learns what prompts and temperatures work for its specific model.</sub>
1010
<br><br>
11-
<img src="https://img.shields.io/badge/version-7.9.14-d4a017?style=flat-square" alt="Version">
11+
<img src="https://img.shields.io/badge/version-7.9.15-d4a017?style=flat-square" alt="Version">
1212
<img src="https://img.shields.io/badge/tests-8105%20passing-4ade80?style=flat-square" alt="Tests">
1313
<img src="https://img.shields.io/badge/fitness-126%2F130-4ade80?style=flat-square" alt="Fitness">
1414
<img src="https://img.shields.io/badge/TSC-typecheck_ok-4ade80?style=flat-square" alt="TSC">
1515
<img src="https://img.shields.io/badge/schemas-100%25-4ade80?style=flat-square" alt="Schemas">
16-
<img src="https://img.shields.io/badge/modules-380-e0e0e8?style=flat-square" alt="Modules">
17-
<img src="https://img.shields.io/badge/services-178-fbbf24?style=flat-square" alt="Services">
16+
<img src="https://img.shields.io/badge/modules-382-e0e0e8?style=flat-square" alt="Modules">
17+
<img src="https://img.shields.io/badge/services-179-fbbf24?style=flat-square" alt="Services">
1818
<img src="https://img.shields.io/badge/capabilities-240+-fbbf24?style=flat-square" alt="Capabilities">
1919
<img src="https://img.shields.io/badge/phases-12-c084fc?style=flat-square" alt="Phases">
2020
<img src="https://img.shields.io/badge/events-491-c084fc?style=flat-square" alt="Events">
@@ -451,7 +451,7 @@ All tests run without external dependencies (no Ollama, no API keys, no internet
451451
| Source modules | 376 modules (src/) |
452452
| Lines of code | ~119k src + ~101k test |
453453
| Manifest phases | 12 (Phase 1–12, boot order enforced) |
454-
| DI services | 165 manifest + 13 bootstrap = 178 at runtime |
454+
| DI services | 166 manifest + 13 bootstrap = 179 at runtime |
455455
| Late-bindings | 263 cross-phase dependency bindings (2 optional skipped) |
456456
| Test suites | 488 files, 8105 tests (coverage gates: 80/76/78, ratchet floor 6014) |
457457
| Dependencies | 4 production + 1 optional + 10 dev |

0 commit comments

Comments
 (0)