docs: multi-client learn hooks + Phase 2/3 command rewriting - #959
docs: multi-client learn hooks + Phase 2/3 command rewriting#959AlexMikhalev wants to merge 43 commits into
Conversation
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.
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.
Documentation PreviewYour documentation changes have been deployed to: 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.
68f8a84 to
bc9d019
Compare
structural-pr-review (independent pass after branch rebuild)PR: Gitea #3186 / GH #959 Scope check (critical)
Previous merge attempts were correctly blocked / dangerous: branch was not docs-only relative to Gitea Diff review
FindingsFindings: 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)
Observed on head before rebuild: After rebuild: Verdict
Process noteEarlier merges on clients (#90–#93) used abbreviated author-side “structural” comments, not a full load of the terraphim-skills |
- 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
Independent structural-pr-review completed
Full reviews on Gitea #3186. P1s fixed in c2e2541+. |
|
Merged on Gitea as #3186 (admin force_merge by root). Gitea is source of truth for this docs change. |
|
Closed: merged on Gitea #3186 as 1ff006f (admin force_merge). GH branch diverged/conflicting; Gitea main is SoT for this docs change. |
Extend howto for Claude/OpenCode/pi + #810 P2/P3. Related #2704 closed, clients #93 recursive KG.