Skip to content

feat: audit fixes round 2 - supersede, questions, kb-audit, hygiene#9

Merged
George-iam merged 19 commits intomainfrom
feat/audit-fixes-round2-20260406
Apr 6, 2026
Merged

feat: audit fixes round 2 - supersede, questions, kb-audit, hygiene#9
George-iam merged 19 commits intomainfrom
feat/audit-fixes-round2-20260406

Conversation

@George-iam
Copy link
Copy Markdown
Contributor

Summary

5 commits that were orphaned after PR#8 merge. Cherry-picked onto fresh branch from main.

  1. auditor supersede/amend action parsing (A1 Level 2)
  2. open questions inter-session protocol (A2) - 3 new MCP tools
  3. KB audit counter + structural report (A3)
  4. hygiene: fsync, scope warning, orphan event rename, attachClaudeSession retry (C1, C2, E2, E7, E9)
  5. YAML parser colon fix, workspace-merge DRY, init error reporting (N5, N6, N11)

Test plan

  • Full storage audit: 119/119 PASS
  • Build clean
  • Full E2E on fresh MCP server (requires VS Code reload)

- AUDIT_PROMPT now includes action field for decisions: new/supersede/amend
- Parser extracts action, supersedes, amends fields from auditor output
- session-cleanup handles three paths:
  - action=supersede: calls supersedeDecision(oldId, newInput)
  - action=amend: saves with same slug (overwrite existing)
  - action=new: default, unchanged behavior
- DECISIONS field spec includes supersedes/amends with usage instructions

Completes: A1 Level 2 from full audit plan.
New storage module questions.ts with markdown-based Q&A protocol:
- askQuestion(): create [open] question with id Q-NNN
- answerQuestion(): record user answer, status -> [answered]
- markQuestionApplied(): status -> [applied] with note
- listQuestions(): parse .axme-code/open-questions.md
- questionsContext(): inject open questions into axme_context output

3 new MCP tools:
- axme_ask_question: agent/auditor records a question
- axme_list_open_questions: show pending questions
- axme_answer_question: record user's answer

Integration: axme_context shows open questions section when any exist.

Closes: A2 from full audit plan.
- New storage module kb-audit.ts: counter tracking, report persistence
- incrementKbAuditCounter called after each successful session audit
- Warns in stderr at 20+ sessions since last KB audit
- New CLI: axme-code audit-kb --workspace X
  Shows decision/memory counts, writes structural report, resets counter
- LLM-powered conflict analysis deferred to future version

Closes: A3 from full audit plan.
- engine.ts: fsync before rename in atomicWrite, fsync after write in
  appendLine (crash safety on SIGKILL)
- memory.ts: scope validation warning when repos not found in workspace
- types.ts: rename session_orphan_closed -> session_orphan_audit_queued
  (honest semantics — event fires on worker spawn, not completion)
- sessions.ts: attachClaudeSession retry loop (3x 50ms) on transient
  meta.json unavailability during shutdown race

Closes: C1, C2, E2, E7, E9 from full audit plan.
- test-plan.ts: YAML parser now splits on first word-char colon only,
  fixing values with colons (e.g. command: curl http://host:8080)
- workspace-merge.ts: documented alignment with safety.ts unionMergeSafety,
  added mergeSafetyRulesFromPaths re-export, removed standalone dedupe()
- init.ts: silent catch{} blocks in Phase 1/2 now report errors via
  workspaceResult.errors and opts.onProgress instead of swallowing

Closes: N5, N6, N11 from full audit plan.
checkGit now checks via `gh pr list --head <branch> --state merged`
before allowing git push. If the current branch already has a merged PR,
push is denied with a message pointing to D-041 (reusing old branches
prohibited). This prevents the scenario where an agent continues pushing
to a stale branch after PR merge, losing commits that never reach main.

Fails open if gh CLI unavailable or network error.
shortenToolInput for unknown tools now wraps JSON.stringify in try-catch,
falling back to "[object]" on circular references. Prevents crash during
transcript rendering if a tool input contains cyclic structures.

Also: triage of all 24 catch{} blocks in src/ — all are intentional
fail-open patterns for hooks, workspace detection, and best-effort cleanup.
No changes needed.

Closes: N18, N27, T1 from full audit plan.
E4:  ensureAxmeSessionForClaude empty-tail suppression — read-only tools
     (Read/Glob/Grep) reuse stale session instead of creating empty fresh one
E5:  checkBash deniedCommands per pipe segment (was whole-string includes)
E8:  decisions rebuildIndex in-process mutex via promise chain
N4:  deploy.ts dead code removed (showChecklist, runChecklist, ChecklistRunResult)
N7:  init.ts fromPresets counter — always computed dynamically from storage
N9:  session-auditor path normalization consistent (strip leading ./)
N10: (verified OK — includes() check already prevents exact dups)
N12: (verified OK — different dirs prevent real collision)
N14: workspace-detector enrichWithGitRepos returns new object, not mutate
N15: workspace-detector path normalization strips ./ prefix
N16: config.ts warns on unknown preset IDs in config.yaml
N17: presets.ts removed self-referencing presets from ai-agent-guardrails
N19: escapeXml now escapes quotes (&quot; &apos;)

All 54 issues from the full audit plan are now closed.
- questions.ts: header regex now matches space-separated timestamps.
  nextId scans raw file as fallback for robustness.
- safety.ts: pipe-containing deniedPrefixes now match anywhere in the
  pipe chain, not just from start. Multi-segment pipe commands with
  denied patterns in the middle are now correctly blocked.

Found and fixed during PR#9 E2E verification (81/81 assertions).
…status

A3 complete: agents/kb-auditor.ts with full LLM flow:
- Prompt analyzes all active decisions + memories + oracle evidence
- Finds conflicts, stale entries, consolidation candidates, ambiguities
- Returns structured KbAuditFinding[] with confidence scores
- CLI axme-code audit-kb now runs LLM analysis (not just structural report)
- --apply flag auto-supersedes/revokes findings with confidence >= 0.9
- Creates open questions for ambiguous findings via questions.ts API

PR#14 complete: AUDIT_PROMPT ###QUESTIONS### section:
- Auditor can emit questions when it finds ambiguity in transcript
- Parser extracts question/context pairs from output
- session-cleanup saves questions via askQuestion() after audit
- Questions merged across chunks in multi-chunk audits

N13 complete: AuditLogExtraction.status now includes "updated":
- When saveScoped overwrites existing slug, status = "updated" not "deduped"
- Audit log truthfully reflects what happened

All 54 issues from the audit plan are now fully implemented.
kb-auditor.ts used static `import { Claude }` which doesn't exist as
named export in @anthropic-ai/claude-agent-sdk. Changed to dynamic
`await import()` + `sdk.query()` pattern matching session-auditor.ts.
Also uses extractCostFromResult for proper cost tracking.

This was causing SyntaxError crash on any CLI command that loaded dist/
(cleanup, audit-kb, hooks) because the static import fails at module
instantiation time.
- Fixed sdk.query() pattern (was using non-existent static import)
- Reduced oracle evidence from all 57 repos to top 5 by decision count
  (84K → 41K chars, 21K → 10K tokens)
- KB audit now completes in ~2 min, finds real issues (10 findings on
  live workspace: 7 conflicts, 1 stale, 1 consolidate, 1 question)
- Verified E2E: $0.15 cost, report written to kb-audit/

Also fixed stale catch{} syntax error in cli.ts from previous edit.
- axme-code audit-kb now auto-detects workspace root from cwd (even if
  running from a sub-repo like axme-code). Falls back to parent dir if
  cwd is single-repo inside a workspace.
- --all-repos flag collects decisions from ALL repos (2444 across 56)
  instead of just workspace-root (75). Enables cross-repo conflict
  detection.
- Fixed duplicate fs import declarations in cli.ts.
- Usage updated: axme-code audit-kb [--all-repos] [--apply]
With --all-repos, each repo gets its own LLM audit call with its own
decisions + memories + oracle evidence. This ensures per-repo conflict
detection works correctly and keeps prompt size manageable (~10K tokens
per repo instead of 60K+ for all 2444 decisions in one call).

Without --all-repos, only workspace-level decisions (75) are audited.

Report shows findings tagged with source repo: "[CONFLICT] D-012, D-045 @ axme-control-plane".
--apply targets the correct repo path for each finding.
Complete rewrite of KB auditor:
- Agent with Read/Grep/Glob/Edit/Write/Agent tools
- Reads decisions + memories from .axme-code/
- Checks actual code to verify which decisions are current
- Directly edits decision files (supersede/revoke) — no --apply flag needed
- --all-repos: agent audits each repo independently, can use sub-agents
- Streams thinking + text output to stderr for visibility
- Auto-detects workspace root from any sub-repo cwd
@George-iam George-iam merged commit baec291 into main Apr 6, 2026
@George-iam George-iam deleted the feat/audit-fixes-round2-20260406 branch April 7, 2026 08:00
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