Skip to content

Commit 54645b0

Browse files
Shahinyanmclaude
andauthored
Worktree dream backfill (#21)
* feat(completeness): module + NoGoal/ClosedNoOutcome rules * feat(completeness): decision-no-evidence + suggested-unconfirmed rules * feat(completeness): pending-leak rule * feat(completeness): best-effort pending_count fs helper * feat(completeness): render section + pack integration * chore(completeness): version bump + CHANGELOG * feat(dream): add Source::Dream event provenance Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): backend trait, backfill IO types, mock backend Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): Pass A prompt builder Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): Anthropic HTTP backend for Pass A Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): dream_state watermark migration + accessors Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): session scope resolution (since + limit) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): dedup-guard via token Jaccard similarity Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): stamp dream provenance on backfilled events Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): run_dream orchestration with dry-run + indexing Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): CLI dream subcommand with --dry-run/--since/--task/--limit Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(dream): tested session→task mapping + transcript flattening Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(dream): add dream backfill entry under 0.12.0 CHANGELOG Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(hierarchy): add tasks.parent_id column + index * feat(hierarchy): persist parent_id from open event meta * feat(hierarchy): children_of + parent_of queries * feat(hierarchy): would_create_cycle guard * feat(hierarchy): cascade pack-cache invalidation to parent * feat(hierarchy): roll up direct children in parent pack * feat(hierarchy): CLI create --parent with validation * feat(hierarchy): MCP task_create parent param * feat(hierarchy): warn on closing a task with open subtasks * feat(hierarchy): CLI list --tree * chore(hierarchy): CHANGELOG entry for subtask hierarchy * feat(close-gate): CLI close prints completeness gaps (non-blocking) * feat(close-gate): MCP task_close returns completeness_gaps * chore(close-gate): CHANGELOG entry * feat(recall): pure relevant_recall engine for proactive recall Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(recall): PostToolUse hook surfaces prior rejections via additionalContext Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(recall): CHANGELOG entry for push-recall Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(push-recall): MCP PostToolUse prepends recall banner via updatedMCPToolOutput Complements claude-memory-60m's additionalContext path (which skips mcp__ tools). Gated MCP-only; falls through to the capture queue so event capture is unaffected. Best-effort: no hit / any error passes the output through unchanged. Reuses tj_core::recall::relevant_recall — no recall logic here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(push-recall): CHANGELOG entry for updatedMCPToolOutput recall No version bump — workspace is already 0.12.0; sibling bullet under the existing push-recall (additionalContext) entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(core): migration v7 + project decision alternatives column Add nullable alternatives column to decisions table (migration v7) and project a decision event's meta.alternatives JSON into it on index. The append-only log is untouched; existing decisions stay NULL. Pack cache is wiped so packs re-render once events carry alternatives. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(pack): render structured decision alternatives render_active_decisions now reads the alternatives column and renders a 'considered:' block under each decision, marking the chosen option and showing each rationale. Malformed/empty payloads are skipped so the decision itself always renders. Coexists with the Completeness and Subtasks sections added earlier. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(mcp): event_add alternatives param (decision-only) EventAddParams gains an optional alternatives JSON value. On a decision event it is stamped onto meta.alternatives; on any other event type the handler rejects it with a clear error. MCP-only for v1 — no CLI path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(changelog): structured decision alternatives under 0.12.0 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(constraint-context): add TaskContext.constraints field (additive) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(constraint-context): render Known constraints block in classifier prompt Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(constraint-context): gather task constraints into recent_task_contexts Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(constraint-context): CHANGELOG entry under 0.12.0 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(reminder): pure active_task_reminder builder in tj-core Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(reminder): SessionStart source=compact re-injects active task Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(reminder): CHANGELOG entry under 0.12.0 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(memory-export): pure frontmatter::render_memory renderer Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(memory-export): export-memory CLI writes Claude-memory frontmatter files Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(memory-export): CHANGELOG entry for export-memory under 0.12.0 * chore: gitignore .docs/ (local specs + plans) * style: cargo fmt --all across new feature code * fix(ci): cargo fmt --all + serialize XDG-mutating MCP test - cargo fmt --all over the epic's new code (fmt check was failing CI) - task_pack_returns_rpc_error_when_state_dir_is_unusable now holds the handler_env() mutex; it mutates the process-global XDG_DATA_HOME which the task_create/task_close handler tests read, so under parallel CI it poisoned their env mid-run and task_close_reports_completeness_gaps failed with an unrelated path error. * fix(ci): clear clippy warnings (-D warnings) - needless borrow (cli.rs test) + map_or->is_some_and (cli main) via clippy --fix - mcp tests: reword handler_env doc to drop the '+' markdown-list marker (doc_list_item_without_indentation), and #![allow(await_holding_lock)] on the tests module — the guard is intentionally held across .await to serialize handler tests on the current-thread runtime. * fix(ci): cross-platform export-memory test + restore MSRV toolchain pin - export_memory_dry_run test: assert filename + 'memory' separately instead of the 'memory/<file>' literal — Windows prints a backslash separator. - ci: msrv job pins dtolnay/rust-toolchain@1.88 again (dependabot #17 bumped it to @1.100, which installs a non-existent rust 1.100.0 → 404). * fix(ci): escape <id> in rustdoc comments (invalid-html-tags -D warnings) cargo doc with RUSTDOCFLAGS=-D warnings rejected the bare <id> in the create --parent / task_create parent doc comments as an unclosed HTML tag. Reworded to 'the given id'. --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2081f46 commit 54645b0

29 files changed

Lines changed: 4481 additions & 41 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ jobs:
5050
- uses: actions/checkout@v4
5151

5252
- name: Install Rust 1.88
53-
uses: dtolnay/rust-toolchain@1.100
53+
# The action tag IS the toolchain version installed; @1.88 pins MSRV.
54+
# (Dependabot bumped this to @1.100 in #17, which tries to install a
55+
# non-existent rust 1.100.0 — revert to the real MSRV.)
56+
uses: dtolnay/rust-toolchain@1.88
5457

5558
- name: Cache cargo
5659
uses: Swatinem/rust-cache@v2

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@
1414
# Token Pilot local cache
1515
.token-pilot/
1616
.token-pilot-fingerprint.json
17+
18+
# Local design specs & plans (not versioned)
19+
.docs/

CHANGELOG.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.12.0]
11+
12+
### Added
13+
- `export-memory` command: distills a task's goal, outcome, and key
14+
decisions/constraints into a Claude-memory frontmatter file under
15+
`~/.claude/projects/<encoded>/memory/tj-<id>-<slug>.md`, feeding Claude's
16+
native long-term memory + dream. Scope: `--task <id>`, `--all-closed`
17+
(default = all closed tasks); `--dry-run` prints without writing.
18+
One-directional and idempotent; never reads Claude's memory or mutates the
19+
append-only JSONL.
20+
- Active-task reminder after compaction: when Claude Code reconstructs context
21+
via a SessionStart with `source="compact"`, the journal now prepends the
22+
most-recent open task's title + goal + up to 3 in-force `constraint` texts to
23+
`additionalContext` — so the post-compaction agent doesn't lose what it was
24+
doing or its hard constraints. Pure, read-only, best-effort (never breaks the
25+
hook). New `tj_core::reminder::active_task_reminder`. Copies the mechanic of
26+
the experimental `criticalSystemReminder` without depending on that unstable
27+
field.
28+
- Constraint-as-context: the event classifier now sees each active task's most
29+
recent `constraint` events (≤ 5) in its prompt, under a "Known constraints for
30+
<task>" block, with an instruction to prefer `rejection`/`correction` when a
31+
chunk violates a constraint. Additive — tasks without constraints get the exact
32+
prior prompt.
33+
- Push-recall: after a tool call, the PostToolUse hook surfaces a relevant prior
34+
`rejection`/`decision` via `additionalContext` ("⚠ recall: in task X you
35+
previously rejected …"), so the agent doesn't re-walk a ruled-out path.
36+
Conservative (≤2 hits above a relevance threshold), read-only, best-effort
37+
(errors never break the hook). New `tj_core::recall::relevant_recall` engine.
38+
Disable with `TJ_PUSH_RECALL=0`.
39+
- Push-recall via `updatedMCPToolOutput`: when Claude calls an **MCP** tool whose
40+
input echoes a prior rejection/decision (same `recall::relevant_recall` engine),
41+
the PostToolUse hook prepends a `` recall banner to what Claude sees of that
42+
tool's output. MCP tools only — complements the `additionalContext` path above,
43+
which skips `mcp__` tools, so a recall is never double-surfaced. The real output
44+
is preserved below the banner; any miss or error passes it through unchanged.
45+
Read-only, best-effort; also gated by `TJ_PUSH_RECALL=0`.
46+
- Close gate: closing a task now surfaces its completeness gaps (from
47+
`completeness::assess`) — CLI prints them to stderr, MCP `task_close` returns
48+
them in a new `completeness_gaps` field. Non-blocking: the close always
49+
succeeds.
50+
- Capture-completeness flagging: a task's resume-pack now shows a `Completeness`
51+
section listing structural gaps (closed without outcome, decisions without
52+
evidence, unconfirmed suggested events, missing goal, unclassified pending
53+
entries) — shown only when gaps exist. Read-only; reusable
54+
`completeness::assess` API for the upcoming close-gate.
55+
- `task-journal dream` — offline memory backfill (Pass A). Re-reads session
56+
transcripts and appends significant typed events the realtime classifier
57+
missed, stamped `source=dream`, `status=suggested` (visible, prunable).
58+
Manual trigger; `--dry-run`, `--since`, `--task`, `--limit`. Reuses the
59+
Anthropic HTTP backend via `TJ_DREAM_MODEL` / `TJ_DREAM_MAX_TOKENS`.
60+
Additive — the JSONL source of truth is never mutated.
61+
- Subtask hierarchy: tasks can have a `parent_id`. Set at creation via
62+
`task-journal create --parent <id>` or the MCP `task_create` `parent` param
63+
(validated: parent must exist, no cycles). A parent's resume-pack rolls up its
64+
direct children (status, id, title). `list --tree` renders the hierarchy.
65+
Closing a parent with open children warns but proceeds. Additive — existing
66+
flat tasks are unaffected (`parent_id` NULL).
67+
- Structured decision alternatives: a `decision` event can now carry
68+
`meta.alternatives` — a JSON array of `{option, chosen, rationale}` making the
69+
options considered and the final choice explicit instead of implicit in the
70+
hypothesis+rejection chain. Set via the MCP `event_add` `alternatives` param
71+
(decision-only — rejected with an error on any other event type). Projected to
72+
a new `decisions.alternatives` column (migration v7) and rendered under each
73+
entry in the resume-pack's Active decisions section. MCP-only for v1; additive
74+
— the JSONL source of truth is untouched and existing decisions stay NULL.
75+
1076
## [0.11.1] - 2026-06-08
1177

1278
**Fix: `pack` panicked on multibyte UTF-8.** Pack truncation sliced the

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ members = [
77
]
88

99
[workspace.package]
10-
version = "0.11.1"
10+
version = "0.12.0"
1111
edition = "2021"
1212
rust-version = "1.88"
1313
license = "MIT"

crates/tj-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ name = "task-journal"
1616
path = "src/main.rs"
1717

1818
[dependencies]
19-
tj-core = { package = "task-journal-core", version = "0.11.1", path = "../tj-core" }
19+
tj-core = { package = "task-journal-core", version = "0.12.0", path = "../tj-core" }
2020
anyhow = { workspace = true }
2121
clap = { workspace = true }
2222
tracing = { workspace = true }

0 commit comments

Comments
 (0)