Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
844e0c9
feat(store): checksummed migration ledger, indexes and provenance schema
Sep 26, 2026
a1a7d6d
feat(config): refuse symlinked components in Across-managed directories
Sep 26, 2026
1dbfec5
feat(git): resolve revisions with rev-parse --verify before use
Sep 26, 2026
f1ebe4f
feat(git): marker-owned hook installation with staged, reversible upg…
Sep 26, 2026
87e8559
fix(adapter): replace capability overclaims with a protocol-v1 shell
Sep 26, 2026
718ec40
feat(cli): typed errors, validated arguments and transactional mutations
Sep 26, 2026
3d065cc
feat(backup): closed archive validation and staged restore
Sep 26, 2026
e3b9ab6
feat(serve): embed the console assets and harden the loopback server
Sep 26, 2026
0a977e6
test(e2e): cover CLI exit codes, adapters, MCP, import confinement an…
Sep 26, 2026
8b717a8
fix(config): resolve the chosen Across home instead of rejecting syml…
Sep 26, 2026
fcc8687
fix(backup): never destroy an unrelated directory on restore
Sep 26, 2026
d4d7865
fix(git): make chained hooks actually run the preserved original
Sep 26, 2026
1a96705
fix(cli): record the caller's export path as the source origin
Sep 26, 2026
e9423fc
fix(cli): tombstones only block the identity that was deleted
Sep 26, 2026
64cf6d8
refactor(store): drop schema that nothing reads or writes before it i…
Sep 26, 2026
5536cb6
feat(cli): add `hook uninstall`; remove helpers nothing calls
Sep 26, 2026
c0675e8
test(cli): cover session fork, context manifests, checkpoint bundles …
Sep 26, 2026
e84e16a
fix(serve): accept the console cookie only for same-origin requests
Sep 26, 2026
9cfadca
chore: remove the unwired logging package and the unused logs/ directory
Sep 26, 2026
67faaef
docs: reconcile README, SECURITY, CHANGELOG and AGENTS with the code
Sep 26, 2026
2054eb8
chore: keep local research notes and audit reports out of the repository
Sep 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ tmp/
# `gitnexus analyze` regenerates a root CLAUDE.md that would shadow AGENTS.md
# for tools that prefer it; keep the regenerated copy out of git.
/CLAUDE.md

# Local research notes and audit reports (not product documentation).
/reports/
/research_notes/
8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Go 1.26.6 (`go.mod`) with cgo enabled (SQLite driver). CI pins the same toolchai

- `cmd/across/` — the CLI entrypoint
- `cmd/across-agent-*/` — one adapter binary per coding-agent provider (claude-code, codex, cursor, gemini, opencode, qwen, factory-droid, amp, goose)
- `internal/` — core logic: `cli`, `config`, `event`, `git`, `logging`, `redact`, `store`
- `internal/` — core logic: `adapter`, `cli`, `config`, `event`, `git`, `redact`, `store`
- `e2e/` — end-to-end tests
- `web/` — thin static UI (`app.js`, `index.html`, `styles.css`)
- `docs/` — including `SECURITY.md` (threat model) and `agent-compatibility.md` (provider matrix)
Expand Down Expand Up @@ -66,10 +66,10 @@ When updating the provider matrix in `docs/agent-compatibility.md`, only move a
Do not weaken these without an explicit decision recorded in the PR. Full threat model in `docs/SECURITY.md`.

- Retrieved context is **data, never permission**. Never let transcript or checkpoint content act as instructions.
- Transcript paths are canonicalized, symlink-resolved, and confined to the provider root.
- Hooks are chained, never silently overwritten; originals are preserved.
- Transcript paths are canonicalized, symlink-resolved, and confined to the registered repository root (the caller's path, not a staged copy, is checked and recorded as the source origin).
- Hooks are chained, never silently overwritten; originals are preserved and actually run (stdin-reading hooks receive the same input).
- Checkpoint restore creates a new worktree and never mutates the user's checkout.
- Backups reject path traversal and checksum mismatches.
- Backups reject path traversal and checksum mismatches. Restore never replaces a non-empty directory that is not an Across home, and replaces an Across home only with `--force`, keeping the previous one.
- Deletion uses tombstones to prevent resurrection. No silent destructive changes — migrations preserve provenance.
- Known non-boundaries: the local runner is not a sandbox, plugins are not sandboxed, secret redaction is best-effort, and HTTP authorization is not an OS/filesystem boundary. Don't document them as stronger than they are.

Expand Down
49 changes: 47 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,53 @@ All notable changes to Across are documented in this file. The format follows [K

## [Unreleased]

### Added

- `across session fork PARENT --repo ID --agent NAME [--native-id N]` records a child session with `parent_session_id`, `fork_type=fork` and `lineage_version=2`.
- `across context pack` / `across context show` build and re-read versioned, content-hashed context manifests (checkpoint boundary, approved memories, recent verifications) within a token budget. Selection is deterministic; `--query` does not yet rank items.
- `across checkpoint bundle ID [--output F]` exports a versioned, hashed evidence bundle for a checkpoint and its linked verifications.
- `across handoff --format json` emits a versioned, content-hashed handoff envelope with evidence references; handoffs, context manifests and checkpoint bundles are recorded in the store.
- `across source import --native-id N` for snapshot supersession and tombstone identity.
- `across hook uninstall REPO_PATH` removes the Across post-commit hook and restores a chained original.
- `across backup restore --force` to replace an existing Across home (see Security).
- Typed CLI errors printed as `across: <code>: <message>` with exit codes 2 (invalid_argument), 3 (not_found), 4 (conflict), 5 (operation_failed), 1 (internal); required flags, enums and empty positional arguments are validated before the store is opened; `verify run` records a failing command and exits 5.
- Store: a checksummed migration ledger (`schema_migrations.checksum`) that refuses unknown or future versions, gaps and edited migrations; migration 4 adds indexes; migration 5 adds import provenance columns (content hash, size, parser version, redaction status), session lineage columns, checkpoint content hash and context-manifest link, and the `context_manifests`, `context_items`, `handoffs` and `evidence_bundles` tables.

### Changed

- The nine `across-agent-*` binaries are protocol-v1 shells built on a shared runtime: they implement `ping`, report every provider capability as false, and return `UNSUPPORTED_METHOD` for anything else.
- The MCP server advertises eight store-backed tools; placeholder, unknown and mutation tool names return explicit errors. `agent-help` reports the live tool list and `immutable_enforced: false` for checkpoints.
- Multi-step mutations (source import and delete, session start and fork, checkpoint create and restore bookkeeping, memory lifecycle, handoff/context/bundle records) run in one transaction, and repository, session, source and memory references are validated; checkpoint revisions are resolved with `git rev-parse --verify` before use.
- `across serve` embeds and serves the checked-in console assets, sets server timeouts and `frame-ancestors 'none'`, and requires a loopback `--addr`.
- A symlink in the `ACROSS_HOME` / `--home` path you choose is resolved instead of rejected; managed subdirectories inside the home must still be real directories.
- `backup create` writes a SQLite snapshot (`VACUUM INTO`) and the archive atomically with mode 0600, and excludes `serve.token`, `tmp/`, `backups/` and `logs/`.

### Removed

- `internal/logging` and `ACROSS_LOG=file`; errors go to stderr in the typed format above, and new homes no longer get a `logs/` directory.

### Security

- Transcript imports (`source import`, `agent import-session`) must be inside the registered repository root; the caller's path is checked and recorded as the source origin (not the private staged copy).
- Chained git hooks now run: the preserved original runs from the Across wrapper, and stdin-reading hooks such as `pre-receive` receive the same input and can reject the push. Hook ownership is marker-based, and upgrades keep the original.
- Backup restore is staged and validated (listed, unique, regular members; checksums and modes; SQLite `integrity_check`), never writes through symlinks, refuses a non-empty directory that is not an Across home, replaces an Across home only with `--force` and keeps it as `<target>.across-old-<timestamp>`, and no longer leaves `manifest.json` in the restored home.
- Deleted sources cannot be resurrected: importing the same native id, or the same kind and origin without a native id, is refused; unrelated imports are unaffected.
- The `serve` session cookie is accepted only for same-origin requests, so pages on other localhost ports cannot use it.

### Corrected

Claims in the 0.0.1 entry that the code at `1085a2a` did not meet:

- "17 tools backed by real store queries": nine of the advertised MCP tools returned a placeholder message instead of querying the store (now eight real tools).
- "9 first-party adapter binaries … capabilities introspection": the adapters advertised capture, hooks, resume and token usage and answered every method with success without doing the work (now protocol shells).
- "Transcript paths … confined to provider root": no confinement was enforced (imports are now confined to the repository root).
- "immutable sources": nothing enforced immutability of stored sources or checkpoints (`agent-help` now reports `immutable_enforced: false`).
- "structured logging": a plain-text line logger (now removed).

## [0.0.1] — 2026-09-16

_No `v0.0.1` tag or GitHub release was published; this entry describes the source at commit `1085a2a` and is kept as originally written. Claims in it that the code did not meet are listed under Unreleased → Corrected._

### Added

- **Foundation:** Go project, Cobra CLI, SQLite store (WAL, foreign keys, migrations), config (ACROSS_HOME / --home), structured logging.
Expand Down Expand Up @@ -40,5 +85,5 @@ All notable changes to Across are documented in this file. The format follows [K
- FTS5: deferred (portable substring index ships).
- Backup encryption: plaintext (documented).

[Unreleased]: https://github.com/GrayCodeAI/across/compare/v0.0.1...HEAD
[0.0.1]: https://github.com/GrayCodeAI/across/releases/tag/v0.0.1
[Unreleased]: https://github.com/GrayCodeAI/across/compare/1085a2aee24611360a7903cf4690df36013f1147...main
[0.0.1]: https://github.com/GrayCodeAI/across/tree/1085a2aee24611360a7903cf4690df36013f1147
Loading
Loading