بنقرة واحدة
principles
The 12 design principles this codebase is built on. Read first, before any task.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
The 12 design principles this codebase is built on. Read first, before any task.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
How to consume a GitHub issue body as an agent task prompt. The 9-section template, the lifecycle, the failure modes.
Spec-driven development — the practice of writing the spec before the code. With the 9-section template and the three pnpm spec-check gates.
Differences and deterministic behavior of the mock ADT server used by adt-bench smoke runs.
How to return a strict scenario result JSON with evidence and no extra prose.
Test-driven loop for ABAP — inspect, change, check syntax, run unit tests, diagnose, fix.
Standard ABAP object workflow (discover, create or edit, check, activate, validate).
| name | principles |
| description | The 12 design principles this codebase is built on. Read first, before any task. |
The adt-bench codebase was built from scratch on a small set of non-negotiable principles. Every decision — what to include, what to defer, what to reject — is traceable to one of these. When in doubt, fall back to the principle. When you find yourself breaking one, justify it loudly in the PR.
The principles are ordered roughly from "this is the meta-rule" to "this is what we do on Tuesday". Read them in order.
The spec is the source of truth. Code is correct when it matches
the spec. The spec is correct when it describes the code we want.
The pnpm spec-check gate enforces this automatically.
The spec is written before the code. Not the other way around. Not at the same time. Before. If you find yourself writing code first, stop and write the spec.
See the sdd skill for the template, the three gates, and the
common failures.
The benchmark's value is comparing agent runtimes against the same scenarios. The scenarios, skills, and mock ADT server are the shared substrate; the agent is the variable. Every architectural decision must support this.
packages/runner-<name>/).bench-cli) MUST NOT know which runtime is
being used at the type level — only at the dispatch level
(--agent <name>).packages/bench-cli is the only place that knows the end-to-end
pipeline. Every other package is a single-concern module with a
narrow contract. The harness glues them together.
If you find yourself adding business logic to the harness, push it down into a package with its own spec. The harness should be ~300 lines, not 3,000.
A package's source code MUST NOT mention another domain's terms.
agent-runner MUST NOT mention ABAP, ADT, MCP, mastracode,
claude, openai, gpt, gemini.mock-adt-server MUST NOT mention agent, benchmark, scenario.scenarios MUST NOT import any other @adt-bench/* package.prompt-builder MUST NOT inject connector-specific adapter
documentation (that's the runner's job).evaluator MUST NOT know which agent produced the result.This is checked by tools/spec-coverage.mjs (manually, for now).
The reason: if a package starts knowing about another domain, the
boundary blurs and a future refactor becomes impossible.
Every external input is parsed by a Zod schema. The schema is the
source of truth; the TypeScript type is z.infer<typeof Schema>.
No class-validator, no yup, no hand-rolled parsers.
Why: Zod gives us runtime validation + compile-time types from one
declaration. The .strict() modifier catches typos and schema
drift. The .parse() throws ZodError with a structured path.
These are real engineering wins, not theoretical.
Every package's specs/SPEC.md §6 lists every test the package
must pass. The spec-drift tool fails the build if a test in the
matrix is missing from code, OR if a test in code is missing from
the matrix. The two directions are equally important.
A test that is not in the matrix is "untested coverage claim" — a lie about what we know. A matrix row that is not in code is a broken promise. Both fail the build.
The spec is the what — the contract. The tests are the proof that the contract holds. The spec is prose; the tests are executable.
If the spec says "MUST NOT throw", the proof is a test that catches the throw and reports a failure. If the spec says "returns the file content as a string", the proof is a test that calls the function with a known input and asserts the string.
A spec without tests is a wish. A test without a spec is a maintenance burden. Both together are a contract.
Every specs/SPEC.md has the same 9 sections, in the same order:
The order is fixed. The sections are mandatory. The spec-check
gate enforces it. Deviating from the template is a sign that
something is wrong with the spec.
Why: a predictable structure lets reviewers and tools assume section presence. If §3 is "Behaviour contracts" in every spec, you can find it in 2 seconds. If §3 is "How it works" in one spec and "API reference" in another, every review costs you a search.
Every spec has a §7 "Non-goals" section that explicitly lists what the package does NOT do. This is not a TODO list. This is a fence.
A non-goal says: "I considered this. We are not doing it. Here's why." It prevents scope creep at the PR-review stage. "But you could just..." is a non-goal violation, not a feature request.
The hardest part of every design decision is not picking what to do — it's picking what not to do. Document that.
Every cross-package boundary is a Zod schema. The schema is public; the implementation behind it is private.
AgentRunResult is a Zod schema. The shape is fixed. Changing
it requires a major version bump.ScenarioResult is a Zod schema. The shape is what the agent
must return. The agent can be wrong; the schema is right.Evaluation is a Zod schema. The shape is what the evaluator
must produce. The evaluator can be wrong; the schema is right.If you change a schema, you break a contract. The change should be deliberate, reviewed, and documented in the spec.
Every end-to-end run hits the mock ADT server. The mock is deterministic, in-process, and has the same shape as a real SAP ADT endpoint. A test that "talks to ADT" talks to the mock, not to a real BTP system.
This means:
pnpm bench:smoke runs in CI without secrets.pnpm verify runs in CI without an LLM (the simulated agent
returns a deterministic ScenarioResult).pnpm install && pnpm verify,
and see the whole pipeline work in <60s.When you add a real agent runner, you MUST also support the
simulated and replay modes so CI stays deterministic. The
live mode is for humans with secrets.
Every interesting technical choice in this codebase was rejected in favor of the boring one:
yaml library? No, use
yaml (issue #10).mastracode or the
AgentRunner interface.Boring solutions win because:
yaml library is on a stable
version; our hand-rolled parser was already broken on the
:// case.vitest stops working, we can swap to
node:test. If we build a custom runner framework, we own the
maintenance forever.The default answer is "use the boring thing." The default answer is right 90% of the time.
When you face a design decision, ask:
If the answer to any of these is "no" or "I'm not sure", stop and read the relevant package's SPEC.md. If the SPEC.md doesn't answer your question, update the SPEC.md first, then continue.