Skip to content

Fix residual gaps: typed hooks, security hardening, CLI testability#8

Merged
ApiliumDevTeam merged 26 commits intodevfrom
fix/residual-gaps-audit-rondas-1-3
Mar 3, 2026
Merged

Fix residual gaps: typed hooks, security hardening, CLI testability#8
ApiliumDevTeam merged 26 commits intodevfrom
fix/residual-gaps-audit-rondas-1-3

Conversation

@ApiliumDevTeam
Copy link
Copy Markdown
Collaborator

@ApiliumDevTeam ApiliumDevTeam commented Mar 3, 2026

Summary

  • Rewrite extension hooks to use typed event fields instead of as Record<string, unknown> casts across semantic-observability, semantic-skills, memory-semantic, and agent-mesh (eliminates 13 unsafe casts)
  • Harden agent-mesh: namespace-prefix enforcement on share/query tools, bounded message log, ACL grant fix, companion triples for conflict resolution, batched delegation queries
  • Replace process.exit with defaultRuntime.exit in 4 CLI modules (hooks, logs, plugins, help) for testability
  • Fix CLI command registration: pass argv explicitly, use Promise.allSettled for subcli registration, extract lightweight-commands constants
  • Add injection detection patterns (3 new) and variant test coverage (7 new tests) in enrichment-sanitizer
  • Fix agent-events state cleanup: clear seqByRun + listeners in reset, add missing test resets in agent-events and commands tests
  • Fix extension packages: import paths (mayros/plugin-sdk), missing devDependencies, peerDependency versions

17 atomic commits, 33 files, 406 insertions, 260 deletions.

Test plan

  • npx tsc --noEmit — 0 errors
  • pnpm build — clean
  • pnpm test -- src/infra/agent-events.test.ts extensions/semantic-skills/enrichment-sanitizer.test.ts src/auto-reply/reply/commands.test.ts — all pass
  • grep -n "as Record" extensions/semantic-observability/index.ts → 0 matches
  • grep -n "(event as Record" extensions/memory-semantic/index.ts → 0 matches
  • grep -n "process\.exit" src/cli/hooks-cli.ts src/cli/plugins-cli.ts src/cli/logs-cli.ts src/cli/program/help.ts → 0 matches
  • Full test suite pnpm test — no regressions

ApiliumDevTeam and others added 26 commits March 2, 2026 18:59
## Summary

- **Bump pnpm overrides**: `minimatch` 10.2.1→10.2.3 (2x HIGH ReDoS),
`fast-xml-parser` 5.3.6→5.3.8 (LOW stack overflow)
- **Bump node-llama-cpp** 3.15.1→3.17.1: drops 4 deprecated transitive
packages (npmlog, gauge, are-we-there-yet, old tar)
- **Drop @discordjs/opus**: eliminates 7 deprecated packages from the
`node-pre-gyp` chain; `opusscript` is already the preferred codec
- **Fix 107 README links**: maryos→mayros across all docs
- **Fix 15 broken internal doc links** caught by `docs:check-links`
- **Fix 15 test files for vitest 4.x** mock hoisting compatibility
(BlueBubbles, Telegram, Slack, Feishu, agent-runner, cron,
hooks/install, CortexSidecar)
- **Track CI-required assets** (.gitignore negation rules for template
docs, a2ui bundle placeholder, test fixture tgz)
- **Bump version to 0.1.2** + sync 38 extensions
- Platform updates: iOS, Android (Play Store + sideload flavors), macOS
- Rename clawnet→meshnet in refactor docs

## Test plan

- [x] `pnpm install` — no resolution errors
- [x] `pnpm build` — succeeds
- [x] All 239 previously-failing tests pass locally (12 test files
verified)
- [x] CI: check-docs, build-artifacts, CodeQL, skills-python, protocol,
android test/build all green
- [ ] CI: full test suite on push
- [ ] CI: macOS job

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Bumps the docker-images group with 2 updates: node and debian.


Updates `node` from 22-bookworm to 25-bookworm

Updates `debian` from `98f4b71` to `74d56e3`

---
updated-dependencies:
- dependency-name: node
  dependency-version: 25-bookworm
  dependency-type: direct:production
  dependency-group: docker-images
- dependency-name: debian
  dependency-version: bookworm-slim
  dependency-type: direct:production
  dependency-group: docker-images
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the docker-images group with 2 updates: node and debian.

Updates `node` from 22-bookworm to 25-bookworm

Updates `debian` from `98f4b71` to `74d56e3`


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>
The deriveIdHint() function was returning "mayros-bluebubbles" from
the npm package name, but plugin manifests use short IDs like
"bluebubbles". Strip the "mayros-" prefix so hints match manifests
and eliminate 38 config warnings on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t timeout

- Android bundle-playstore job now skips gracefully when KEYSTORE_FILE
  secret is not configured, instead of failing with ENOENT
- Increase Discord pairing test timeout from 10s to 60s to handle
  slow CI runners under heavy load

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
## Summary

- **Strip `mayros-` prefix from plugin entry hints** — eliminates 38
config warnings on startup by aligning derived hints with manifest short
IDs
- **Skip Android `bundle-playstore` when keystore is missing** — job now
skips gracefully instead of failing with ENOENT
- **Increase Discord pairing test timeout** — 10s→60s to handle slow CI
runners

## Test plan

- [x] Plugin discovery tests pass (8/8)
- [x] Discord monitor tests pass (3/3)
- [x] All 239 previously-fixed tests still pass
- [ ] CI green on push

🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary

- Bump root package.json version to 0.1.3
- Sync 38 extension versions to 0.1.3

## Test plan

- [x] `pnpm plugins:sync` — 38 updated, 0 skipped
- [ ] CI green

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- llm-task, open-prose: use mayros/plugin-sdk instead of relative path
- llm-task, open-prose: add missing devDependency on @apilium/mayros
- googlechat, memory-core: fix peerDependency version to >=0.1.0
- skill-hub: add missing semver dependency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Makes CLI exit points testable by routing through the runtime
abstraction instead of calling process.exit directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- command-registry: pass argv param instead of using process.argv
- register.subclis: wrap eager registration in Promise.allSettled to
  prevent a single failing subcli from breaking others

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move ALLOWED_INVALID_COMMANDS and ALLOWED_INVALID_GATEWAY_SUBCOMMANDS
  to shared lightweight-commands module
- Add shouldRegisterPrimarySubcommand guard in run-main
- Add resetConfigGuardForTest helper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use pickGatewayPort() instead of hardcoded 18789 so the SSH tunnel
command matches the actual configured gateway port.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows tests to reset the bannerEmitted state between test cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- clearAgentRunContext: also clear seqByRun entry to prevent stale
  sequence numbers across runs
- resetAgentRunContextForTest: clear all Maps (runContextById, seqByRun,
  listeners) for complete test isolation
- Add missing resetAgentRunContextForTest() call in 3rd test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use { hash?: string } instead of any for the createTriple no-op stub.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 3 new patterns: 'do not follow system/developer', 'developer
  message', and XML-tag injection (<system>, <assistant>, etc.)
- Add 7 tests for uncovered regex variants: forget, pretend, you
  should, run bash, override instructions, wget, eval

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- prepareContext: batch listTriples calls in groups of 5 with
  Promise.all to reduce sequential Cortex round-trips
- mergeResults: pre-fetch all parent text values into a Set to
  eliminate N+1 dedup queries
- Add removeInjectedContext to prevent memory leaks from accumulated
  delegation contexts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Store companion triple with full original predicate alongside
  conflict-flag triple for unambiguous resolution
- resolveConflicts: look up companion triple for exact original
  predicate, with endsWith fallback for legacy data
- Clean up companion triples when resolving conflicts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Using owners[0] as grantor was incorrect — the first owner cannot
grant admin to themselves. Use 'system' as the grantor instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hooks:
- subagent_spawning: use typed event.agentId/label/childSessionKey
  instead of as Record casts
- subagent_ended: use event.targetSessionKey/outcome/runId, clean up
  injected context on end
- before_agent_start: mark unused event as _event
- agent_end: use typed event.success instead of cast

Tools:
- mesh_share: enforce namespace prefix on subject and predicate
- mesh_query: two-step query via ownership triples instead of single
  patternQuery that could leak cross-namespace data
- mesh_conflicts: remove always-true conditional after early return
- CLI share: add write access check before createTriple

Infra:
- Bound messageLog to 1000 entries via appendToMessageLog helper
- Add ensureNsPrefix utility for consistent namespace enforcement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove dead before_agent_start hook (event.skills does not exist
  on PluginHookBeforeAgentStartEvent)
- Remove before_tool_call hook and toolCallTimers map; rewrite
  after_tool_call using typed event.toolName/params/result/durationMs
- Fix LLM hooks: use event.runId instead of callId, event.usage.input
  and event.usage.output instead of promptTokens/completionTokens
- Remove redundant String() wrapper on event.model (already string)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- semantic-skills before_tool_call: use typed event.toolName directly
- semantic-skills after_tool_call: use typed event.toolName and
  event.result directly, remove redundant null guard
- memory-semantic before_compaction: use typed event.messages directly
  instead of casting to Record<string, unknown>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test exercises /bash via handleCommands but did not call
resetBashChatCommandForTests() first, risking stale activeJob
state from prior tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ApiliumDevTeam ApiliumDevTeam merged commit 4fb8587 into dev Mar 3, 2026
3 checks passed
@ApiliumDevTeam ApiliumDevTeam deleted the fix/residual-gaps-audit-rondas-1-3 branch March 3, 2026 10:53
ApiliumDevTeam added a commit that referenced this pull request Mar 9, 2026
## Summary

- **Rewrite extension hooks** to use typed event fields instead of `as
Record<string, unknown>` casts across semantic-observability,
semantic-skills, memory-semantic, and agent-mesh (eliminates 13 unsafe
casts)
- **Harden agent-mesh**: namespace-prefix enforcement on share/query
tools, bounded message log, ACL grant fix, companion triples for
conflict resolution, batched delegation queries
- **Replace `process.exit`** with `defaultRuntime.exit` in 4 CLI modules
(hooks, logs, plugins, help) for testability
- **Fix CLI command registration**: pass argv explicitly, use
`Promise.allSettled` for subcli registration, extract
lightweight-commands constants
- **Add injection detection patterns** (3 new) and **variant test
coverage** (7 new tests) in enrichment-sanitizer
- **Fix agent-events state cleanup**: clear seqByRun + listeners in
reset, add missing test resets in agent-events and commands tests
- **Fix extension packages**: import paths (`mayros/plugin-sdk`),
missing devDependencies, peerDependency versions

17 atomic commits, 33 files, 406 insertions, 260 deletions.

## Test plan

- [x] `npx tsc --noEmit` — 0 errors
- [x] `pnpm build` — clean
- [x] `pnpm test -- src/infra/agent-events.test.ts
extensions/semantic-skills/enrichment-sanitizer.test.ts
src/auto-reply/reply/commands.test.ts` — all pass
- [x] `grep -n "as Record" extensions/semantic-observability/index.ts` →
0 matches
- [x] `grep -n "(event as Record" extensions/memory-semantic/index.ts` →
0 matches
- [x] `grep -n "process\.exit" src/cli/hooks-cli.ts
src/cli/plugins-cli.ts src/cli/logs-cli.ts src/cli/program/help.ts` → 0
matches
- [x] Full test suite `pnpm test` — no regressions
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