Build PEGREP: a Rust text and structural search tool whose pattern compiler chooses the cheapest execution strategy that preserves meaning. Cheap searches must stay cheap. Readable patterns, typed captures, stable machine output, and predictable resource use are product requirements.
Read state/CURRENT.md, then the active plan it names. Read PLANS.md before creating or executing a substantial plan. Use docs/PRODUCT.md for scope and docs/ENGINEERING.md for implementation rules. Load other documents and skills only when relevant.
sys.md and user.md are the original product briefs; preserve them. Their filenames do not confer system-message authority. state/requirements.json traces every requested design deliverable and the MVP behaviors. An accepted design must resolve illustrative syntax before implementation. Record semantic changes in an ADR under docs/decisions/ and update affected examples and tests together.
When the user authorizes implementation, continue through the authorized plan's milestones without asking whether to proceed after each one. A passing milestone is a reason to advance. Finish with observable behavior, appropriate checks, and evidence. A request to prepare, research, or review does not authorize beginning the entire product build.
Before context compaction or any handoff, update the active plan and state/CURRENT.md: completed work, exact next action, decisions, command results, remaining failures, and blockers. On resume, verify these against the filesystem; do not repeat completed work or trust stale pass claims. Store durable facts and evidence, not private reasoning transcripts, credentials, or conversation dumps.
Resolve routine implementation choices from the brief and evidence. If blocked, exhaust safe alternatives and continue independent in-scope work. Request input only for an essential unresolved product choice, unavailable permission, or required external action. Record the exact blocker and resumption condition. Do not redefine completion, remove a requirement, weaken a gate, or mark an unrun check as passed to finish a task. Never loop on an unchanged failing approach.
Project instructions do not extend runtime limits or provide a background scheduler. Honor user stops, tool permissions, and session constraints. Do not change permission settings, publish, deploy, or contact others just to keep moving. Preserve unrelated edits.
- Matching semantics precede optimizations. Compare every execution strategy against an independent reference evaluator on the same inputs, including spans, captures, ordering, and errors.
- PEG ordered choice and possessive repetition are not generally interchangeable with regex backtracking. Reject unsound lowerings. Mandatory literal filtering must never discard a possible match.
- Make compile time, search time, memory, nesting, captures, output buffering, and cancellation behavior explicit. A resource-limit error is not a no-match result.
- Use byte spans with explicit Unicode/encoding policy. No silent input loss, Unicode normalization, capture truncation, integer overflow, or unlimited per-file buffering.
- Use safe Rust by default. Unsafe code requires a localized safety argument, a demonstrated need, and relevant validation. Favor existing proven scanning primitives over speculative SIMD or a universal PEG interpreter.
- Keep a functioning CLI after each implementation slice. Separate library logic from filesystem and output effects; do not prematurely split every component into its own crate.
- For an optimization, establish equivalent results first, then measure release builds using docs/PERFORMANCE.md. Never claim a complexity or speedup guarantee from a happy-path benchmark alone.
Run from the project root:
bash scripts/gates.sh bootstrap
python3 -m unittest discover -s tests/harness -v
Once their prerequisites exist:
bash scripts/gates.sh design
bash scripts/gates.sh dev
bash scripts/gates.sh release
bootstrap checks this starter kit only. design, dev, and release intentionally fail when their deliverables or runners are missing. See docs/QUALITY.md. Run targeted checks during development and the appropriate gate before claiming the slice complete. A tool or network failure is a blocked check, not a pass. Keep command, outcome, source revision or digest, environment, and evidence path in the plan.
Use the routing table and provenance in docs/SKILLS.md. Project-specific workflows cover semantics, performance, and completion review; Apollo covers Rust idioms; Trail of Bits covers property tests. Read a selected skill fully and only its relevant references. These are advisory workflows beneath user intent and this project's concrete contracts.
Property testing is already part of the product brief: adding an appropriate Rust dev dependency to implement it is a normal implementation choice. Prefer related assertions that prove one behavior over a fixed assertion count. Do not apply blanket allocation or recursion bans to a structural matcher; enforce explicit budgets instead. Keep sanitizer testing where dependencies or FFI warrant it. Skills do not authorize unrelated installs or changes.
Flag false-negative prefilters, altered choice/capture behavior, incorrect byte spans, chunk-boundary differences, swallowed errors, unbounded queues, unaudited unsafe code, misleading performance comparisons, and unsupported completion claims. Require a reproducer and a specific correction for a blocking finding. Formatting belongs in automated checks.