Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
854 changes: 317 additions & 537 deletions AGENTS.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
133 changes: 133 additions & 0 deletions docs/development/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,136 @@ issue or regression

通常闭环为:问题或回归 -> 确定性刻画 -> 聚焦实现 -> 单测与 durable smoke ->
catalog 选择的 canary -> 敏感变更 owner review -> 必要时观察发布结果。

## Engineering Scope And Refactoring

Before adding a module, protocol field, CLI option, fixture or abstraction,
apply the scope-fit review below. During development and again before approval
or merge, apply the bounded refactoring pass. These are engineering decisions
within the accepted task, not additional user-approval gates.

### Bounded Future-Facing Refactoring

During development and again before approving or merging each PR, explicitly
ask whether the touched behavior or its adjacent owning boundary has a small,
related, behavior-preserving refactor that would make the next likely product
or control-plane change easier. Prefer removing duplicate authority,
strengthening typed contracts, narrowing module ownership, and retiring
obsolete compatibility seams over adding speculative frameworks. For
control-plane work, keep state-machine and effect authority in the typed
TypeScript boundary when that is the established owner; Python may adapt or
bridge that contract, but must not silently recreate a second source of truth.

Apply the refactor in the current PR when it shares the same domain or change
reason, remains locally reviewable and reversible, and is covered by
characterization or parity validation; it need not be strictly required for
the immediate fix. Do not use this principle to justify broad migration or
unrelated cleanup. When the valuable related refactor is larger than a bounded
companion change, record a focused follow-up instead. PR review and merge notes
should state whether this future-facing pass was applied, deferred, or found
unnecessary, with the concrete boundary considered.

### Scope-Fit Review

Before adding a new module, builder, protocol field, CLI option, fixture, smoke
section, or abstraction, pass a scope-fit review:

- Identify the shipped behavior, active call site, or explicit compatibility
contract that needs it. If the value is only an uncommitted future runner, a
design note, or a hypothetical extension with no validation contract, keep the
design in docs or todo state until the real call site appears.
- Prefer a cohesive behavior-preserving seam. For example, let the ledger first
recognize one compact public-safe row shape before adding a dedicated
benchmark-specific builder, arm constants, or wide field-level smoke. Do not
split so narrowly that reviewers must reconstruct one logical behavior from
several dependent PRs.
- Design tests from semantics, not observed output. Independently review the
intended invariant and legal or illegal transitions before testing the
implementation. Never derive expected results from the implementation under
test or its current output; characterization fixtures are non-authoritative,
and contradictions require rule repair plus negative or mutation coverage.
- Characterize before moving code. For status, quota, review-packet, scheduler,
monitor, and handoff behavior, add or extend parity fixtures first, then
extract the proven rule or cohesive rule group.
- Reuse existing repository patterns and bounded contexts. Add code where its
change reason belongs, such as `control_plane/runtime`, `control_plane/quota`,
or `control_plane/todos`; do not create generic sink directories or helper
layers just because several files share a similar shape.
- Treat large or hot files as warning signals. When a change would grow an
already oversized module, first look for a narrow read model, domain helper,
or bounded-context home. For internal module moves, update active call sites
and delete the old entry point; leave a compatibility wrapper only when a
real external import, persisted state, CLI/API contract, or migration window
requires it.
- Distinguish duplicate knowledge from duplicate-looking code. Collapse shared
state rules, protocol semantics, serialization contracts, and lifecycle
invariants; avoid a parameter-heavy abstraction when two callers merely look
similar but will evolve for different reasons.
- Keep smokes thin and durable. They should prove shipped behavior, boundary
enforcement, and regression contracts, not every incidental field produced by
a temporary builder. Large smokes are a prompt to move reusable logic into
product modules or to narrow the assertion surface.
- Make illegal states hard to express. For status, quota, scheduler, monitor,
todo, and handoff flows, prefer explicit enums, schemas, and transition
helpers over scattered booleans and prose-only assumptions.
- State-classification and delivery-semantics rules belong in typed enums,
schemas, or transition helpers. Substring denylists and prose heuristics must
carry a documented reason and a typed follow-up; PR review must flag them
with the concrete false-positive/negative risk.
- Core control-plane obligations and error text must stay domain-neutral. Do
not put product- or benchmark-specific wording (for example "product
advancement") into generic work-lane, quota, todo, or settlement contracts;
prefer goal-agnostic phrasing.
- Default behavior changes must be disclosed: rename the smoke that encoded the
old default, update docs/release notes, and name the affected lanes.
"Guidance" versus machine-enforced obligations (such as `must_attempt_work`)
must be explicit in the contract, not inferred from prose.
- Fail fast with actionable context at input, config, permission, and state
boundaries, but do not replace clear control flow with broad exception
plumbing or silent fallback.
- Ship right-sized, reversible batches. A PR should be theme-unified, locally
validated, and reviewable as a complete stage package. A few hundred to
roughly one or two thousand lines can be appropriate when the diff is cohesive
and avoids hidden future scaffolding; a 30-line PR can still be too small if it
leaves behavior split across follow-up PRs. Separate characterization/parity
fixtures, mechanical moves, behavior changes, and cleanup when that makes
review and rollback clearer.
- Keep public PRs concise and current-purpose focused. Future extension points
are allowed when they reduce near-term churn, preserve compatibility, or
define a real contract that is documented and tested. Do not bundle
private/local experiment scaffolding, diagnostic run dumps, unused speculative
plumbing, or long background narratives with the code path needed by the
current behavior.
- Compress rather than append. For docs, fixtures, dashboards, and examples,
replace or retire stale material when adding new current truth; do not let
canonical surfaces accumulate multiple versions of the same conclusion.

Use this checklist to delete, defer, or right-size code as actively as you add
it. A PR that removes an unused abstraction, narrows a smoke to the real
contract, or moves a rule into the right bounded context is often more valuable
than one that adds a larger framework around the same behavior.

## Agent Instruction Loading And Maintenance

The repository shares one policy entry: `AGENTS.md` for Codex and the explicit
`@AGENTS.md` import in `CLAUDE.md` for Claude Code. Keep the import single-source;
a prose request to read the file does not ensure startup loading. Do not eagerly
import the detailed procedures: read their linked owner when its task applies.

Codex's default `project_doc_max_bytes` is 32 KiB across discovered instructions.
The root regression checks that this file fits, but ancestor instructions, nested
files and user overrides still require a host-specific loading check. Claude's
import/discovery settings have different semantics; 32 KiB is not a universal
Claude limit. Inspect actual startup context after changing the entry or its
alias, and distinguish assembled text from model compliance and live effects.
Existing sessions may retain an older copy.

Run `uv run --extra test python -m pytest -q tests/test_repository_instruction_delivery.py`
for root size, shared import, local routes and existing inbound anchors. Review
a moved obligation clause by clause: owner, modality, scope, order, exceptions,
evidence provenance, continuation and stop conditions. A link test or shorter
file does not establish equivalence. Keep operational rules in their existing
owners rather than adding another parallel policy collection.

Design sources and the disposition of the earlier proposal are recorded in
[the instruction/skill/prompt study](../research/2026-10-17-agent-instruction-skill-prompt-guidance.md).
43 changes: 43 additions & 0 deletions docs/development/good-smokes.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,42 @@ evidence.
不要仅因 integrated smoke 很慢就删除它。应先测量成本来自哪些阶段,并证明较小测试
覆盖同一端到端边界;只要它仍提供独有证据,就应保留。

When a smoke grows beyond roughly 500 lines, re-check whether it is really one
test. This is a review prompt, not an automatic deletion or failure threshold.
Move reusable behavior into its product owner and keep the smoke thin. Large
integration smokes remain appropriate when smaller tests cannot cover their
real end-to-end adapter contract.

Do not retain one-off smokes whose main purpose is to assert the exact text of
a dated research note, candidate ranking packet, temporary run review, or
transitional benchmark decision. Keep that information in the research document
and cover shared invariants with a data-driven aggregate smoke.

Smoke 超过约 500 行时,应重新检查它是否混合了多个测试;这不是自动删除或失败阈值。
将可复用行为放回产品 owner,使 smoke 保持轻量;较小测试无法覆盖真实端到端 adapter
合同时,仍可保留大型 integration smoke。不要用一次性 smoke 固化过期研究笔记、候选
排名、临时运行评估或阶段性 benchmark 决策的精确文案;这些信息留在研究文档,共有
不变量交给数据驱动的聚合 smoke。

### Benchmark Boundaries

Keep focused public/private boundary smokes such as
`examples/benchmark-candidate-source-boundary-smoke.py`, and toolkit permission
and integrity smokes while they validate the shipped provider-neutral contract.
Add active benchmark smokes only for stable toolkit behavior; experiment-specific
validation belongs with the research workspace. Benchmark-native runners,
adapters, ledgers, scoring reducers and dated packets stay outside the active
product surface. Follow [archive placement](../../benchmark/README.md#archive-placement):
retired implementations and dated packets belong under `deprecate/benchmark-legacy/`;
only the explicitly qualified immutable snapshots may remain under `benchmark/`.
Neither archive category enters active CI benchmark execution.

保留公开/私有边界,以及已交付 provider-neutral toolkit 权限和完整性 smoke。
新增 active benchmark smoke 只保护稳定 toolkit 行为,实验专属验证归研究工作区。
Benchmark-native runner、adapter、ledger、scoring reducer 和过期 packet 不进入活跃
产品面;退役实现和过期 packet 归 `deprecate/benchmark-legacy/`,满足规范条件的不可变
快照才可留在 `benchmark/`。两类归档都不参与 active CI benchmark 执行。

## Public-Safe Fixtures / 公开安全 Fixture

Use temporary repositories, fake transports, synthetic records, and compact
Expand All @@ -131,6 +167,13 @@ smoke touches benchmark, host, agent, or external-system data.
当 smoke 接触 benchmark、host、agent 或外部系统数据时,遵循
[公开/私有边界](../public-private-boundary.md)。

Benchmark smokes must never require raw task text, trajectories, logs, verifier
output tails, credentials, uploads, leaderboard submissions, or local private
artifact paths.

Benchmark smoke 不得依赖原始任务文本、trajectory、日志、verifier 输出 tail、凭证、
上传、leaderboard 提交或本地私有 artifact 路径。

## Validate The Change / 验证变更

Run the narrowest meaningful checks first, then add risk-based coverage:
Expand Down
17 changes: 12 additions & 5 deletions docs/guides/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ already exists, reuse it and do not create or overwrite a goal or the active obj
is not connected, prefer `loopx connect`, and use `loopx bootstrap` only when
project state clearly needs initialization. Ensure `.loopx/`, `.loopx/goals/`,
and `.local/` are ignored. Keep me in this TUI, do not use hidden headless
execution. After the project is connected, generate the thin heartbeat prompt
and set the current Codex CLI task body with `/goal <thin task_body>`. Then
execution. After the project is connected, generate the host-specific bootstrap loader with `heartbeat-prompt --bootstrap --thin --runtime-profile codex_cli`
and set the current Codex CLI task body with `/goal <loader task_body>`. Then
stop and report the active state id, current user gate, top agent todo, and
next safe action.
```
Expand All @@ -262,11 +262,18 @@ show the current state id, concrete user gate if one exists, top user todo if
any, top agent todo, and next safe action before longer delivery work. The
setup turn should not spend quota for delivery unless the user explicitly asks
it to do delivery in the setup turn. The agent should still generate
`heartbeat-prompt --thin` and install that body into the surface during setup:
Codex CLI gets `/goal <thin task_body>`, while Codex App gets a heartbeat
`heartbeat-prompt --bootstrap --thin --runtime-profile codex_cli` and install that body into the surface during setup:
Codex CLI gets `/goal <loader task_body>`, while Codex App gets a heartbeat
automation body that starts at 3 minutes and then follows
`scheduler_hint`.

The CLI loader binds `codex_cli`; App automation uses its own
`heartbeat-prompt --bootstrap --thin --codex-app` loader. Each loads current
instructions on entry. Never reuse the CLI guard for an App wake, freeze a Turn
identity, or save today's execution body as the permanent prompt. Apply a new
loader through the authorized host update and read it back; source changes alone
do not migrate existing automations. Existing authority and cadence floors remain.

Once `loopx` is installed, generate a stricter repo-specific setup
message:

Expand All @@ -277,7 +284,7 @@ loopx codex-cli-bootstrap-message --project . --goal-id <goal-id>
Keep that as the preferred interactive path: the human watches and steers in
Codex CLI TUI, while LoopX owns quota/status/todos/gates/writeback. The
generated packet also shows the no-clone install-repair command, the
post-bootstrap thin prompt generation command, and a transcript-free validation
host-specific bootstrap loader commands, and a transcript-free validation
checklist, so a fresh repo path can be reviewed without touching raw Codex
session data.

Expand Down
Loading
Loading