mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-27 22:15:33 +00:00
* feat(git): divergence-safe pull, push-probe, default-branch detection for brain durability Add GIT_ENV_AUTH + divergenceSafePull (skip-on-dirty, conflict-abort-clean, never-mid-rebase), detectDefaultBranch, pushProbe, and an env-gated GBRAIN_GIT_ALLOW_FILE_TRANSPORT escape hatch. Export GIT_ENV. pullRepo's --ff-only contract is unchanged. * feat(durability): brain-repo hardening core (hook, helper, cron, PAT, AGENTS rules) hardenBrainRepo/unhardenBrainRepo: local untracked post-commit hook + committed brain-commit-push.sh (one shared push-retry template), repo-scoped credential with existing-helper reuse, push-probe verify, active-resolver-file rules with taxonomy from _brain-filing-rules.json, minimal DB-free pull cron. PAT redaction via redactSecretsInText. * feat(sources): harden/pull/unharden commands + auto-harden on add --url sources harden/pull/unharden subcommands; --pat-file/--no-harden on add; auto-harden managed clones on add; unharden-before-remove. cli.ts pre-connect early-exit for DB-free 'sources pull --path' (the cron entry, never opens PGLite). * test(durability): unit + integration coverage for brain-repo durability git helpers, core harden/unharden, hook+helper E2E (real background push), cron generators. 41 tests across 4 files. * chore: bump version and changelog (v0.42.48.0) Brain-repo git durability: auto-harden a brain's working tree (local auto-push hook, committed commit-push helper, always-on agent rules, DB-free pull cron, repo-scoped credential, push-probe verify) the moment gbrain gets a PAT + URL. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sources): route harden exit code through setCliExitVerdict A raw process.exitCode write is zeroed by the owned-verdict flush-exit (#2084 PGLite-Emscripten pollution defense); cli-exit-verdict-pin guard caught it. Use setCliExitVerdict(3) so 'sources harden' actually reports needs-attention to cron/automation. * docs: document brain-repo durability (KEY_FILES + multi-source guide) KEY_FILES: extend git-remote.ts entry (divergenceSafePull, pushProbe, detectDefaultBranch, GIT_ENV_AUTH, GBRAIN_GIT_ALLOW_FILE_TRANSPORT) + add brain-repo-durability.ts/sources-harden.ts entry. multi-source-brains.md: add a Durability (auto-harden) how-to covering sources harden/pull/unharden, --pat-file, the guarantees, and the security posture. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
45 lines
1.9 KiB
TypeScript
45 lines
1.9 KiB
TypeScript
/**
|
|
* Durability cron generators (v0.42.44, D2 + D12): pure-string renderers.
|
|
* Asserts the cron is DB-free (gbrain sources pull --path, NOT `pull <id>`),
|
|
* secret-free, self-disabling, and that the launchd plist is periodic.
|
|
*/
|
|
import { describe, test, expect } from 'bun:test';
|
|
import { renderCronWrapper, generateBrainPullPlist } from '../src/core/brain-repo-durability.ts';
|
|
|
|
const TOKEN = 'ghp_SHOULD_NEVER_APPEAR';
|
|
|
|
describe('renderCronWrapper (D2 DB-free)', () => {
|
|
const w = renderCronWrapper('wiki', '/data/clones/wiki', 'main', '/usr/local/bin/gbrain', '/home/u/.gbrain/brain-push.log');
|
|
|
|
test('calls the DB-free path command, not the engine-opening one', () => {
|
|
expect(w).toContain("sources pull --path '/data/clones/wiki'");
|
|
expect(w).toContain("--branch 'main'");
|
|
expect(w).not.toMatch(/sources pull '?wiki'?(\s|$)/); // never `sources pull wiki`
|
|
});
|
|
|
|
test('self-disables when the captured checkout is gone', () => {
|
|
expect(w).toContain("if [ ! -d '/data/clones/wiki/.git' ]");
|
|
expect(w).toContain('path gone, skipping');
|
|
});
|
|
|
|
test('sources the shell profile (secret-free) and never bakes a token', () => {
|
|
expect(w).toContain('source ~/.zshenv');
|
|
expect(w.includes(TOKEN)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('generateBrainPullPlist (D12 launchd)', () => {
|
|
const plist = generateBrainPullPlist('com.gbrain.brain-pull.wiki', '/home/u/.gbrain/brain-pull-wiki.sh', '/home/u', 1800);
|
|
|
|
test('is periodic (StartInterval), not a KeepAlive daemon', () => {
|
|
expect(plist).toContain('<key>StartInterval</key><integer>1800</integer>');
|
|
expect(plist).not.toContain('<key>KeepAlive</key>');
|
|
});
|
|
|
|
test('carries the per-source label and the wrapper path only (no secret)', () => {
|
|
expect(plist).toContain('<string>com.gbrain.brain-pull.wiki</string>');
|
|
expect(plist).toContain('/home/u/.gbrain/brain-pull-wiki.sh');
|
|
expect(plist.includes(TOKEN)).toBe(false);
|
|
});
|
|
});
|