Skip to content

feat(crush): source+dest adapter for crush.db v1 (#40) - #110

Merged
ImL1s merged 3 commits into
mainfrom
feat/issue-40-crush-source-dest
Jul 30, 2026
Merged

feat(crush): source+dest adapter for crush.db v1 (#40)#110
ImL1s merged 3 commits into
mainfrom
feat/issue-40-crush-source-dest

Conversation

@ImL1s

@ImL1s ImL1s commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

Implements #40: Crush source adapter + destination Skill host.

  • Source: crush-sqlite-v1 — pin goose_db_version max 7; store crush.db under data dir / project .crush/ / exact DB path
  • List/show: root sessions only by default (parent_session_id empty); exact ref can select children; parts {type,data} extract text/tool/shell; fail closed on corrupt JSON
  • Destination: .crush/skills + ~/.config/crush/skills (+ agents/claude compat discovery)
  • Matrix: registry-derived 12×12=144
  • Does not invoke Crush CLI/serve/migrations/MCP

Test plan

  • PYTHONPATH=src python3 -m unittest discover -s tests -q
  • python3 scripts/self_verify.py
  • python3 scripts/check_secrets.py
  • CI green on PR
  • Exact-HEAD @codex review with no open P1

Add Crush as a first-class source and destination host.

- Read crush-sqlite-v1 from per-project .crush/crush.db (goose_db_version max 7)
- Default list: root sessions with extractable turns; exact-id reaches children
- Fail closed on corrupt parts JSON; no recursive home multi-project scan
- Destination install: .crush/skills + ~/.config/crush/skills
- Registry matrix 12×12=144; fixtures, smoke, STATUS/CHANGELOG/README honesty
@ImL1s

ImL1s commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7190c5af45

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/portable_resume/adapters/crush.py Outdated
FORMAT_ID = "crush-sqlite-v1"
# Migrations: initial + summary_message_id + created_at_indexes + provider +
# is_summary_message + todos + read_files (pressly/goose version_id sequence).
SCHEMA_VERSION = 7

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Compare against the actual goose migration ID

For real Crush databases, Pressly/goose stores each migration filename's numeric prefix in goose_db_version.version_id; the latest migration named in this file therefore records 20260127000000, not the ordinal count 7. Because _require_schema() compares MAX(version_id) with this constant, every current real crush.db is reported as unsupported while the synthetic fixtures pass only because they invent version IDs 1..7.

Useful? React with 👍 / 👎.

Comment thread src/portable_resume/adapters/crush.py Outdated
Comment on lines +309 to +312
if query.cwd is not None:
try:
cwd = canonicalize_cwd(query.cwd)
except DiagnosticError:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject mismatched cwd instead of relabeling sessions

When --source-root points at one project's database while --cwd names another project, this assigns the requested cwd without comparing it with the resolved database/project root. The adapter can therefore select context from project A and emit it as project B's handoff metadata; infer cwd only from a recognized project-root layout, or reject/filter conflicting cwd values rather than copying the caller's value.

Useful? React with 👍 / 👎.

Comment thread docs/STATUS.md
| Discovery false unsupported / stale SQLite | [Issue #7](https://github.com/ImL1s/resume-skills/issues/7) + plan 026 | **Done (P1a / PR #93 → `7ff33eb`):** probe uses DB signature without sessions walk; soft-capped sample for plain/zstd; byte-bounded head; FS soft merge/rank with `W_TRUNCATED`. Show streaming plain path **done** via #8 / PR #94. |
| Peak memory on large show | [Issue #8](https://github.com/ImL1s/resume-skills/issues/8) + plan 027 | **Done (plain):** PR #94 → `8ac5549` / pin `cba2e34` — `stable_scan_lines` + attempt-local reduce; ~20 MiB regression; updated_at pinned to scanned inode. Residual: zstd full decompress; collect-then-yield still residual with #10. |
| Capability registries + dynamic matrix | [Issue #36](https://github.com/ImL1s/resume-skills/issues/36) | **Done (product axes):** independent source/destination/package registries; rectangular matrix derived from enabled sets (currently **11×11=121** on main; published `0.3.4` was **9×9=81**); package surfaces drive native zip builds; schema source enum matches enabled sources (incl. `pi`, `openclaw`, `goose`). Residual: auto-generated docs tables / planned-profile release gates still manual. |
| Capability registries + dynamic matrix | [Issue #36](https://github.com/ImL1s/resume-skills/issues/36) | **Done (product axes):** independent source/destination/package registries; rectangular matrix derived from enabled sets (currently **12×12=144** on main; published `0.3.4` was **9×9=81**); package surfaces drive native zip builds; schema source enum matches enabled sources (incl. `pi`, `openclaw`, `goose`). Residual: auto-generated docs tables / planned-profile release gates still manual. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align the status gate rows with the 144-cell claim

This newly updated row says the current matrix is 12×12=144, but the top-level Packaging matrix and Installed runner matrix gates still claim 121/121 and 11×11. Readers therefore get contradictory current evidence from the repository's designated status document; update those gate rows to the verified 144/144 result, or avoid claiming 144 here until that evidence is recorded.

AGENTS.md reference: AGENTS.md:L47-L47

Useful? React with 👍 / 👎.

self.assertNotRegex(
text,
r"(?i)goose[^.\n]{0,60}(picker|native).{0,20}pass",
r"(?i)crush[^.\n]{0,60}(picker|native).{0,20}pass",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add a separate not-run assertion for Crush

The added Crush regex is passed as assertNotRegex's optional failure-message argument, so the test still checks only the goose pattern and will pass even if docs/STATUS.md starts claiming that Crush's native picker passed. Put the Crush regex in its own assertion so the documented not-run honesty gate is actually enforced.

AGENTS.md reference: AGENTS.md:L26-L26

Useful? React with 👍 / 👎.

Use real Pressly/goose version_id prefixes (max 20260127000000) instead of
ordinals so live crush.db stores are supported. Bind handoff cwd only from
project-layout roots and filter/list-fail when --cwd conflicts with that
project. Align STATUS packaging gates to 144/144 and harden honesty checks.
@ImL1s

ImL1s commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Unknown error
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

)

Store synthetic DBs under <project>/.crush/crush.db and align installed-runner
smoke cwd with that project root. select_session requires summary.cwd when
query.cwd is set; data-dir-only fixtures left latest empty under smoke.
@ImL1s

ImL1s commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

1 similar comment
@ImL1s

ImL1s commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19f5da763a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +124 to +125
# No source_root: only try <cwd>/.crush (closed policy — no home scan).
if query.cwd:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Discover Crush's configured global data directory

When Crush is using its CRUSH_GLOBAL_DATA mode, the active crush.db resides in the platform-resolved global data directory rather than <cwd>/.crush. This implicit-discovery branch only checks the latter and never consults the setting, so an ordinary installed resume-crush invocation reports the source unavailable unless the user manually supplies --source-root.

Useful? React with 👍 / 👎.

Comment on lines +595 to +596
project_rel=".crush/skills",
global_rel=".config/crush/skills",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor CRUSH_SKILLS_DIR for global installs

When a user configures Crush with CRUSH_SKILLS_DIR, global install/verify/uninstall still resolve the fixed ~/.config/crush/skills path because this profile does not declare or otherwise handle the host override. The installer can therefore report success after placing Skills in a directory that the configured Crush instance does not load.

Useful? React with 👍 / 👎.

Comment on lines +235 to +240
def _session_cwd(query: Query, database: str) -> str | None:
"""Handoff cwd from project layout only — never copy caller cwd (Codex P1)."""

if not _cwd_matches_query(query, database):
return None
return _project_cwd(database)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep latest selectable for direct database roots

When --source-root is a data directory or exact crush.db outside a <project>/.crush/ layout and the invocation also supplies --cwd, this returns None for every summary's cwd. The shared select_session() excludes cwd-less summaries when resolving latest or free-text refs, so the advertised direct/data-directory forms return E_NO_MATCH for the common show latest --cwd ... invocation even though exact IDs work.

Useful? React with 👍 / 👎.

Comment thread docs/STATUS.md
| Post-manifest stale journal recover (#64 gate P1) | [PR #70](https://github.com/ImL1s/resume-skills/pull/70) → `e6a26b1` | **Fixed on main:** if complete journal write fails after ownership manifest publish, `recover_root` matches journal target generation to on-disk manifest and clears stage/journal only (no payload rollback). Regressions in `test_install_control_store`. |
| Cursor #11 post-merge skeptic P1s | [PR #72](https://github.com/ImL1s/resume-skills/pull/72) → `3e94dea` | **Fixed on main:** Desktop list window = `scanned_records+1` (not `listed_sessions*4`); show case-fold for stored UUID; live CLI blob respects lowered `Bounds.record_bytes`. CI green on pre-merge HEAD. |
| Next-wave agent roadmap (Pi, OpenClaw, goose, …) | [Issue #48](https://github.com/ImL1s/resume-skills/issues/48) + [Issue #38](https://github.com/ImL1s/resume-skills/issues/38) | Phase 0 on `7b5192c`. **Pi / OpenClaw / goose** filesystem product paths done (matrix **11×11=121**). Native UI/picker activation not-run for these hosts. Remaining wave agents: Crush/Cline/OpenHands/… |
| Next-wave agent roadmap (Pi, OpenClaw, goose, …) | [Issue #48](https://github.com/ImL1s/resume-skills/issues/48) + [Issue #38](https://github.com/ImL1s/resume-skills/issues/38) | Phase 0 on `7b5192c`. **Pi / OpenClaw / goose** filesystem product paths done (matrix **12×12=144**). Native UI/picker activation not-run for these hosts. Remaining wave agents: Crush/Cline/OpenHands/… |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove Crush from the remaining-wave list

This updated roadmap row still names Crush as remaining work, while the same status document now marks the Crush source and destination done and reports the 12×12 matrix. That leaves the repository's designated done/not-done record internally contradictory; remove Crush from this list or qualify what Crush work actually remains.

AGENTS.md reference: AGENTS.md:L47-L47

Useful? React with 👍 / 👎.

@ImL1s

ImL1s commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

Merge gate (HEAD 19f5da7)

  • CI: green (quality + py3.11–3.14 ubuntu/macos + build/smoke)
  • Exact-HEAD Codex: returned — no P1; P2 only

P2 disposition (document, non-blocking)

  1. CRUSH_GLOBAL_DATA discovery — deferred. Phase 1 closed policy is --source-root / project .crush / <cwd>/.crush only (no multi-root home scan). Documented in source-formats.
  2. CRUSH_SKILLS_DIR install override — deferred. Installer uses fixed .crush/skills + ~/.config/crush/skills; env override is host-side follow-up.
  3. latest + direct data-dir + --cwd — deferred. Project-layout path is the smoke/product default; exact ID still works for data-dir forms. Follow-up if real users hit E_NO_MATCH on bare data-dir + latest.
  4. STATUS remaining-wave list — Crush product path marked done; residual is native UI not-run only.

Ship #40 Crush source+dest (12×12=144).

@ImL1s
ImL1s merged commit 52dc5b4 into main Jul 30, 2026
10 checks passed
@ImL1s
ImL1s deleted the feat/issue-40-crush-source-dest branch July 30, 2026 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant