upload current sources

This commit is contained in:
2026-09-16 01:47:28 -07:00
commit f8b45ea4a5
109 changed files with 26012 additions and 0 deletions
@@ -0,0 +1,94 @@
# ADR-003 — Ground-truth enforcement: hooks, not advice
Date: 2026-09-04 · Status: Accepted
## Context
The old estate proved that advisory guidance fails: an MCP routing table, skills,
and operating rules existed for months, yet the servers and skills were never
consulted during development — even on the CAP packages where they obviously
applied. Causes: tool-selection dilution under a saturated loadout, zero
enforcement (prose loses to momentum), friction (cold starts, deferred tool
loading), and model overconfidence in trained SAP knowledge. The requirement for
this repo: consultation must be structural — the agent must forget what it
thinks it knows, consult the MCP servers and context7 before work starts, and be
able to cite sources on demand.
## Decision
Four mechanisms in `.claude/settings.json` + `.claude/hooks/` (project scope,
part of the founding kit for every future package):
1. **SessionStart injection** — every session opens with the grounding charter:
training knowledge is not a citable source; the five MCP servers + context7
are; if tools are deferred, loading them is the first action.
2. **Per-prompt reflex (UserPromptSubmit)** — a SAP-scoped analogue of the
machine-global TOOL-REFLEX hook: never classify whether a prompt "needs" a
consult; the classification step is the known failure.
3. **Consultation gate (PreToolUse deny)** — every successful `mcp__*`,
WebSearch, or WebFetch call stamps `.claude/.last-mcp-consult`; a Write/Edit
on a SAP artifact (`.cds`, `.abap`, `.bdef`, annotations, views,
`manifest.json`, `srv/`, `app/`, `worker/`) is **denied** unless a
consultation happened within 30 minutes, with the remedy stated in the denial
reason. Governance `.md`, `docs/`, and `.claude/` paths are exempt so
documentation never jams.
4. **Citation duty** — every SAP behavioral claim recorded in PRD/ADR/KNOWLEDGE
carries `[source: <server> <doc-id/URL>, verified YYYY-MM-DD]` (CLAUDE.md
rule 6); a PostToolUse reminder fires on governance-doc edits. Uncited =
hypothesis.
## On "load tools automatically at session start"
**Corrected 2026-09-04** after reading the 2026-09-03 "Investigate performance
lag issue" session transcript: my original claim ("no setting exists to preload
deferred tools") was true of settings *keys* but wrong in practice. The
`ENABLE_TOOL_SEARCH=false` environment variable disables deferral entirely
(verified against the binary in that session). It must be set before process
bootstrap — the settings.json `env` block loads too late, per that session's
finding — so it lives in the `claude()` wrapper in `~/.bashrc`, where it is
**already active machine-wide**, including for sessions started in this repo.
History: preloading was first measured at ~98k tokens/turn at the old ~950-tool
surface and rejected in favor of the TOOL-REFLEX hook; once plugin localization
cut the surface to ~40 tools, the same session adopted preloading via the
wrapper. This repo's slim 5-server loadout keeps the preload cost small.
Mechanism 1 (SessionStart load-first order) remains as the fallback for launch
paths that bypass the wrapper (e.g. IDE-spawned sessions).
## Consequences
- Consultation stops being a virtue and becomes a precondition; skipping it now
produces a denied edit instead of silent drift.
- The 30-minute freshness window is a tunable; if it proves too tight or too
loose in practice, adjust it in `sap-consult-gate.sh` and note it here.
- The gate measures that *a* consultation happened, not that the *right* one
did — citation duty and review cover relevance.
- Hooks activate on the first session started inside this repo (project hooks
are read at session start).
## Amendment 2026-09-14 — gate hardened after code review
The 2026-09-04 gate was advisory in practice: the `Write|Edit` matcher missed
Bash writes (sed -i, heredocs, tee, cp/mv, interpreter one-liners), MultiEdit,
NotebookEdit and filesystem-MCP edits; the `mcp__.*` PostToolUse matcher let
any MCP call (memory, chrome, mcp-manage) refresh the 30-minute marker; hook
commands hard-coded this checkout's absolute path; and a missing `jq` produced
a silent allow. I changed the mechanism, not the prose:
- PreToolUse gate matches `Write|Edit|MultiEdit|NotebookEdit|Bash|
mcp__filesystem__write_file|mcp__filesystem__edit_file|mcp__filesystem__move_file`;
for Bash the script gates only commands that combine a write indicator with
a gated path (documented heuristic, known blind spots: variable-built paths,
`cd`-relative paths, writes by invoked scripts).
- The consult marker is refreshed only by the grounding servers (sap-docs,
abap-docs, sap-released-objects, the Fiori/UI5 servers, context7, CAP) and
WebSearch/WebFetch — anchored regex in `settings.json`.
- Hook commands resolve via `"${CLAUDE_PROJECT_DIR}"`; scripts prefer that
variable over `$0` [source: https://code.claude.com/docs/en/hooks —
"`${CLAUDE_PROJECT_DIR}`: the project root where the session started",
verified 2026-09-14].
- Missing `jq` or an unresolvable marker now denies (fail closed); `jq` is a
hard dependency of any session in this repo.
- `*/worker/*` left the gated set: the TypeScript worker is governed by
context7 and the OpenAPI contract, not the SAP gate.
- `.claude/hooks/tests/run.sh` pipe-tests both scripts (37 cases) against an
override marker so the real marker is never touched.