Create your own
Lesson illustration

Writing Project Instructions for Kernel Version, File Scope, Commands, Evidence, Work Lists, and Assumptions

Hello. This module turns your driver work into a controlled engineering loop rather than a sequence of long, improvised agent chats. The first control is a project instruction contract: a short, version-controlled document that tells an agent what repository it is working in, what it may change, what it must prove, and when it must stop for a human decision.

For this driver, the contract must be stricter than a typical coding-assistant prompt. A plausible-looking DSA change can still be wrong if it silently assumes hardware behavior, imports semantics from a superficially similar switch, or runs against the wrong kernel base. Your instruction file should therefore make evidence, scope, and stopping conditions explicit.


Choose an agent entry point, then keep the policy portable

Do not assume one instruction filename is automatically understood by every tool.

  • Claude Code: use a repository-root CLAUDE.md (or .claude/CLAUDE.md). Claude Code documentation describes these as project-wide, version-controlled instructions.
  • Cursor: either use a root AGENTS.md for simple project instructions or use .cursor/rules/*.mdc when you want rules that are always applied or attached only for specified paths.

The policy text itself should be tool-neutral: it should say “the agent,” not “Claude” or “Cursor.” That makes moving between tools a controlled transcription problem rather than a redesign.

If your team uses one tool at a time, place the complete contract in its active entry point. If you support both tools concurrently, maintain one canonical source such as docs/ai/agent-contract.md, and ensure that the active tool’s entry point contains the same policy or an explicitly supported reference to it. Review changes to the policy as carefully as changes to driver code.

CLAUDE.md and Agents.md Explained: Stop Repeating Yourself to AI

Watch “CLAUDE.md and Agents.md Explained: Stop Repeating Yourself to AI” from GritAI Studio for a compact explanation of what a useful project context file contains: exact commands, versions, layout, workflow, and boundaries.

Watch the six areas to identify the essential contents of a project instruction file. Then watch building the rules, focusing on the distinction between an initial generated draft and the project-specific constraints that make it reliable.

If you are using Claude Code, read the official placement guidance:

How Claude remembers your project - Claude Code Docs

Read Anthropic’s Claude Code documentation to choose the correct scope for shared project instructions and to see how larger instruction sets can be split into focused rules.

In the “CLAUDE.md files” section, read the project instruction locations, especially the distinction between project and local files. Then, in “Organize rules with .claude/rules/” and “Path-specific rules,” read the modular rule guidance. Use root-level instructions for non-negotiable project rules; reserve path-specific rules for later, when code-area-specific guidance is genuinely needed.

If you are using Cursor, read the official rule model:

Rules | Cursor Docs

Read Cursor’s documentation to understand the difference between a simple repository-wide instruction file and structured rules with scope and frontmatter.

In “Project rules” and “Rule anatomy,” read how project rules are applied. Pay particular attention to alwaysApply, description, and globs: an always-applied rule is appropriate for kernel version, evidence, and safety rules. Then read the “AGENTS.md” section, beginning the simple markdown option. For this course, prefer one small always-applied project contract before adding path-specific rules.

Treat instructions as a contract, not a suggestion

A useful instruction file is neither a generic personality prompt nor a copy of the Linux coding style document. The kernel tree already contains much of its own convention. Your contract should record facts that an agent cannot safely infer:

  1. Identity: the exact kernel source, target submission base, V1 patch-series origin, architecture, and configuration.
  2. Authority: which files the agent may change for a particular task, and which files it must never alter.
  3. Standard commands: the approved commands that produce comparable evidence.
  4. Evidence discipline: what counts as a fact, what must be recorded, and when ambiguity stops a hardware-related edit.
  5. Work-list discipline: the required record for every review item and every newly discovered failure.
  6. Non-assumptions and stop rules: the conditions requiring a human answer rather than an invented answer.

This is similar to defining a narrow interface in kernel code: vague permissions create unbounded behavior. “Fix the driver” is not an interface. “For task REV-014, edit only these files, use these commands, and prove these claims” is.

A text instruction file alone is not a security boundary. An agent with unrestricted shell access may still run commands it should not. In the next lessons, you will back this policy with command allow-lists, separate worktrees, checkpoints, logs, retry limits, and human approval gates. For now, make the intended rules clear enough that they can later be enforced mechanically.


Make the kernel identity impossible to guess

“Use Linux 6.x” is not a sufficient instruction. A release label can refer to a tag, a stable branch tip, a vendor tree, or an internal backport. DSA APIs, YAML schemas, helper availability, and review expectations are all tied to the actual tree.

Record both a human-readable label and an immutable commit identity:

FieldWhy it belongs in the contract
KERNEL_TREEDistinguishes upstream, stable, vendor, or internal tree.
TARGET_BASE_REFHuman-readable target, such as a release tag or branch name.
TARGET_BASE_COMMITFull commit ID used for diffs and proof.
V1_SERIES_BASE_COMMITExact tree on which V1 was authored or reconstructed.
DRIVER_PATHPrevents searching or editing the wrong driver.
BINDING_PATHNames the binding that must agree with driver property handling.
ARCH and DEFCONFIGMakes build and DTB results reproducible.
PATCH_RANGEDefines exactly what Sashiko and later review tools assess.

Use values collected during the baseline restoration work. Do not let the agent “discover” a convenient substitute if one is missing.

For example, this is an acceptable policy statement:

Target submission base:
  tree: upstream linux.git
  ref: v6.XX
  commit: <full verified commit ID>

The agent must compare HEAD with the target base before analysis or edits.
If HEAD is not descended from the recorded base, stop and report BASE_MISMATCH.
The agent must not choose a different tag, branch, stable release, or vendor tree.

The placeholders are deliberately blocking. Until you replace them with verified values, the agent may inspect and organize evidence, but it must not claim a target-kernel result.


Scope files by task, not by optimism

“Only modify the driver” is usually too vague. A DSA repair may properly involve the driver, binding YAML, a Makefile or Kconfig entry, and documentation. But it should not silently expand into unrelated cleanup across net/dsa/ or a broad Device Tree conversion.

Use three file classes.

ClassRule
Always allowedThe agent contract, work list, evidence records, and logs. These are the loop’s records, not product code.
Task-allowedExact paths listed on the approved work-list item. The agent may edit these only to solve that item.
ProtectedUntouched V1 archive, original upstream-review records, supplied manuals, generated artifacts, unrelated kernel code, Git metadata, and external repositories.

The important detail is that a task’s permitted files are an allow-list, not a guess based on the agent’s interpretation of relevance. If a proposed patch needs an additional file, the agent must explain why, update the task plan, and wait for approval when your process requires it.

Protect the original evidence especially carefully:

  • Keep the recovered V1 series in an untouched location or reference.
  • Preserve upstream comments in their original wording and context.
  • Do not alter a supplied hardware manual, even to annotate it.
  • Do not “clean up” generated DTB files, build outputs, or reviewer quotations.
  • Do not rewrite history, rebase, force-push, or change branches unless an explicit later approval permits it.

Define standard commands as named evidence producers

The agent should not improvise a build because it recognizes a Linux tree. Its commands must come from the baseline work and be recorded with their relevant environment.

A good contract gives each command an identifier, an exact command after you fill the project values, what it checks, and where its output belongs. At this stage, command entries may be individual commands; the next lesson will package them into one repeatable check command.

A practical set is:

Command IDPurposeMust save
base.verifyVerify target base and current patch rangecommand line, full commit IDs, exit code
build.driverBuild the relevant configuration and driver.config, command, full log, exit code
warn.driverRun the agreed warning-sensitive buildcommand, log, exit code
checkpatch.seriesCheck the actual patch rangerange, options, output, exit code
dt.bindingValidate the binding schemaschema path, command, log, exit code
dt.dtbBuild and validate the relevant DTBsDTS list, command, log, exit code
sashiko.reviewReserved for the later required review gateexact range, version, settings, report

For the kernel tree, the eventual commands will normally use the established output directory and configuration, followed by appropriate targets such as the driver’s build target, dt_binding_check, and dtbs_check. The exact architecture, configuration, schema selector, and DTS targets must be filled from your V1 baseline—not guessed from an analogous driver or a web example.

Two rules matter:

  1. A command that exits zero is evidence only for what that command checks. A successful binding check does not prove the register configuration is correct.
  2. Every command record needs an exit code and log path. “Build passed” is not traceable evidence.

Write evidence rules that resist plausible invention

The central risk in this project is not merely an incorrect code edit. It is an agent presenting an assumption as hardware fact.

Your instruction contract should require the agent to label each significant claim by source and confidence:

Claim typeMinimum evidence
Hardware behaviorExact manual name, revision, page or section, quoted or precisely paraphrased statement, and status: clear, unclear, incomplete, or conflict.
Target-kernel DSA ruleTarget-tree source path, symbol or relevant call path, and target-base commit.
Existing V1 behaviorFile path, symbol, and line range or commit context. This proves only what V1 does, not that V1 is correct.
Pattern from another driverDriver name, path or commit, trait being compared, and the explicit limit of the comparison.
Review findingOriginal review thread, patch version, reviewer, date if known, and unmodified wording.
Test resultApproved command or hardware test ID, environment, log path, time, and exit/result state.

The most important distinction is:

An analogous driver is evidence of an upstream pattern, not evidence of your switch’s register semantics.

Similarly:

Existing driver code is evidence of existing behavior, not proof of intended hardware behavior.

When a manual is vague, contradictory, incomplete, or unreadable for a relevant hardware-programming decision, the agent must create a BLOCKED_HUMAN task. It should ask a narrow question that identifies the register or behavior, the manual passages in tension, the code decision blocked, and the possible outcomes. It must not resolve the ambiguity by copying V1 or another driver.


Use a work list that retains the original review record

A work list is not a to-do list with “fix review comments.” It is a traceability record joining:

  • a reviewer’s original concern,
  • the task derived from it,
  • the evidence required to decide it,
  • the files and commands permitted,
  • the resulting patch and reviewer reply.

Use one stable identifier per atomic item, such as REV-014. Preserve the original feedback verbatim in the record; write your interpreted task separately. A reviewer may have asked a question rather than demanded a change. Rewriting it prematurely can hide what still needs proof.

Below is a compact, tool-neutral template. Put it in the active project instruction file after replacing every capitalized placeholder with project facts. Store the work-list records in a separate version-controlled file, such as docs/ai/work-list.yaml.

# AI Driver Repair Contract

## Project identity

- Kernel tree: `KERNEL_TREE_URL_OR_NAME`
- Target base ref: `TARGET_BASE_REF`
- Target base commit: `FULL_TARGET_BASE_COMMIT`
- V1 series base commit: `FULL_V1_BASE_COMMIT`
- Target architecture: `ARCH`
- Baseline configuration: `CONFIG_PATH_OR_DEFCONFIG`
- Driver path: `DRIVER_PATH`
- Binding path: `BINDING_YAML_PATH`
- Current patch range: `TARGET_BASE_COMMIT..HEAD`

Before analysis, edits, checks, or review, run `base.verify`.
If the current base, tree, architecture, configuration, or patch range differs
from these values, stop with `BASE_MISMATCH`. Do not select a substitute.

## Allowed files

Always allowed:
- `CLAUDE.md` or `AGENTS.md` or `.cursor/rules/00-driver-contract.mdc`
- `docs/ai/work-list.yaml`
- `docs/ai/evidence.md`
- `docs/ai/logs/**`

For a code task, edit only paths in that task's `allowed_files` list.
Adding a file needs a written reason in the task record and required human approval.

Never modify:
- `artifacts/v1-original/**`
- `docs/ai/upstream-feedback-original/**`
- `docs/hardware-manuals/**`
- generated build output except through approved build commands
- `.git/**`
- unrelated drivers, bindings, DTS files, or shared DSA code
- remote branches, tags, or review systems

Do not rebase, reset, clean, force-push, send email, submit patches,
access physical hardware, or change the active worktree without explicit
human approval.

## Approved commands and result records

Use only commands listed in `docs/ai/commands.md`.
For every command, save:
- command ID and complete command line
- working tree commit ID and patch range
- relevant environment values
- start and end time
- complete stdout and stderr log path
- exit code

Required command IDs:
- `base.verify`
- `build.driver`
- `warn.driver`
- `checkpatch.series`
- `dt.binding`
- `dt.dtb`

Do not replace a failed command with a similar command without recording
the reason and getting approval when required.

## Evidence rules

Label claims as one of:
- `hardware_fact`
- `kernel_rule`
- `v1_observation`
- `analogy`
- `hypothesis`
- `test_result`

A hardware fact requires manual revision, exact page or section, supporting
text, and status: `clear`, `unclear`, `incomplete`, or `conflict`.

V1 behavior is not proof of correct hardware behavior.
A related driver is not proof that this hardware behaves the same way.
A successful build, schema check, or static review is not proof of runtime
or hardware correctness.

For unclear, incomplete, conflicting, or unreadable manual evidence that
affects hardware programming:
1. Do not change the hardware programming.
2. Create a `BLOCKED_HUMAN` work-list item.
3. Ask one focused question naming the decision, relevant manual passages,
   code affected, and the exact missing fact.
4. Continue only unrelated DSA or binding work that has independent evidence.

## Work-list protocol

Read and update `docs/ai/work-list.yaml` before editing code.

Each task must contain:
- stable ID and state
- source review record with original wording and patch version
- clear checkable task statement
- linked tasks or conflicts
- DSA reason and hardware relevance
- required evidence and current evidence links
- explicit assumptions and limits
- allowed files
- approved command IDs
- patch commit or patch file when complete
- reviewer reply draft and proof links
- unresolved risk or human decision, if any

Valid states:
- `NEW`
- `NEEDS_EVIDENCE`
- `READY`
- `IN_PROGRESS`
- `BLOCKED_HUMAN`
- `FIXED_AWAITING_CHECKS`
- `CLOSED`
- `REJECTED_WITH_EVIDENCE`

Only select a `READY` task. Never mark a task `CLOSED` merely because a
code edit exists. It needs the required evidence, clean required checks,
and a proposed reviewer response.

## Required agent behavior

Before editing:
1. State the selected task ID, intended smallest change, allowed files,
   required evidence, and command plan.
2. Check that the evidence is sufficient.
3. Stop for a human when a required decision is blocked.

While editing:
- Make the smallest change that addresses the selected task.
- Do not perform unrelated cleanup.
- Keep observations, facts, hypotheses, and conclusions separate.

After editing:
1. Inspect the diff against the target base.
2. Run every command required by the task.
3. Save results and link them in the work list.
4. Convert each failure or new concern into a linked task.
5. Do not claim completion if any required finding is unresolved.

## Assumptions the agent must not make

Do not assume:
- V1 hardware programming is correct.
- an analogous switch has identical registers, reset behavior, PHY behavior,
  VLAN behavior, CPU-port behavior, or interrupt behavior;
- the manual implies behavior that it does not state clearly;
- a Device Tree property is valid because the driver reads it;
- a binding example proves a compatible board design;
- a helper is available or semantically appropriate in this target kernel;
- a zero exit code proves behavior outside the command's stated scope;
- a reviewer comment is obsolete without recorded proof;
- hardware testing is enabled;
- missing evidence can be filled by a plausible guess.

When blocked, report the smallest focused human question rather than guessing.

The associated task record can be shaped like this:

- id: REV-014
  state: NEEDS_EVIDENCE
  source_review:
    thread: "URL_OR_ARCHIVE_PATH"
    patch_version: "v1, patch 3 of N"
    reviewer: "REVIEWER_NAME"
    original_wording: "VERBATIM_REVIEW_COMMENT"
  task: "State the checkable issue without changing the reviewer wording."
  links:
    related: []
    conflicts: []
    supersedes: []
  reasoning:
    dsa_reason: "Why this matters to the DSA integration."
    hardware_relevance: "none | decision that requires manual evidence"
  evidence_needed:
    - "Target-kernel source location and required call-context rule."
    - "Manual section and status, if hardware programming is involved."
  evidence_links: []
  assumptions: []
  limits: []
  allowed_files: []
  approved_commands:
    - base.verify
  result:
    patch: null
    checks: []
    reviewer_reply: null
    remaining_risk: null

Notice that allowed_files is empty while the task is still gathering evidence. That is intentional. It prevents a research task from turning into an unapproved code change.


Keep instructions short enough to be used

An instruction file loaded into every agent session is a high-value, limited context budget. Keep the root contract focused on rules that affect most tasks. Put changing data in linked records:

  • docs/ai/work-list.yaml for task state and reviewer traceability
  • docs/ai/evidence.md for manual citations, code observations, and open questions
  • docs/ai/commands.md for the exact approved commands
  • docs/ai/logs/ for immutable command outputs
  • later, tool-specific narrow rules for the driver directory or binding directory if they earn their complexity

Do not put credentials, lab addresses, tokens, private URLs, or serial-console details in the repository instruction file. Those belong in ignored local configuration and, later, an explicit hardware-test process.

Cursor’s guidance is useful here: rules should be focused, actionable, and split when they become large rather than becoming a vague handbook.


A practical acceptance check for this lesson

Before treating your project instructions as ready, perform a non-editing dry run with the agent:

  1. Ask it to identify the target base, V1 base, driver path, binding path, and current patch range.
  2. Ask it to read one upstream comment and create a NEW or NEEDS_EVIDENCE work-list item without changing code.
  3. Give it a deliberately ambiguous manual statement and confirm that it creates a focused BLOCKED_HUMAN question rather than proposing a register change.
  4. Ask what files it may modify for that task. The correct answer should be “none” until the work-list item permits them.
  5. Review git diff yourself. At this point it should contain only the instruction and record files you intentionally created.

A failure in this dry run is valuable: convert it into a precise instruction improvement. Do not respond by adding broad prose such as “be more careful.” Specify the observable rule that was missing.


The main result of this lesson is a version-controlled project contract that makes the agent’s boundaries explicit: exact kernel identity, explicit file authority, repeatable commands, evidence labels, a traceable work list, and mandatory human stops for uncertain hardware facts.

Next, you will turn the listed standard commands into one repeatable check command that captures logs and exit codes for builds, warning checks, kernel checks, and Device Tree validation.

Can't find a good explanation? Sign up and we'll make it for you

Sign up