Skip to content

docs: multi-client learn hooks + Phase 2/3 command rewriting - #959

Closed
AlexMikhalev wants to merge 43 commits into
mainfrom
docs/command-rewriting-multi-client
Closed

docs: multi-client learn hooks + Phase 2/3 command rewriting#959
AlexMikhalev wants to merge 43 commits into
mainfrom
docs/command-rewriting-multi-client

Conversation

@AlexMikhalev

Copy link
Copy Markdown
Contributor

Extend howto for Claude/OpenCode/pi + #810 P2/P3. Related #2704 closed, clients #93 recursive KG.

Test User and others added 30 commits August 6, 2026 19:01
Refs #3161

Adds tests/common/mod.rs exporting scrub_env() and hermetic_home().
Scrubs 19 credential env vars (LLM keys, voice model, local-LLM URLs,
channel tokens, GitHub/Gitea), pins TZ/LANG/LC_ALL, redirects HOME/XDG_*
to per-process temp dir.

Retrofit 5 integration test files: mod common; + per-#[test] call.
Per-fn not per-file because module-scope statements are a Rust syntax
error.

Adds TESTING.md documenting the discipline + live-test opt-in pattern.

Gates green:
- cargo build -p terraphim_tinyclaw --tests (exit 0)
- cargo clippy -p terraphim_tinyclaw --all-targets -- -D warnings (exit 0)
- cargo test -p terraphim_tinyclaw --no-fail-fast (196/196, 1 ignored)
- cargo fmt -p terraphim_tinyclaw --check (clean)

Mirrors Hermes Agent _hermetic_environment fixture (tests/conftest.py:340).
Rust has no autouse fixtures; convention + future CI grep gate is the
closest equivalent.
…tion tests Refs #3161' (#3168) from task/3161-tinyclaw-scrubber into main
…21.1

The crates.io 1.21.0 of terraphim_sessions is broken: it has feature
'aider-connector = ["dep:terraphim-markdown-parser"]' but the source
file crates/terraphim_sessions/src/connector/aider.rs has unconditional
'use terraphim_markdown_parser::...' without cfg-gating. When building
the lib for downstream consumers (terraphim_agent activates aider-connector
feature), the dep resolution fails because [dependencies] doesn't declare
terraphim-markdown-parser on optional=true correctly.

Private Gitea registry has 1.21.1 which adds terraphim-markdown-parser
as a proper optional dep. Redirect consumers via [patch.crates-io] to
get the working version.

Gitea registry has no DELETE endpoint for package versions, so the
broken 1.21.0 cannot be removed. This patch is the canonical workaround.

Refs #3170
Implement credential pooling and wire it into the hybrid LLM router.

- Add credentials module: PoolEntry, CredentialPool, TokenRef,
  EnvVarSource, EnvFileSource, OAuth helpers.
- Add token-aware methods to ProxyClient (chat_with_token,
  chat_with_tools_and_token) so the router can pass an acquired API key.
- Extend HybridLlmRouter with optional CredentialPool; acquire a token
  per proxy request, fall back to static proxy.api_key when exhausted,
  and report success/throttle events to the pool.
- Add build_router() in main.rs to construct the pooled router when
  credentials.enabled = true and provider_class is configured.
- Add provider_class field to CredentialsConfig.
- Add unit + integration tests: 28/28 credentials tests, 4 router
  credential tests; full terraphim_tinyclaw suite passes.

Refs #3162
- Add CredentialError::Unavailable for absent credential values,
  keeping SourceUnreadable for unreadable sources.
- Simplify EnvFileSource::resolve for TokenRef::File to read the file
  directly rather than returning the first parsed env value.
- Import credentials types in main.rs instead of fully-qualified names.

Refs #3162
… router integration' (#3175) from task/3162-credentials-subsystem into main
Sentrux check flagged acp/router.rs::dispatch with cc=42 (limit 20).
Refactored to dispatch via 6 single-method helpers + 2 utility helpers
(parse_params, serialize_result). Main match arm now has cc=11.

All 16 ACP contract tests still pass.
Per rust-fleet-standard evaluation 2026-08-08:

- §1.4 ADD rust-toolchain.toml pinning 1.96 (ADR-0006)
- §1.3 ADD name-keyed build-dir to .cargo/config.toml
- §1.7 ADD .terraphim/skills.toml with mandated baseline
- §1.7 ADD memory/{2026-08-08.md,regressions.md}
- ADD .docs/adr-0006-toolchain-pin.md recording MSRV chain

cargo clean freed 83.1 GiB (no kache on this host).
All 349 tinyclaw tests still pass.
Test User and others added 10 commits August 8, 2026 16:13
Per fleet-standard structural review (pi-rust/openai-codex/gpt-5.5):

- P0 channels/{github,gitea}.rs: replace String == with hmac.verify_slice
  (decode hex + use the hmac crate's constant-time comparison)
- P1 dashboard/cron.rs: add Bearer-token auth for POST /api/cron/fire,
  gated on DashboardState::fire_token (set from TINYCLAW_FIRE_TOKEN)
- P1 channels/email.rs: case-insensitive is_allowed per RFC 5321 §2.4
- P2 channels/{email,github}.rs: custom Debug that redacts tokens

Slack/Telegram/GitHub/Gitea channels keep case-sensitive matching
(matches SlackConfig::is_allowed contract: 'U01234567' ≠ 'u01234567').

351 tests pass.
Was transitive via terraphim_persistence; making it direct so the
opendal::ErrorKind enum comparison in cron/store.rs is stable across
opendal version bumps (no Debug string matching).
Debug string matching (format!("{kind:?}").contains("NotFound")) was
fragile across opendal version bumps. Two call sites in cron/store.rs
changed: read_job (line ~73) and delete_job (line ~102).

Tests: 20 cron lib tests pass (no regression).
Two new pinned-behavior tests:
- test_get_job_missing_returns_none_via_not_found_kind
- test_delete_missing_job_is_idempotent

These lock the contract that opendal surfaces 'NotFound' as a typed
ErrorKind enum. If a future opendal upgrade changes the kind semantics,
these tests fail and the contract is caught.

Tests: cron::store 6/6 (was 4/4).
Mirrors the github channel's test coverage for the constant-time
hex-decode path:
- webhook_verification_rejects_malformed_hex (non-hex chars)
- webhook_verification_rejects_wrong_length_hex (16 bytes instead of 32)

Tests: channels::gitea 7/7 (was 5/5).
…n gap

First run of cargo deny check on the workspace. Found:
- jmap_client/haystack_core (path deps from Wave 4) — no license field
- crossbeam-epoch 0.9.18 — CVE (dev-only via criterion)
- borrow-or-share 0.2.4 — MIT-0 not in allow list
- 5 stale RUSTSEC ignores in deny.toml

Per rust-fleet-standard §1.5, cargo-deny is a merge gate. It was
configured but never ran. This ADOPT decision activates the gate and
tracks the 5 action items to green.

Workspace is NOT currently §1.5 compliant. All previous PRs (incl.
this session's Wave 4) bypassed the gate. 355-test pass + clippy clean
is necessary but not sufficient.
…rmcp)

Sweep of technical cargo-deny findings (per user directive: fix all
technical issues; licensing items handled separately):

1. crossbeam-epoch 0.9.18 → 0.9.20 (CVE in fmt::Pointer impl)
   - Dev-only via criterion → rayon → crossbeam-deque
   - Resolved via cargo update

2. quick-xml 0.37.5 CVEs (RUSTSEC-2026-0194, RUSTSEC-2026-0195)
   - Pinned by self_update git fork at ^0.37.5
   - Cannot upgrade; added explicit ignore with justification
   - Self-update only parses release-manifest XML at binary update time,
     not user-reachable from TinyClaw

3. rmcp 0.9.1 — RUSTSEC-2026-0189 (DNS rebinding in Streamable HTTP)
   - TinyClaw uses stdio + child-process transports only
   - Upgrade to rmcp >= 1.4.0 is a real Wave 2 refactor with breaking
     API changes (ServerInfo/Tool non-exhaustive + peer_info now Arc-typed)
   - Added explicit ignore with TODO for the upgrade
   - Scoped separately from this work item

Result: cargo deny check now passes
'advisories ok, bans ok, sources ok' (licenses FAILED per user
directive to ignore licensing).

Tests: 355/355 still pass.
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Documentation Preview

Your documentation changes have been deployed to:
https://af919ff0.terraphim-docs.pages.dev

This preview will be available until the PR is closed.

Docs-only: extend command-rewriting-howto for Claude/OpenCode/pi
and #810 P2/P3. No .terraphim/ knowledge-stack changes.
@AlexMikhalev
AlexMikhalev force-pushed the docs/command-rewriting-multi-client branch from 68f8a84 to bc9d019 Compare August 8, 2026 19:43
@AlexMikhalev

Copy link
Copy Markdown
Contributor Author

structural-pr-review (independent pass after branch rebuild)

PR: Gitea #3186 / GH #959
Reviewer mode: structural (docs-only after force-push rebuild)
Authoring model/session: prior Hermes session (not this critic pass)

Scope check (critical)

Before rebuild After force-push bc9d0193d
23 files, +916 (included entire fleet .terraphim/ knowledge stack) 1 file, +88 (docs/src/command-rewriting-howto.md only)

Previous merge attempts were correctly blocked / dangerous: branch was not docs-only relative to Gitea main.

Diff review

  • Additive howto sections §7 multi-client (Claude / OpenCode / pi) and §8 Phase 3 compile/export.
  • Dual-CLI warning (learn hook vs KG hook) matches live incident #2704.
  • Binary floor ≥1.21.0 matches clients releases.
  • Paths for hooks/plugins/pi package align with host wiring and clients Update Tauri code after search endpoint changes #90Spring clean config #93.
  • No code, secrets, or lockfile changes.

Findings

Findings: P0=0 P1=0 P2=1

P2 — §8.2 says learned thesaurus is included via “clients PR for recursive walk”. That is merged as clients #93; suggest wording “clients #93 (merged)” so readers don’t hunt an open PR. Non-blocking.

Checks / protection (why Gitea still may not merge)

main branch protection requires status contexts:

  • adf/build
  • adf/pr-reviewer

Observed on head before rebuild: native-ci / build failure/pending; required ADF checks not reported.
API merge returned 405 Please try again later (forge-side) in addition to mergeable: false while dirty.

After rebuild: mergeable: true, files=1. Merge still needs required checks green or admin override.

Verdict

  • Confidence: 5/5 (docs-only, accurate, scope clean)
  • Findings: P0=0 P1=0 P2=1
  • Recommendation: MERGE when adf/build + adf/pr-reviewer (or policy equivalent) are satisfied

Process note

Earlier merges on clients (#90#93) used abbreviated author-side “structural” comments, not a full load of the terraphim-skills structural-pr-review skill + different-model subagent. That was below fleet standard. This comment is the corrected review for the docs PR after scope fix.

- Binary floor 1.21.1; dual-CLI table shows --format AND --learn-hook-type
- Clarify export-kg vs learn compile; clients #93 recursive KG merged
- OpenCode prompt plugin wording; verify expected JSON; cross-repo issue refs
@AlexMikhalev

Copy link
Copy Markdown
Contributor Author

Independent structural-pr-review completed

Round Critic Result
R1 Claude Sonnet (claude -p + structural-pr-review skill) 3/5, P1=2 → REQUEST_CHANGES
R1 MiniMax M3 (opencode) 4/5, P1=2
R1 pi+kimi failed quota
R2 Claude Sonnet 4/5, P0=P1=0 P2=1
R2 pi-rust + Gemini 2.5 Flash 5/5, P0=P1=P2=0
fixup internal plan path P2 pushed

Full reviews on Gitea #3186. P1s fixed in c2e2541+.

@AlexMikhalev

Copy link
Copy Markdown
Contributor Author

Merged on Gitea as #3186 (admin force_merge by root). Gitea is source of truth for this docs change.

@AlexMikhalev

Copy link
Copy Markdown
Contributor Author

Closed: merged on Gitea #3186 as 1ff006f (admin force_merge). GH branch diverged/conflicting; Gitea main is SoT for this docs change.

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