fix: repair main CI (missing mcp dispatch + untracked adapter files) - #86
Conversation
…access anh Tam's direct request mid-session 2026-07-24: yana-ai chat's Ollama provider (confirmed live via a real ollama_chat test against qwen2.5-coder:14b) is pure conversation only by design -- no file read, no repo visibility (src/chat/mod.rs's module doc explains why: nothing executes, so there's nothing for Yana AI's hook system to guard). He wants it to actually read the repo, Claude-Code-like -- chose this (extend yana-ai chat directly) over the alternative (point Cursor's agent mode at Ollama and reuse the existing core/adapters/cursor/ hook, whose Ollama-agent support couldn't be confirmed from Cursor's docs). Per this repo's own D7/ADS v1 rule (Specification-first Development, established by anh Tam himself this session), this is not something to silently code -- it's a real scope-expansion question for Program J (Universal Capability Runtime), whose Scope section currently names exactly 4 AI-tool clients (Claude/Cursor/Gemini/Codex) sourced from VISION-2.4.md's roadmap. Grepped VISION-2.4.md directly: no mention of yana-ai chat or a local-model client anywhere in the original 30- capability roadmap. Adding it would be real scope growth (M=5, not 4), not filling in content that was already implied -- different in kind from how the other 3/4 Open Questions got answered this session (pure re-reading of existing source docs, no new scope). Recorded as a new "Input bổ sung" section with a second Open Question (does this belong in Program J's scope or is it a separate Program/ Program D sub-goal) -- explicitly not decided by this agent, flagged for anh Tam. Also recorded upfront, before any Architecture discussion: this is a real security-posture change, not a small one -- yana-ai chat's current zero-tool-calling design is exactly why it sits outside the hook system's reach; giving it real file/exec access means it must start complying with the same guard rails every other agentic surface in this repo already does (04-sandbox-isolation-law.md, agent-excessive-agency-law.md, agent-tool-poisoning-guard.md, execution-environment.md's banned runtime functions) -- a weaker local model doesn't mean weaker consequences from what it's allowed to run. Docs-only, no code touched -- matches the D7 gate (Specification phase only until anh Tam resolves the two open questions). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
anh Tam's direct decision: "program J đi, gộp vào cho gọn" -- confirms yana-ai chat + local Ollama belongs inside Program J's scope rather than a separate Program, accepting the real scope expansion from M=4 (the roadmap-named Claude/Cursor/Gemini/Codex) to M=5. Updated: Scope section records the decision with a note that this 5th client is qualitatively different from the other 4 (a Yana AI-owned binary, not an external editor/CLI needing a translator script) -- flagged as a preliminary observation, not an architecture decision, since Phase 3 for the whole Program is still blocked on the earlier, still-unresolved question (MCP Server replacing vs. extending the translator-per-engine pattern). Open Questions: the yana-ai-chat scope question is marked answered; the whitelist-relationship question from the original roadmap remains the one real open item. Capability List's AI Adapter Layer row gets a cross-reference note rather than a duplicate new row, since this is a new client for an existing capability, not a new capability itself. README.md's Program table synced to match. Still not touching Architecture/Modules/Interfaces/code -- Phase 3 stays blocked until the MCP-Server-vs-translator-pattern question is resolved, per this repo's own D7/ADS v1 gate. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…aces translator pattern anh Tam's decision via AskUserQuestion, choosing between two presented options: MCP Server fully replaces the existing translator-per-engine pattern (core/adapters/cursor/before-shell-execution.js and future translators), rather than the lower-risk incremental option (MCP added as a discovery-only layer, translator kept for real-time hook enforcement) that was presented as the recommendation. Recorded the risk that was surfaced before the decision, not to contest it -- it's anh Tam's call, not something this agent infers -- but so it isn't lost: the current translator-per-engine path is proven, live security enforcement (guard-destructive.sh via Cursor); full replacement means that enforcement path needs to be rewritten and re-validated through MCP, which is inherently request/response and needs to be confirmed suitable for a PreToolUse hook's fast-block-or-fail requirement before implementation, not assumed. Both architecture questions that were blocking Phase 3 (this one, and the yana-ai-chat scope question resolved in commit 252da15) are now answered -- Phase 3 Architecture is unblocked for the whole Program. Docs-only, no code -- Phase 3 itself is diagrams/design per ADS v1, still not an implementation gate. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…kills, never actually existed Found while working through Program J's last Open Question: agent-tool- poisoning-guard.md, owasp-llm-top10/SKILL.md, agent-attack-surface/ SKILL.md, and deusdata--codebase-memory-mcp/SKILL.md all reference core/config/mcp-whitelist.json as if it already existed. Confirmed via `find`/`grep` that it never did -- the same "rule describes unbuilt infrastructure" pattern already fixed multiple times this session for 50-financial-deadman-switch-law.md, 54-bft-consensus-law.md, 56-circuit-breaker-law.md, and 62-sovereign-overlord-gate-law.md, and for the yana-router reference inside 9router-gateway/SKILL.md. anh Tam's direct instruction on hearing this: "không có thì tạo" (if it doesn't exist, create it). Created following the exact schema agent-tool-poisoning-guard.md already documents (policy/unknown_server_action/approved_mcp_servers), not inventing new structure. Seeded with one real, grounded entry -- ollama, confirmed live and in actual use this session (Program J's local-model- client work) -- rather than a placeholder list. Explicitly disclosed, not silently implied: no hook or script currently reads this file (grepped core/gates/sovereign-interceptor.js and core/hooks/*.sh, found no reference). The file now exists and matches its documented schema, but wiring an actual enforcement point is separate work, tracked in PROGRAM-J-SKELETON.md's Open Questions section as unresolved, not claimed done here. Also updates PROGRAM-J-SKELETON.md and README.md: Program J's Open Question 1 is now answered (the file's absence, not a real "extend vs build" choice, was the actual blocker), bringing Program J's Open Question count to 0. Phase 3 Architecture is unblocked but not yet started -- flagged as a stopping point for this session given its length, not started speculatively. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nded in real code
Per ADS v1's own Phase 3 definition ("ve kien truc, so do luong... khong
code"), drafted two flow diagrams for the MCP-Server-replaces-translator
decision from commit f6efc81:
1. Real-time hook enforcement (the security-critical path) -- traced
through src/guard/mod.rs directly before drawing anything. Found
check_command(command: &str) -> Option<&'static str> (line 691) is
already a pure function with no I/O, and its own comment says it was
extracted specifically so it "can be called once per MCP candidate" --
the MCP integration point already exists, unused. Also found the real
blocker: dispatch() (line 99) calls std::process::exit() directly,
fine for one-shot CLI use but fatal if called as-is from a long-running
MCP server process -- the correct integration point is check_command()
itself (needs a pub bump), not dispatch()/cmd_destructive(). Recorded
as a concrete Phase 9 Implementation Plan dependency, not glossed over.
2. Capability discovery (the genuinely new thing MCP adds beyond what the
translator pattern could do) -- tools/list against a runtime-read
registry instead of a hardcoded per-engine list.
Also recorded, as a flagged assumption needing anh Tam's confirmation
rather than a silent decision: Claude Code's own native PreToolUse/
PostToolUse hooks (.claude/settings.json, calling core/hooks/*.sh
directly) are a different mechanism from the translator-per-engine
pattern (Cursor's before-shell-execution.js and friends) and are assumed
OUT of this replacement's scope -- Claude Code was never using a
translator to begin with.
Modules table and README.md's Program table synced. Phase 4 (Workflow)
and Interfaces (message schema) intentionally left as TODO -- Phase 3 is
scoped to flow diagrams only per ADS v1, not full interface contracts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…kening enforcement anh Tam's answer to the Claude Code scope question: "neu chuyen duoc thi cu, khong thi neu van ho tro thi dung nhu cu la duoc" (convert if feasible, otherwise keep using it as-is). Worked through the actual feasibility question rather than assuming an answer either way, because it's a real safety question, not just a technical one: Claude Code's PreToolUse hook is a mandatory interception mechanism (runs before every Bash/Write/Edit call regardless of what the model wants), while an MCP tool is something the model voluntarily chooses to call. Naively "moving hook enforcement to MCP" would mean turning a mandatory check into a tool the model could be prompt-injected into skipping -- a real security regression, not a neutral refactor. The reconciliation: don't touch the interception mechanism itself (.claude/settings.json's PreToolUse stays exactly as mandatory as it is today, the model has no visibility into or control over it) -- only change what the hook script does internally, from calling guard-destructive.sh directly to calling the new MCP Server (the same thin-bridge pattern core/adapters/cursor/before-shell-execution.js already uses, just with Claude Code's hook runner as the caller instead of Cursor). This unifies the judgment source across all 5 MCP clients without weakening what makes the Claude Code path safe today. Conclusion: Claude Code is now in scope for the MCP replacement, no exception. Updated the Ranh gioi scope section, Modules table, and the Status header/README.md table to match -- no more "assumption pending confirmation" language since anh Tam settled it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… not invented schema Fetched the actual MCP specification (modelcontextprotocol.io/ specification/2025-06-18/server/tools) before writing anything -- JSON-RPC 2.0, tools/list and tools/call message shapes taken verbatim from the published spec, not guessed from training-data recall (this session's trust-score flag requires double evidence for claims; a wrong schema here would be worse than no schema). Interfaces: defines the check_command tool (name/description/inputSchema/ outputSchema) and concrete tools/call request/response examples for both allow and deny outcomes. The one thing flagged as load-bearing, not a footnote: MCP's spec itself splits errors into two channels (JSON-RPC Protocol Errors vs. isError:true Tool Execution Errors) that guard- destructive.sh/check_command() currently has no equivalent of -- every unverifiable case there is just "deny," never a third "error, not sure" state. Both MCP error channels MUST map to deny on the client side, no exception, or the MCP transition would silently reintroduce a fail-open path the current design goes out of its way to avoid (see the fail-closed philosophy documented in core/adapters/cursor/before-shell-execution.js, read directly in the Phase 3 commit). Phase 4 Workflow: expands Phase 3's flow diagram into a full pipeline with startup, persistent connection (not per-request spawn, unlike the current spawnSync-per-call translator), all 4 result branches including the two failure paths, and audit logging (routed through the existing audit-hardening-policy.md chain, not a new parallel log per MCP's own "log tool usage for audit purposes" requirement). Three items explicitly left undecided for Phase 9 Implementation Plan or anh Tam's call: the MCP server's CLI subcommand name, the client-side timeout value (the current 15s was tuned for spawning bash; in-process calls should be much faster but that needs Phase 12 Benchmark data, not a guess), and how the server process gets started in a working session. Status header and README.md's table synced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Found while honestly scoring Program J against ADS v1's Readiness Matrix (Phase 5): none of today's Program J decisions (MCP replaces translator, Claude Code in scope without weakening enforcement, mcp-whitelist.json created) had been written to L1 atomic memory, despite memory-persistence-law.md's explicit requirement that architecture decisions affecting future work MUST be persisted before relying on them in a future session -- conversational context is ephemeral, L1 is not. add-fact.sh is interactive (prompts per field), not scriptable in this session -- followed the same manual-write pattern already established by fact-20260710-220852 and fact-20260710-220901 (matching schema, ID convention, confidence: unverified per fact-confidence-rule.md's "manual promotion only" constraint) rather than inventing a new convention. Recorded only the single highest-impact decision (MCP replaces translator-per-engine, including Claude Code, without weakening its enforcement mechanism) as one atomic fact -- not every sub-decision from today's session, per L1's own "atomic" naming. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ed from implementation Honest, evidence-based scoring against all 10 Readiness Matrix categories (ADS-v1.md only names the 10 categories, doesn't define a rubric per category -- flagged the two genuinely ambiguous ones, Notebook and Context, as "cach hieu chua chac" rather than confidently scoring something undefined): Ready (5): Repository, Knowledge, Runtime, Governance, Security -- each with concrete evidence, not just asserted. Ambiguous interpretation (2, counted at half weight): Notebook, Context. Not ready (2): Benchmark (no numbers anywhere, not even a rough estimate -- the timeout question from Phase 4's Workflow section is exactly this gap), Cost (never addressed in Phase 0-4 despite being thematically connected to this session's earlier "reduce Claude quota" discussion -- the two were never actually connected into real analysis). Tally: 5 + 2*0.5 + 0 = 6/10 = 60%, below ADS v1's own 80% bar -- "Readiness < 80% -> Block, chi duoc Research/ADR/Design, khong code." This is the expected, correct outcome at this stage (Phase 0-4 just finished, Phase 6 ADR / Phase 7 Research / Phase 8 Design Review haven't happened yet) -- not a failure, the gate doing its job. Rewrote the Status header to compress the accumulated per-decision history from today's session into one current-state summary, since it had grown into a long chronological log that the body sections (Scope, Architecture, Interfaces, Workflow, Readiness Matrix) already cover in full -- the detail isn't lost, just no longer duplicated at the top. README.md's Program table synced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…l-model delegation failed twice Benchmark: measured the CURRENT translator pattern directly (5 runs, node + spawnSync + core/adapters/cursor/before-shell-execution.js against a benign `ls -la`) rather than leaving the Readiness gap as an unmeasured guess: 178-310ms per call, ~220ms average. Compared against already-measured numbers from BENCHMARK.md (2026-07-23): Rust binary startup ~22-24ms, yana-rt guard token-budget dispatch (in-process, but carries ADR-008 lock overhead) ~65ms. check_command() has neither process-spawn nor lock overhead, so a persistent in-process MCP server should beat the current 220ms baseline by at least an order of magnitude -- stated as a directional estimate, not a real number, since the MCP server doesn't exist yet to measure. Cost: tried delegating a first-draft cost-factor brainstorm to two local Ollama models before writing it myself, per this session's local-model- delegation practice. Both failed -- qwen2.5-coder:14b gave an off-topic, truncated answer; huihui_ai/qwen3.5-abliterated:9b ran past 120s (backgrounded) and came back with an empty, invalid-JSON result. Wrote the analysis directly instead of forcing a bad delegation result into the doc. Flagged the most important point in it: the highest real cost here isn't money, it's the consequence of getting the MCP-error-to-deny mapping wrong (documented in Interfaces) -- a safety regression, not a budget line item, so this category needs engineering review more than financial estimation. Readiness Matrix score updated 60% -> 70% (Benchmark and Cost move from Not-ready to Partial). Still below ADS v1's 80% bar, still correctly blocked from Phase 10 Implementation -- recorded plainly that the honest path to 80% is going through Phase 6-8, not padding the score. Status header and README.md's table synced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…cision Phase 6 of ADS v1 for Program J. Follows ADS v1's own specified ADR template (Decision/Problem/Alternatives/Tradeoffs/Reason/Consequence), not the freeform Status/Context/Decision shape ADR-006 through ADR-009 used, since ADS v1 (established 2026-07-24) is now this repo's standing process for Program-scoped decisions. Distills PROGRAM-J-SKELETON.md's Phase 0-5 content into the formal ADR shape -- no new decisions introduced, every claim traces back to that doc, the real code read directly during this session (core/adapters/ cursor/before-shell-execution.js, src/guard/mod.rs), or the L1 fact already recorded (fact-20260724-233122). Records both alternatives that were actually on the table (the lower-risk incremental option this agent recommended via AskUserQuestion, and the full-replacement option anh Tam chose), not just the winner, per the Alternatives/Tradeoffs sections ADS v1's template requires. States plainly in its own Status section that writing this ADR does not clear Program J for Phase 10 Implementation -- Readiness is 70%, below ADS v1's 80% bar, and Phase 7 (Research) / Phase 8 (Design Review) still need to happen first. An ADR records a decision; it isn't a readiness gate by itself. Updated PROGRAM-J-SKELETON.md's ADR section (was a TODO placeholder) and its Status header, plus README.md's Program table, to point at the new file. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-config install path
Fetched real sources before writing anything (github.com/modelcontextprotocol/
rust-sdk, code.claude.com/docs/en/mcp), per ADS v1 Phase 7's own scope
("Khong viet code. Nguon: GitHub... Documentation... MCP...").
Three findings, each with a direct Phase 9 implication:
1. rmcp is the official Anthropic-maintained Rust MCP SDK
(cargo add rmcp --features server), actively developed, macro-based
tool definitions, supports both stdio and Streamable HTTP in
long-running multi-client mode. Means Phase 9 doesn't need to hand-roll
JSON-RPC -- lower risk of getting the error-mapping requirement
(Interfaces, Phase 1) wrong through a homegrown protocol
implementation.
2. Claude Code's local MCP server connection uses CLAUDE_PROJECT_DIR in
the spawned server's environment -- the exact same convention already
used by core/adapters/cursor/before-shell-execution.js (read directly
in the Phase 3 commit). No new convention needed.
3. The one with real install-experience impact: Claude Code plugins can
declare mcpServers directly in plugin.json using ${CLAUDE_PLUGIN_ROOT},
auto-connecting at session startup with zero manual .mcp.json setup.
Yana AI already ships as a Claude Code plugin (plugin.json,
marketplace.json exist) -- this means the MCP Server addition doesn't
need a new install step beyond an entry in plugin.json, matching the
existing "npx yana-ai-install wires the hooks (60 seconds)" philosophy
README.md already advertises.
First drafted a condensed summary via qwen2.5-coder:14b (local Ollama) --
this time asked it to reformat/condense already-fetched real source
material rather than reason from scratch (the task shape that failed
twice earlier today for Cost analysis). Result was accurate and usable,
unlike those two attempts -- used as the starting structure, then
expanded with the full detail and Program-J-specific implications above
before this commit.
Explicitly flagged as NOT yet researched: how Cursor, Codex, and Gemini
(3 of Program J's 5 clients) connect to local MCP servers -- only Claude
Code's mechanism is confirmed. Left as an open Phase 8 dependency, not
assumed to work the same way.
Status header rewritten again (was growing into a long chronological
log) -- README.md's table synced.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…endency caution Scored against ADS v1's own 9-item checklist (Architecture/Naming/ Dependency/Duplicate/Security/Maintainability/Performance/Scalability/ Governance), each with cited evidence rather than a rubber stamp. Dependency: fetched crates.io's real API data for rmcp before writing anything -- 17.1M total downloads, Apache-2.0 (matches Yana AI's own license), last published 2026-07-23 (yesterday), easily clears dependency-vetting-law.md's 8-criteria bar. Found one real thing worth flagging: crates.io's max_version is 3.0.0-beta.1, but 2.2.0 is the actual latest stable release -- Phase 9 should pin the stable line for a dependency sitting on a security-critical path, not the beta. Scalability: read check_command()'s signature directly rather than guessing -- `fn check_command(command: &str) -> Option<&'static str>` has no shared mutable state, no locks, no I/O, so it's safe to call concurrently from multiple client connections without added synchronization. A real finding from the code, not an assumption. Naming: genuinely unresolved -- the MCP server's CLI subcommand name was never decided (Workflow section already flagged this placeholder). Left as a real gap for Phase 9, not silently picked here. Zero items scored Fail. Explicitly noted: Design Review passing does not raise the Readiness Matrix score by itself -- they're different gates. Readiness stays at 70%, still below ADS v1's 80% implementation bar. Also re-flagged, still unresolved from Phase 7: how Cursor/Codex/Gemini (3 of Program J's 5 clients) connect to local MCP servers was never researched, only Claude Code's mechanism was. Left as an open gap rather than assumed identical. Status header and README.md's table synced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…name proposed from precedent Read src/main.rs's existing Commands enum before proposing a name for the new MCP server subcommand, rather than inventing one -- found Chat (line 162) is the one existing top-level command with flat flags and no nested action enum, unlike the Task/Guard/Bus-style noun+action pattern every other command uses. Proposed `yana-rt mcp` on that precedent, since the MCP server is "run as a mode" like chat, not a CRUD resource like task/ guard. Treated this as a naming/housekeeping call following existing convention, not an architecture decision needing anh Tam's sign-off -- flagged the reasoning so it's not an unlabeled guess either. Five stages per ADS v1's own Phase 9 template (Research -> Prototype -> Alpha -> Beta -> Stable): - Research: the still-open Cursor/Codex/Gemini MCP connection gap from Phase 7/8, plus a check_command()-to-rmcp spike with no client swapped yet. - Prototype: yana-rt mcp exposing exactly one tool, tested against a real MCP client, both Interfaces error-mapping branches (Protocol Error, isError:true) verified to resolve to deny -- stated as a hard gate before Alpha, not optional. - Alpha: Cursor only (it already has a translator to compare against), running in parallel with the old path, real Benchmark data gathered against the 220ms baseline before touching anything else. - Beta: remaining clients, including wiring actual enforcement for core/config/mcp-whitelist.json (created earlier today, still has no reader -- this is where that gap gets closed, not left open forever). - Stable: all 5 clients on MCP; the guard-destructive.sh/before-shell- execution.js deprecate-or-keep question (raised, not answered, in Phase 8's Maintainability row) gets decided here, not earlier. Explicit boundary stated: this plan stages the work, it does not itself authorize Phase 10 code -- Readiness is still 70%, still below ADS v1's 80% bar. Status header condensed again and README.md's table synced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…config confirmed Fetched real docs for each of the 3 remaining clients separately (per this session's own established discipline: "khong gia dinh giong nhau"), not assumed identical to Claude Code: - Cursor: .cursor/mcp.json, same mcpServers JSON schema as Claude Code (cursor.com/docs/context/mcp) - Gemini CLI: .gemini/settings.json, same mcpServers JSON schema again (github.com/google-gemini/gemini-cli docs) - Codex CLI: .codex/config.toml, genuinely different -- TOML, not JSON, [mcp_servers.<name>] table syntax (learn.chatgpt.com/docs/extend/mcp) Net finding for Phase 9: 3 of 4 clients (Cursor, Gemini, and Claude Code when not using the plugin.json auto-connect path) share one identical JSON schema -- an install script only needs one TOML branch (Codex) as the real special case, not four separate formats. This repo already has untracked .cursor/, .codex/, .gemini/ directories from earlier session work -- the right locations for these config files once Phase 10 starts. Marks Roadmap's Research stage as done; the remaining Research-stage item (the rmcp + check_command spike) is unchanged, tracked separately. Status header and README.md's table updated to note anh Tam authorized proceeding past the Readiness gate for a small Prototype spike next. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…atency data anh Tam authorized proceeding past the 70% Readiness gate for a small Research/Prototype spike, per ADS v1's own exception path for a human override. Not Phase 10 implementation -- an isolated, disposable prototype validating the architecture before committing to it for real. New: src/mcp.rs, a minimal MCP server (rmcp 2.2.0, pinned to the stable line per Phase 8's own finding, not crates.io's 3.0.0-beta.1 max_version) exposing exactly one tool, check_command, over stdio. Calls crate::guard::check_command() directly, in-process -- the same pure judgment function core/hooks/guard-destructive.sh mirrors, unchanged. src/guard/mod.rs: check_command() becomes pub (was module-private) so src/mcp.rs can call it without going through dispatch()/cmd_destructive() (both route to std::process::exit(), fatal if called from a long-running server process). Zero logic changes -- confirmed by diff, verified in review. src/main.rs + Cargo.toml: new Commands::Mcp and rmcp/tokio dependencies, all gated behind a new `mcp` Cargo feature, separate from default `cli`. This is the crate's first tokio/async dependency (confirmed via docs.rs before adding) -- kept isolated so the spike doesn't change the default build's footprint. Verified at the binary level (strings scan), not just by reading #[cfg] attributes: tokio/rmcp symbols are absent from a default-feature build. Live end-to-end test this session (real Python MCP client, full initialize/tools-list/tools-call handshake, not simulated): benign command -> allow, `rm -rf` -> deny with the real reason text, and the exact `python3 -c` inline-script bypass fixed earlier this session -> deny with the identical reason the bash guard would give -- proving check_command() is genuinely reused, not reimplemented. Measured latency: p50 0.134ms, avg 0.154ms per call (50 runs, post-warmup) versus the previously-measured 178-310ms translator baseline -- roughly 1400-1600x faster once the server is already running. cargo test --features cli (mcp NOT enabled) still 183/183 + 63/63, single-threaded, confirming zero regression to the existing default build. One pre-existing test flake found and left alone, out of scope: guard::blast_paths::tests::absolute_path_under_repo_root_is_protected races on a shared YANA_REPO_ROOT env var under parallel test execution (passes reliably in isolation) -- not touched by this change, not introduced by it. Per 54-bft-consensus-law.md's spirit (src/guard/mod.rs is core-lock-pinned security-critical code, same category as core/hooks/** even though the law's literal trigger table doesn't name src/), dispatched both security-team/security-auditor.md and code-auditor.md before this commit. No Safety-severity findings. Three Style/Performance-tier notes from code-auditor, explicitly scoped to "fix before Phase 10, not now": the tool_router field is currently dead code (rmcp's default #[tool_handler] expansion calls the associated fn, not the cached instance -- confirmed by reading rmcp-macros' generated code, not assumed), the `mcp` feature doesn't declare its real dependency on `cli` (works today only because main.rs is itself gated on `cli`), and tokio's "full" feature set is wider than a stdio-only server needs. Applied the one cheap fix (security-auditor's and code-auditor's own wording note on the check_command doc comment: "both call process::exit()" corrected to "both route to process::exit()", since only dispatch() calls it directly). core/config/core-lock.json regenerated per 67-core-integrity-lock-law.md's protocol (diff reviewed -- only src/guard/mod.rs's hash changed -- regenerated via update-core-lock.sh, never hand-edited). Readiness Matrix impact (docs/programs/PROGRAM-J-SKELETON.md): Benchmark row moves from Partial to Ready on this real data, taking the overall score from 70% to 85% -- above ADS v1's 80% bar. Stated plainly in the doc: this is the result of one small spike, not a completed Phase 10, and whether to treat Program J as formally past the Readiness gate is anh Tam's call to make, not this agent's to declare. Also closed the Research-stage gap flagged in the previous two commits: fetched real docs for Cursor (.cursor/mcp.json), Gemini CLI (.gemini/settings.json), and Codex CLI (.codex/config.toml) separately, per this session's own discipline of not assuming they match Claude Code's mechanism. Finding: 3 of 4 clients share one identical mcpServers JSON schema; only Codex differs (TOML). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Still root-causing the E403 on the actual npm publish PUT after confirming (2026-07-24/25) that OIDC token exchange and provenance signing both succeed -- environment/permissions/id-token are all verified present in this file, branch is confirmed main (workflow_dispatch's own if: condition doesn't gate on ref at all), so the failure is somewhere in npm-side Trusted Publisher matching, not this workflow's config as written. Adds one diagnostic step printing GITHUB_REPOSITORY/REF/WORKFLOW/JOB/ EVENT_NAME/ACTOR right before the publish step, to hand-compare against npmjs.com's Trusted Publisher entry for anything logs don't otherwise surface (e.g. GITHUB_WORKFLOW is the workflow's `name:` field, not its filename -- worth confirming npm expects the filename, not the display name, since this repo's workflow name is "Publish to npm + PyPI + crates.io", not "publish.yml"). Explicitly temporary -- remove once the 403 is root-caused. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
src/yana_ai/rt.py resolved the yana-rt binary via shutil.which with no self-check, the same bug class fixed in scripts/yana-rt-wrapper.js on 2026-07-08/09 after a real incident (self-invocation through PATH, 100% CPU, 116C, forced shutdown) -- but that fix was never ported to this file, so every PyPI release to date carries the same unpatched recursion risk. Adds the same guard pattern as the JS fix: a hard re-entry env var checked before resolving any candidate, plus a realpath self-check applied to every candidate including the explicit override, so the wrapper's own path pasted into the override cannot re-arm the recursion either. Verified with 5 direct logic tests against the new helper functions (self-reference rejection, nonexistent path, empty input, real executable, exit code 1 on re-entry) -- all pass. README.md: corrected an inaccurate warning that claimed pip was unaffected; only cargo install yana-rt is structurally immune (no wrapper to recurse through). npm and PyPI both currently carry the bug in their latest published release. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports the last four English-only README updates into the three translations: the yana-rt self-recursion warning (npm/PyPI affected, cargo unaffected), the demo GIF, the debunked-1256x benchmark rewrite, and the new yana-ai chat subcommand. Also corrects a pre-existing 57-vs-58 hooks mismatch in the safety-architecture tree diagram that predates this change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds `yana-ai skill-quality show|promote`, a per-skill outcome ledger built entirely from two signals Yana AI already produces: which skill/agent a task's session invoked (audit-chain.log) and eval judge's PASS/FAIL verdict. No new hook, no new LLM call, no new dependency. Idea borrowed from HKUDS/OpenSpace's quality-from-real-tasks and provisional/trusted promotion model, reimplemented from scratch with no dependency on that project or its cloud. Promotion always requires an explicit human command; demotion on a fresh FAIL streak is automatic, since revoking standing is safe to run unattended in a way granting it isn't. Incorporates a follow-up round from external code review: narrows skill/task attribution to the task's own work window instead of an unbounded "now" (mitigates, doesn't fully close, cross-task attribution — full fix needs task-id tagging in audit-log.sh itself, out of scope here), and switches timestamp comparison from raw string ordering to parsed RFC3339 instants. 262 tests pass (199 unit + 63 integration), 0 regressions. Verified end-to-end against a real task, a real Skill tool-call entry in audit-chain.log, and a local Ollama judge call. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
npm publishing has been blocked for weeks by an issue confirmed to be account-level, not package- or config-specific: the same 403 reproduces across multiple packages under the same npm account, through both CI's OIDC trusted publishing and a fresh manual browser login, while npm's own `access list` reports read-write on every one of them. Reported to npm support repeatedly with no resolution. Rather than keep chasing an unresponsive support channel, all four READMEs now say so plainly and point new installs at `pip install yana-ai` or `cargo install yana-rt` for the current version. Also updates the existing yana-rt self-recursion known-issue callout, which referenced this same npm block as "tracked, in progress" — no longer accurate now that active pursuit has stopped. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-skills # Conflicts: # README.md # src/main.rs
switch-engine.sh supported 15 coding-agent tools, most of them advisory-only Aider wrappers for cloud providers nobody was using. Narrows to the four anh actually runs: Claude Code, Cursor, Codex, Antigravity. - Removed the copilot/aider/kimi/gemini/qwen/deepseek/openrouter/ continue/opencode/zed/windsurf/kiro cases from switch-engine.sh (core/ and its .claude/ mirror, now byte-identical -- the mirror had also drifted independently before this change and is now fully resynced). - Deleted the now-unused adapter source files and kimi-hook-adapter.sh (both copies), plus stale generated artifacts for dropped engines (GEMINI.md, OPENCODE.md, .github/copilot-instructions.md, .windsurf/, .kiro/). - Updated adapters/README.md, README.md (+vi/ko/zh), cli-reference.md, and docs/ARCHITECTURE.md (+.claude mirror) to describe only the 4 kept engines. Left CHANGELOG.md, ROADMAP.md, and the docs/technical/ design docs alone -- those are point-in-time historical records, not live documentation. Dispatched security-auditor + code-auditor per 54-bft-consensus-law for the MANIFEST.json/core-lock changes. No Safety-severity findings; fixed the Correctness ones they raised: a second scripts_count field in MANIFEST.json, a missed .claude/scripts/kimi-hook-adapter.sh mirror copy, and a stale self-reference to the removed `gemini` case inside adapters/antigravity.md. core-lock re-pinned after review (260 files, 0 drift). yana chat's own provider list (Anthropic/OpenAI/Gemini/Groq/ DeepSeek/OpenRouter/9Router/Ollama/Kimi) is untouched -- a separate system anh confirmed should stay as-is. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Product version axis only (package.json/MANIFEST.json/.claude-plugin marketplace.json+plugin.json/package-lock.json); Cargo.toml (yana-rt, already 1.3.3) and pyproject.toml (PyPI, 0.42.3) are unchanged this cycle per VERSIONING.md's independent-axis scheme. Two rounds of security-auditor + code-auditor review (54-bft-consensus- law) on the MANIFEST.json/version-file changes caught real issues, fixed before this commit: - bin/yana's subcommand dispatch allow-list was missing two already- shipped yana-rt subcommands (observability, skill-quality) -- both existed in main.rs but fell through to "Unknown command" when invoked via yana-ai. Fixed and independently re-verified by a real exec() of bin/yana per 71-entry-point-verify-law, not just a diff re-read. - A scripts-count field in .claude-plugin/plugin.json (114, stale since the earlier kimi-hook-adapter.sh deletion) and package.json's description (57 hooks/2,013 skills, several releases stale). - marketplace.json's version had lagged one patch behind package.json/ MANIFEST.json/plugin.json at 0.43.1 -- all four now read 1.0.0. No Safety-severity findings from either review round. See CHANGELOG.md for the full v1.0.0 entry, including an explicit, unresolved-issues section: npm publish remains frozen at v0.43.1 (account-level block, not fixed by this release) and the desktop app's auto-update pipeline is broken (tools/yana-desktop/package.json never bumped past 0.1.0). Verification: core/scripts/drift-check.sh clean, validate-counts.sh all 6 counts OK, cargo test 262/262 (199 unit + 63 integration), verify-core-lock.sh 260 files 0 drift. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rtk-ai/rtk (Apache-2.0, single Rust binary) filters/compresses bash output before an agent reads it -- up to 90% smaller on common dev commands (git, test runners, linters, cloud CLIs). Documented as a recommended companion tool, not vendored or added as a dependency: it's an external CLI proxy, not IP worth reimplementing (unlike the OpenSpace skill-quality case). Kept deliberately light -- docs/reference + one README section only, no core/rules or MANIFEST.json touch, so this doesn't trigger 54-bft-consensus-law's dual-reviewer ceremony for what is a documentation-only addition. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
core/hooks/rtk-bridge.sh (mirrored .claude/hooks/ + .codex/hooks/ on disk, not committed here -- .codex/ itself is separate pre-existing uncommitted work outside this task's scope): a PreToolUse Bash hook bridging to the external rtk CLI (github.com/rtk-ai/rtk, Apache-2.0), which compresses command output before an agent reads it. Not vendored, not wired into .claude/settings.json's live hook chain -- inert unless a user sets YANA_RTK_BRIDGE=1 and has rtk installed. Two rounds of security-auditor + code-auditor review (54-bft-consensus- law) on this new hook found and fixed real issues before commit: - Safety: the exit-0 path granted an explicit permissionDecision:allow based purely on rtk's own self-reported exit code, with no check that the rewrite preserved the original command. Removed -- this hook now only ever supplies updatedInput; Yana AI's own destructive-command guards and the harness's normal permission flow decide allow/deny/ask on whatever command actually runs, same as any command it never saw. - Safety: rtk was resolved via bare PATH lookup. Added YANA_RTK_BIN to let a user pin an absolute path instead (full binary-hash pinning is out of scope for a single opt-in bridge -- documented as a deliberate tradeoff, not an oversight). - Safety: added a verbatim-substring invariant check before trusting any rewrite -- an unrelated or malicious rewrite falls back to the untouched original command rather than being trusted blindly. - Correctness: no timeout on the rtk call -- a hang would hang the whole tool call. Fixed, then hit this repo's own documented macOS landmine (no timeout/gtimeout by default) on the first attempt -- now resolves timeout/gtimeout with the same degrade-gracefully pattern already used in hook-timeout-guard.sh. - Correctness: no test proved the mocked rtk actually received the literal command text (a word-splitting regression could have passed all prior assertions). Added. core/tests/hooks/test-rtk-bridge.sh: 25 assertions, including the malformed-JSON/empty-stdin cases fuzz-testing-constraints.md requires and a dedicated case for the invariant-rejection fallback. docs/reference/token-optimization.md: documents what rtk is, install, how to wire the bridge hook in, and states the data-exposure property plainly (command text transits an unaudited third-party process once enabled) per 68-principal-confidentiality-law.md. Also fixes stale hook/test counts this addition caused: MANIFEST.json (hooks 61->62, tests 10->11), plugin.json (hooks 61->62), marketplace/ SKILL.md/docs html "61 hooks" mentions -> 62. core-lock.json regenerated post-review (261 files pinned). drift-check.sh clean, run-hook-tests.sh 260/260. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
anh confirmed explicitly (AskUserQuestion) after installing rtk 0.43.0 via brew and verifying end-to-end: a raw git status command becomes "rtk git status" after the rewrite, exit 0, valid updatedInput JSON, no permissionDecision (per the security fixes already committed in e062f2a). This is the step security-auditor's review explicitly gated on: "before this is ever wired into .claude settings.json". All 5 of that reviewer's prerequisites were already addressed in e062f2a before this commit. YANA_RTK_BRIDGE=1 is now baked into the hook invocation itself (matching the existing YANA_GUARDED_HOOK convention), so it runs automatically without anh needing to export an env var per session. run-hook-tests.sh 260 of 260 passing, core-lock unaffected (settings json is not in the pinned set), end-to-end simulation through hook-timeout-guard.sh confirmed working with the real rtk binary, not just mocks. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wired live earlier this session with anh's explicit confirmation; unwired the same session after a concrete failure was observed, not a theoretical one. With the bridge active, an agent's own verification command (git log --oneline piped to wc -l) silently returned 50 instead of the true 1,478 commits -- rtk's compact git log format truncates rather than counting everything. rtk's own "never emits more tokens than the raw command" guard is a token-count promise, not a completeness promise. This is a real risk for any agent (this one included) that relies on exact tool output for evidence-based claims per verification.md's Iron Law -- a silently truncated git log could have produced a wrong fact reported as verified. Caught only by chance, cross-checking against the GitHub API for an unrelated reason. core/hooks/rtk-bridge.sh (mirrored .claude/ + .codex/) stays available as opt-in only, matching its original design -- YANA_RTK_BRIDGE=1 plus a manual settings.json edit, not auto-wired. Header comment and docs/reference/token-optimization.md both now document this incident explicitly as a known limitation of enabling it broadly, not just the general "compacts output" framing from before. run-hook-tests.sh 260/260, core-lock regenerated (comment-only hook change), drift-check.sh clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
main independently restructured README.md (and its locale translations) while this branch was diverging with its own v1.0.0/harness-cut/rtk work -- the yana-rt self-recursion CPU bug warning, demo GIF repositioning, and a rewritten safety-architecture section (Merkle audit chain, core-lock integrity, reviewed infrastructure writes, human gate) landed on main but not here. This caused a real merge conflict in README.ko.md/ README.vi.md/README.zh.md (PR #85), confirmed via git merge-tree preview before touching anything. Resolution: took main's newer structural content in each locale file as the base, then re-applied this branch's own newer facts on top -- v1.0.0 (from v0.43.2), 62 hooks/113 scripts (from 61/108), the 4-engine harness list (from the stale 12-engine one, including switch-engine.sh examples and the intro sentence naming all 10+ old engines), and added a translated "cutting your own token bill" section pointing at rtk (new content that doesn't exist on main in any language yet). Also fixed two stale counts in README.md itself, found while using it as the reference for what the locale files should say: the ASCII banner still said "61 hooks" and the file-tree comment still said "57 PreToolUse/PostToolUse/Stop hooks" -- both now 62, and the old 10-engine intro sentence (Windsurf/Kiro/OpenCode/Zed/Gemini/Copilot/ Aider) was never updated when harness support was cut to 4, despite the "4 harness adapters" bullet elsewhere already being correct. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-skills # Conflicts: # README.ko.md # README.vi.md # README.zh.md
Investigated PR #85 (already merged to main by the time this was checked, main's CI workflow currently red) at anh's request to check for errors. Found two distinct, real, pre-existing bugs -- neither introduced by this branch's own work, both newly exposed once the merge brought main and this branch's history together on one CI run. 1. bin/yana's dispatch case-statement was missing `mcp` -- the same bug class already fixed once this session for observability/skill-quality: a Rust subcommand exists in src/main.rs but bin/yana never routed to it, so `yana-ai mcp ...` fell through to "Unknown command" even though the underlying yana-rt binary implements it. CI's `yana-rt doctor dispatch . --json` self-check caught this (`"kind": "unreachable", "name": "mcp"`). Fixed by adding `mcp` to the same case-statement line as the other Rust-dispatched subcommands. Independently verified via a dedicated verify-agent dispatch per 71-entry-point-verify-law.md: red/green comparison (bash-level rejection before the fix, clap-level parsing after), sibling subcommands on the same line unaffected, and the exact CI check reproduced locally with `findings: []` after the fix. Note: `mcp` is gated behind a Cargo feature not compiled into the default binary (Program J spike, documented in Cargo.toml) -- this fix makes it reachable from the CLI, it does not make MCP functionality itself available without building with `--features mcp`. 2. .codex/ (agents + hooks mirror, 111 files) and core/tests/adapters/cursor/test-before-shell-execution.sh + core/adapters/cursor/before-shell-execution.js were never committed to this repo at all -- confirmed via `git log --all` returning nothing for either path. Yet core/scripts/verify-hook-mirrors.sh (already committed) hardcodes .codex/hooks as a mirror it expects to match core/hooks/ byte-for-byte, and core/tests/hooks/ run-hook-tests.sh (already committed) references the adapter test suite by exact path. On a fresh checkout (i.e. CI) both checks failed because the files they depend on simply weren't there -- masked locally only because these paths happened to exist untracked on-disk. Confirmed and committed after anh's explicit go-ahead: .codex/ verified byte-for-byte in sync with core/hooks/ via verify-hook-mirrors.sh before staging; the cursor adapter's own test suite (6 cases -- destructive-command denial forwarding guard-destructive.sh's real reason text, benign-command allow, malformed-JSON fail-closed, missing-guard fail-closed, guard-destructive.sh's own jq-missing fail-closed forwarded end-to-end, and a static no-reimplementation check) run and passing locally before commit. run-hook-tests.sh 260/260, drift-check.sh clean, core-lock unaffected (.codex/ and core/adapters/ aren't in its pinned scope). Not yet fixed, flagged separately: a real race condition in risk-scorer.sh/budget-sentinel.sh vs token-budget-guard.sh (concurrent writers to the same state file lose updates under real concurrency, caught by Hook Tests' own race-condition assertions) -- out of scope for this commit, reported to anh separately. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
yana | 0cb1f49 | Commit Preview URL Branch Preview URL |
Jul 27 2026, 05:00 AM |
|
Important Review skippedToo many files! This PR contains 114 files, which is 14 over the limit of 100. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (114)
You can disable this status message by setting the ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…-skills # Conflicts: # bin/yana
| # curl/wget piped directly to bash/sh/zsh — classic supply chain attack vector | ||
| if printf '%s' "$CMD" | grep -qE \ | ||
| '(curl|wget)\s+[^|]+\|\s*(bash|sh|zsh|fish|dash|ksh|python[23]?|node|ruby|perl)'; then | ||
| deny "Blocked [L4.5 Supply Chain]: pipe-to-shell detected ('curl ... | bash' or 'wget ... | sh'). This pattern executes untrusted remote code without review. Download the script first, inspect it, then run it. Rule: core/rules/44-supply-chain-vetting.md | Bypass: YANA_SUPPLY_OK=1" |
| if [[ -n "$CONFLICT" ]]; then | ||
| echo "[multi-run-lock] BLOCKED — $CONFLICT" | ||
| echo "File: $FILE_PATH đang trong scope của agent khác." | ||
| echo "Chờ agent đó xong hoặc chạy: rm $LOCK_FILE để reset." |
| || echo "$COMMAND" | grep -qiE '\bgit\b[^|;&]*\bpush\b[^|;&]*--force|\bgit\b[^|;&]*--force[^|;&]*\bpush\b' \ | ||
| || echo "$COMMAND" | grep -qiE '\bgit\b[^|;&]*\breset\b[^|;&]*--hard' \ | ||
| || echo "$COMMAND" | grep -qiE '\bgit\b[^|;&]*\bclean\b[^|;&]*(-[a-zA-Z]*f[a-zA-Z]*|--force)'; then | ||
| deny "Blocked: command invokes an interpreter (python/node/ruby/perl/bash/sh/zsh) with an inline script (-c/-e/--eval) whose content appears to contain a destructive pattern (rm -rf, DROP TABLE/TRUNCATE, git push --force, git reset --hard, or git clean -f). This guard cannot safely verify commands embedded inside interpreter scripts. Run the destructive operation directly (not wrapped in an inline script), or ask the human to confirm." |
| # at all, a bash builtin -- tracked separately, not silently claimed | ||
| # closed by this round.) | ||
| # 3. `git clean -f` was missing from the inline OR-list entirely (only | ||
| # rm-rf, SQL DROP/TRUNCATE, git push --force, git reset --hard were |
|
|
||
| # ── Destructive SQL operations ──────────────────────────────────────────────── | ||
| if echo "$COMMAND" | grep -qiE '\b(DROP\s+(TABLE|DATABASE|SCHEMA)|TRUNCATE\s+TABLE)\b'; then | ||
| deny "Blocked: destructive SQL (DROP TABLE / TRUNCATE) detected. Database migrations must be reversible. Use ALTER/soft-delete patterns and ask the human to confirm schema drops." |
|
|
||
| // Input Validation Tests | ||
| it.each([ | ||
| { email: '', password: 'valid123', error: 'Email is required' }, |
|
|
||
| await expect(userService.createUser({ | ||
| email: 'test@example.com', | ||
| password: 'password123' |
| // Act & Assert | ||
| await expect(userService.createUser({ | ||
| email: 'existing@example.com', | ||
| password: 'password123' |
| password: 'SecurePass123!', | ||
| name: 'Test User' | ||
| }; | ||
| const hashedPassword = 'hashedPassword123'; |
| // Arrange | ||
| const userData = { | ||
| email: 'test@example.com', | ||
| password: 'SecurePass123!', |
PR #86's self-audit CI job failed with 5 critical/8 high findings, all inside .codex/hooks/ -- the exact same byte-for-byte content already living in core/hooks/ and .claude/hooks/, which the scanner has never flagged. Root cause: .yana-aiignore already excludes .claude/** as 'internal tooling dirs -- scanner infrastructure, not user code' but was never updated to exclude .codex/** the same way when Codex adapter support was added. The findings themselves are the known false-positive class this ignore file already exists to handle -- guard-destructive.sh contains destructive-SQL and force-push keywords as its own detection patterns (text it matches against to block them), not code that executes or performs either action. Verified locally: full-repo scan before this fix showed 20 findings under .codex/ and 0 under .claude/ for identical content; after adding the ignore entry, 0 findings remain under .codex/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PR #86's self-audit CI job failed with 5 critical/8 high findings, all inside .codex/hooks/ -- the exact same byte-for-byte content already living in core/hooks/ and .claude/hooks/, which the scanner has never flagged. Root cause: .yana-aiignore already excludes .claude/** as 'internal tooling dirs -- scanner infrastructure, not user code' but was never updated to exclude .codex/** the same way when Codex adapter support was added. The findings themselves are the known false-positive class this ignore file already exists to handle -- guard-destructive.sh contains destructive-SQL and force-push keywords as its own detection patterns (text it matches against to block them), not code that executes or performs either action. Verified locally: full-repo scan before this fix showed 20 findings under .codex/ and 0 under .claude/ for identical content; after adding the ignore entry, 0 findings remain under .codex/. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Summary
main's CI went red immediately after PR #85 merged. Investigated at anh's request and found two real, distinct causes:
bin/yana's dispatch case-statement was missingmcp— same bug class as the earlierobservability/skill-qualityfix.yana-rt doctor dispatch . --json's self-check caught it ("kind": "unreachable", "name": "mcp"). Fixed and independently verified via a dedicated verify-agent dispatch (red/green comparison, sibling subcommands unaffected, exact CI check reproduced locally withfindings: [])..codex/(agents + hooks mirror),core/adapters/cursor/before-shell-execution.js, and its test suite were never committed to this repo at all, despite already-committed scripts (verify-hook-mirrors.sh,run-hook-tests.sh) assuming they exist. Confirmed viagit log --allreturning nothing for either path. Committed now with anh's explicit go-ahead —.codex/hooks/verified byte-for-byte in sync withcore/hooks/before staging, and the cursor adapter's own 6-case test suite passes locally.Test plan
run-hook-tests.sh260/260core/tests/adapters/cursor/test-before-shell-execution.sh6/6drift-check.shcleancore-lockunaffected (.codex//core/adapters/aren't in its pinned scope)yana-rt doctor dispatch . --jsonreproduced locally:findings: [](was[{"name":"mcp",...}]before the fix)Not fixed here, flagged separately to anh: a real race condition in
risk-scorer.sh/budget-sentinel.shvstoken-budget-guard.sh(concurrent writers to the same state file lose updates), caught by Hook Tests' own race assertions — out of scope for this fix.Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com