diff --git a/.dsh/skills/engineer-software/SKILL.md b/.dsh/skills/engineer-software/SKILL.md new file mode 100644 index 0000000..3093d43 --- /dev/null +++ b/.dsh/skills/engineer-software/SKILL.md @@ -0,0 +1,70 @@ +--- +name: engineer-software +description: >- + Route substantive software engineering work through the smallest evidence-driven workflow: + close unclear requirements or plans, trace an unknown failure, run a disposable decision probe, + deliver and verify a defined code change or refactor, inspect structural redundancy, or draft + local work items. Use when software behavior, diagnosis, architecture, implementation, or + acceptance evidence materially matters. Do not use for ordinary explanations, simple code + reading, translation or formatting, or mechanical file and Git operations whose method and + outcome are already clear. +--- + +# Engineer Software + +Use the least workflow that can produce a trustworthy outcome. The modules below are +alternative starting modes, not phases that every task must traverse. + +## Operating contract + +1. Read repository instructions and inspect existing user changes before any edit. +2. Check the bypass boundary before choosing a module. +3. Select the first module from the user's current uncertainty, not from the eventual task type. +4. Read exactly one primary module before acting. Do not pre-read other modules for completeness. +5. Stay in that module until it finishes or its exit evidence proves another module is necessary. +6. Before a transition, state the evidence that closed the current module and the unresolved need + the next module must handle. Then return here and read only that next module. +7. Bind completion claims to fresh evidence from the final relevant state. Label manual, missing, + flaky, or environment-dependent evidence instead of calling it a pass. +8. Never repeat a module or traverse a cycle without new evidence. Stop with the unresolved blocker + when another pass would only repeat questions, probes, or patches. + +## Bypass + +Bypass this workflow and answer or act directly for factual explanations, code reading, +translation, formatting, obvious text corrections, specified reversible file operations, and +explicitly authorized mechanical Git operations. Upgrade into a module only if inspection reveals +a material software decision, unknown cause, structural risk, or nontrivial acceptance burden. + +## Choose the first module + +| Current need | Read | +| --- | --- | +| Outcome, behavior, scope, compatibility, or plan is materially unresolved | [Shape work](references/shape-work.md) | +| A reported symptom exists but its cause or failure mechanism is unknown | [Trace failure](references/trace-failure.md) | +| One bounded design or interaction question needs a disposable experiment | [Probe choice](references/probe-choice.md) | +| Production behavior and edit scope are closed enough to change and verify | [Deliver change](references/deliver-change.md) | +| The task is to find or assess architecture, design, policy, or implementation redundancy | [Inspect structure](references/inspect-structure.md) | +| The requested output is a local PRD, task breakdown, or triage draft | [Manage work items](references/manage-work-items.md) | + +## Tie breakers + +- Route an unknown cause to `trace-failure`, even when the user also asks for a fix. +- Route a known cause with a closed fix boundary directly to `deliver-change`. +- Route an assessment of structure to `inspect-structure`; route an already-approved structural + change to `deliver-change`, which still applies its conditional structure gate. +- Use `probe-choice` only when an experiment can resolve a named decision. It is never a routine + pre-implementation stage. +- For a mixed request, start with the earliest unresolved condition that can invalidate later work. + Skip `shape-work` when the request and repository already close the contract. +- Keep work-item output local or in the conversation. Remote publication is outside this skill. + +## Shared boundaries + +- Preserve pre-existing work and stay inside the requested scope. +- Inspect facts that are cheap to obtain before asking the user. Ask only when the answer can + change visible behavior, compatibility, data, security, external state, or task scope. +- Do not add speculative abstractions, options, interfaces, migration lanes, or coordination + machinery. +- Do not commit, push, publish, deploy, or mutate remote systems unless the user separately and + explicitly authorizes that action. diff --git a/.dsh/skills/engineer-software/references/deliver-change.md b/.dsh/skills/engineer-software/references/deliver-change.md new file mode 100644 index 0000000..b06b7a0 --- /dev/null +++ b/.dsh/skills/engineer-software/references/deliver-change.md @@ -0,0 +1,57 @@ +# Deliver Change + +Make the smallest sufficient production change and prove the final state. + +## Enter + +Use this module when the intended outcome, protected behavior, edit scope, and acceptance evidence are +closed enough to implement. Carry forward an established reproduction or decision contract instead of +restarting discovery. Return to `trace-failure` when the cause is still unknown. + +## Execute + +1. Inspect repository rules, the working tree, nearby tests, public contracts, and affected callers. + Preserve changes that predate the task. +2. Establish before-change evidence at the cheapest decisive seam: + - changed behavior: a focused check rejects the desired behavior for the expected reason; + - defect: the real symptom reproduces; + - behavior-preserving refactor: characterization or affected checks pass first; + - performance: a repeatable baseline and target exist; + - configuration or generated output: a parser, schema, build, snapshot, or smoke check exists. +3. Apply the conditional **structure-risk gate** only when the change adds or moves a module, + interface, policy, validation rule, state owner, data representation, adapter, migration lane, + broad responsibility, or copied nontrivial logic. Search for the existing owner, comparable + capability, and real callers. + Then check: + - extend the authoritative owner instead of creating a parallel implementation; + - keep policy, validation, state, and data representation single-sourced; + - require wrappers and public interfaces to remove more complexity than they expose; + - preserve dependency direction and avoid cycles or permanent dual paths; + - give compatibility or migration paths an explicit end state and removal condition. + Skip the full gate for a narrow local edit once ownership is obvious. If the gate cannot be judged + locally, stop and enter `inspect-structure`. +4. Change one independently verifiable behavior slice at a time. For new or changed behavior, write + or strengthen the decisive check before production code when a correct seam exists, observe the + expected failure, implement only enough to pass, and inspect the actual result. +5. Refactor only to remove evidenced duplication, leakage, or accidental complexity needed by the + current change. Do not add speculative flags, factories, interfaces, extension points, or future + behavior. +6. Re-run direct evidence after every later edit that can affect it. Then run affected checks and + only the broader build, type, lint, schema, compatibility, or end-to-end checks justified by risk. +7. Inspect the final diff for scope drift, user-work damage, debug probes, disabled checks, stale + dual paths, accidental generated output, and new responsibilities with no clear owner. + +When no correct automated seam exists, use the strongest honest behavioral or manual evidence and +report the missing seam; do not add a shallow test that cannot observe the real contract. + +## Exit + +- If the structure-risk gate cannot establish an owner or safe boundary, stop before the structural + edit, report the uncertainty, and enter `inspect-structure`. +- If evidence invalidates the assumed cause, stop stacking patches and enter `trace-failure`. +- If evidence invalidates the product or compatibility contract, enter `shape-work`. +- Otherwise report the changed behavior and scope, decisive starting evidence, fresh final + verification with exact outcomes, structural-gate result when it ran, and any pre-existing failure + or remaining uncertainty. + +Commit, push, publish, or deploy only when separately authorized. diff --git a/.dsh/skills/engineer-software/references/inspect-structure.md b/.dsh/skills/engineer-software/references/inspect-structure.md new file mode 100644 index 0000000..fc7f67d --- /dev/null +++ b/.dsh/skills/engineer-software/references/inspect-structure.md @@ -0,0 +1,45 @@ +# Inspect Structure + +Find architecture, design, policy, and implementation redundancy with code evidence. + +## Enter + +Use this module for a read-only structural audit or when a local change cannot establish the correct +owner or abstraction boundary. Do not treat aesthetic preference, file count, or unfamiliarity as a +finding. Implementation is out of scope until the user accepts a change boundary. + +## Execute + +1. Define the inspected subsystem, user-visible behavior, protected contracts, and evidence needed + for a credible finding. Read relevant domain terms and decision records before judging intent. +2. Trace responsibilities from public entry points through callers, dependencies, data ownership, + state transitions, and tests. Identify the current authoritative owner for each rule or concept. +3. Look for evidenced candidates: + - duplicate responsibility, policy, validation, state, or data representation; + - parallel implementations or adapters with no distinct contract; + - pass-through wrappers or public interfaces that expose as much complexity as they hide; + - knowledge scattered across callers, dependency cycles, or ownership leakage; + - permanent old/new paths, dead adapters, or configuration that preserves two sources of truth; + - tests forced onto private helpers because no stable behavioral seam exists. +4. For each candidate, cite paths, symbols, callers, and observable maintenance or correctness cost. + Apply a deletion or merge thought experiment: say where the complexity would go and whether the + result concentrates ownership or merely moves code. +5. Exclude or qualify intentional duplication before reporting it: + - migration or compatibility paths with a documented end condition; + - real platform or deployment differences; + - generated code, vendor code, fixtures, snapshots, and protocol mirrors; + - security, safety, or fault isolation; + - measured performance-critical duplication; + - an explicit architecture decision record whose trade-off still applies. +6. Rank only surviving findings by evidence, user impact, change leverage, and reversibility. For each, + recommend keep, merge, delete, re-home, or investigate; include blast radius and verification needs. + +Prefer a concise evidence table or prose report. Generate diagrams or a separate visual artifact only +when relationships are otherwise hard to understand or the user requests one. + +## Exit + +- If no candidate survives the false-positive checks, say so and identify the inspected boundary. +- Report findings without changing production structure. +- Before a system-level refactor, obtain user confirmation of the selected finding and boundary. + Then enter `shape-work` if behavior or compatibility remains open; otherwise enter `deliver-change`. diff --git a/.dsh/skills/engineer-software/references/manage-work-items.md b/.dsh/skills/engineer-software/references/manage-work-items.md new file mode 100644 index 0000000..77fd87f --- /dev/null +++ b/.dsh/skills/engineer-software/references/manage-work-items.md @@ -0,0 +1,35 @@ +# Manage Work Items + +Turn known context into reviewable local planning and triage artifacts. + +## Enter + +Use this module when the requested deliverable is a local PRD, vertical task breakdown, acceptance +brief, or triage draft. It does not discover an unknown failure or publish work to a remote tracker. + +## Execute + +1. Use the current conversation, repository evidence, domain vocabulary, accepted decisions, and + supplied issue text. Inspect missing facts only when they can change the draft. +2. Choose the smallest requested artifact: + - PRD: problem, outcome, users, behavior, constraints, acceptance, decisions, and exclusions; + - tasks: thin end-to-end slices, acceptance checks, dependencies, and human decision points; + - triage: type, current evidence, reproduction status when relevant, missing information, proposed + state, and a durable implementation brief when ready. +3. Keep requirements observable and tasks independently verifiable. Prefer vertical slices that + deliver a narrow complete behavior over layer-by-layer work packages. +4. Mark assumptions, unresolved product or architecture choices, and external prerequisites. Do not + label a task autonomous when it still depends on an unstated human decision. +5. Return the local draft in the conversation or write it only to a user-selected repository path. + Preserve parent material and avoid duplicating an existing authoritative plan. + +Do not publish, comment, label, close, or mutate any remote tracker. If the user asks for remote +publication, prepare the reviewable draft and state that publication requires a separate explicitly +authorized workflow outside this skill. + +## Exit + +Report the artifact location or inline draft, source evidence, dependencies, unresolved decisions, +and the acceptance rule that makes each item ready. Stop after the requested artifact. If the user +also requested implementation and the first executable slice is closed, return to the router and +enter `deliver-change` for that slice only. diff --git a/.dsh/skills/engineer-software/references/probe-choice.md b/.dsh/skills/engineer-software/references/probe-choice.md new file mode 100644 index 0000000..92894bd --- /dev/null +++ b/.dsh/skills/engineer-software/references/probe-choice.md @@ -0,0 +1,34 @@ +# Probe Choice + +Use throwaway code to answer one decision, then remove the experiment. + +## Enter + +Use this module only when a named logic, state, data-model, feasibility, performance, or interaction +question can be resolved more cheaply by running a bounded experiment than by discussion. A probe is +not a draft production implementation. + +## Execute + +1. State the question, competing outcomes, observation method, stop condition, and decision each + possible result would support. +2. Place the probe where its context is clear but mark it unmistakably disposable. Avoid changing + production paths unless the experiment specifically requires a controlled integration seam. +3. Build the minimum runnable slice. Reuse the repository's runner and dependencies; avoid new + persistence, abstractions, error frameworks, generalized options, or polish. +4. Make relevant state and results visible. Keep inputs fixed when comparing alternatives and use + one command or scenario to repeat the observation. +5. Run the probe and record the result, uncertainty, and decision consequence. A runnable artifact + without an observed result is not evidence. +6. Delete the probe after it answers the question, or retain it only with explicit user agreement + and a clear expiry. Capture the decision in the requested durable artifact when one exists. + +Do not promote a disposable implementation by renaming it. Reimplement the accepted behavior under +production constraints and tests. + +## Exit + +- If the result closes implementation, return to the router and enter `deliver-change`. +- If the result changes or leaves open the intended behavior, enter `shape-work`. +- If the experiment uncovers an unexplained failure, enter `trace-failure`. +- Otherwise report the answered question, observation, decision, and cleanup state. diff --git a/.dsh/skills/engineer-software/references/shape-work.md b/.dsh/skills/engineer-software/references/shape-work.md new file mode 100644 index 0000000..f62c2d6 --- /dev/null +++ b/.dsh/skills/engineer-software/references/shape-work.md @@ -0,0 +1,38 @@ +# Shape Work + +Close only the decisions that can invalidate implementation or its acceptance. + +## Enter + +Use this module when the intended behavior, scope, compatibility boundary, success condition, +or decision path is materially unresolved. Do not enter merely because a task is large. + +## Execute + +1. Inspect the current repository behavior, instructions, domain vocabulary, decision records, + public contracts, and nearby conventions that can answer the open questions. +2. Frame the work in observable terms: user or system outcome, affected surface, constraints, + non-goals, acceptance evidence, and irreversible or externally visible choices. +3. Separate confirmed facts, evidence-backed inferences, safe reversible defaults, and decisions + that genuinely require the user. +4. Stress-test uncertain behavior with concrete examples, boundary cases, failure cases, and + compatibility scenarios. Prefer a small example over abstract debate. +5. Ask at most one to three independent blocking questions together. Ask dependent questions + only after their prerequisite is resolved. Include a recommendation when evidence supports one. +6. Record a durable architecture decision only when the choice is hard to reverse, surprising + without context, and the result of a real trade-off. Otherwise keep the decision with the work. +7. Produce the smallest sufficient contract: outcome, scope, protected behavior, constraints, + acceptance checks, and remaining explicit exclusions. + +Do not force an interview, a repository map, multiple candidate plans, or a document artifact. +Stop shaping as soon as the next action is safe and testable. + +## Exit + +- If the user requested only a decision or plan, return the contract and its unresolved risks. +- If implementation is ready, return to the router and enter `deliver-change`. +- If a named uncertainty is best answered by a disposable experiment, enter `probe-choice`. +- If a symptom still lacks a cause, enter `trace-failure`. +- If the desired output is a PRD or task set, enter `manage-work-items`. + +Exit evidence is a closed outcome and acceptance boundary, not agreement that every detail is known. diff --git a/.dsh/skills/engineer-software/references/trace-failure.md b/.dsh/skills/engineer-software/references/trace-failure.md new file mode 100644 index 0000000..ff2619a --- /dev/null +++ b/.dsh/skills/engineer-software/references/trace-failure.md @@ -0,0 +1,43 @@ +# Trace Failure + +Find an evidenced cause before editing production behavior. + +## Enter + +Use this module for a bug, exception, failing check, intermittent symptom, or performance regression +whose cause or failure mechanism is not yet established. If the cause and change boundary are already +known, use `deliver-change` instead. + +## Execute + +1. Build the cheapest decisive feedback signal at the smallest stable seam: a focused test, command, + request replay, browser scenario, trace replay, benchmark, or bounded harness. +2. Reproduce the user's exact symptom. Distinguish a failing assertion from broken setup and record + pre-existing unrelated failures separately. +3. Minimize the reproduction while preserving the failure. Raise the reproduction rate before + debugging a flaky case; control time, randomness, concurrency, or inputs when possible. +4. Form only the competing hypotheses the evidence justifies. Rank them by observed facts and give + each a falsifiable prediction. Do not require a ceremonial fixed count. +5. Test one prediction or causal variable at a time. Prefer a debugger or targeted boundary probe; + tag temporary instrumentation so it can be found and removed. +6. For performance, establish a repeatable metric and baseline before changing code. Use profiling, + query plans, or bisection rather than general logging. +7. Confirm the cause by showing that it predicts the symptom and that a controlled change or probe + removes or alters the symptom as expected. Check a plausible alternative when confusion remains. +8. Remove temporary instrumentation and retain the minimized reproduction as regression evidence + when it exercises the real failure path. + +When debugging an agent or live process, do not ingest an actively written transcript or event log +wholesale. Use bounded tails, time filters, completed runs, external logs, or a stable copied snapshot +so the observation cannot recursively consume its own output. + +If no reliable signal can be built, stop with the exact attempts and request the smallest missing +artifact or access: logs, trace, fixture, environment, or permission for bounded instrumentation. +Do not fill the gap with speculation. + +## Exit + +- Report the reproduced symptom, causal evidence, affected boundary, and ruled-out alternatives. +- If the user requested a fix and its scope is now closed, return to the router and enter + `deliver-change`, carrying the reproduction as baseline evidence. +- If the cause exposes a broader unresolved design choice, enter `shape-work` before implementation. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cbdd88..44b1966 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,8 +23,6 @@ jobs: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - cache: pip - cache-dependency-path: requirements-dev.txt - name: Install validation dependency run: python -m pip install -r requirements-dev.txt - name: Validate public plugin package diff --git a/.gitignore b/.gitignore index 40629ce..591da62 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,8 @@ venv/ Thumbs.db evals/runs/ dist/ + +# DeepSeek Harness runtime state is local; the checked-in skill projection is intentional. +.dsh/* +!.dsh/skills/ +!.dsh/skills/** diff --git a/CHANGELOG.md b/CHANGELOG.md index dddddca..15f9e19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,13 @@ All notable changes to Engineer Software are documented here. ## [Unreleased] -No unreleased changes. +- Reframed the project as a runtime-neutral workflow with Codex and DeepSeek Harness entry points. +- Added a checked, generated `.dsh/skills` projection, static Harness compatibility probe, shared + runtime parity tests, compatibility/install guidance, and a deterministic dual-runtime diagram. +- Added a non-branded engineering cover asset and copy-ready launch guidance without official + endorsement or adoption claims. +- Disabled the CI `setup-python` pip cache because the repository has no cache dependency contract; + the existing Python matrix and validation gates remain unchanged. ## [0.1.0] - 2026-08-13 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fff76a7..6398497 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,8 @@ # Contributing -Contributions should preserve the plugin's thin-router, one-primary-module contract. +Contributions should preserve the runtime-neutral thin router and one-primary-module contract. +Codex is the marketplace entry; DeepSeek Harness consumes the generated project skill projection. +Do not hand-edit or duplicate the workflow under `.dsh/skills/`. ## Development setup @@ -13,6 +15,18 @@ python -m pip install -r requirements-dev.txt Before editing, inspect the worktree and the affected route's `Enter`, `Execute`, and `Exit` contracts. Add or strengthen the focused case before changing routing behavior. +The editable source is only `plugins/engineer-software/skills/engineer-software/`. After changing +`SKILL.md` or a reference, regenerate and check the Harness projection: + +```powershell +python scripts/sync_harness_skill.py --write +python scripts/validate_harness.py --check +``` + +The official Harness integration is project-local `.dsh/skills//SKILL.md` plus relative +resources. Harness is a developer preview; do not invent a remote manifest, claim live API coverage, +or describe the project as an official DeepSeek plugin. + ## Required checks ```powershell @@ -21,12 +35,17 @@ python scripts/validate_evals.py python scripts/validate_project.py python -m unittest discover -s tests -v python -m compileall -q scripts tests +python scripts/validate_harness.py --check ``` For routing changes, add a self-contained case with expected activation, route, result shape, and fixture. Keep every documented transition represented in `evals/routing-cases.json`. Live model evidence belongs under ignored `evals/runs/`, never in a release commit. +The CI workflow intentionally leaves `actions/setup-python` pip caching disabled. This repository +has no `requirements.txt` or `pyproject.toml` cache contract; `requirements-dev.txt` is installed +explicitly for validation. + ## Release policy 1. Keep the manifest version valid SemVer and use at most one `+codex.` suffix. @@ -36,4 +55,3 @@ evidence belongs under ignored `evals/runs/`, never in a release commit. creates the GitHub release. 5. Submit the same final skill tree to the OpenAI plugin portal. Policy attestations and final publication remain explicit publisher actions. - diff --git a/README.md b/README.md index 692cf87..cbf7064 100644 --- a/README.md +++ b/README.md @@ -2,51 +2,44 @@ [![CI](https://github.com/KirschBluteX/engineer-software/actions/workflows/ci.yml/badge.svg)](https://github.com/KirschBluteX/engineer-software/actions/workflows/ci.yml) -Engineer Software is a skills-only Codex plugin that routes substantive software work through one -focused, evidence-driven module at a time. It is designed to avoid both process inflation and the -architectural duplication that can be introduced by an otherwise correct fix or refactor. +**A runtime-neutral, evidence-driven software engineering workflow for AI coding agents.** -## Design +Engineer Software helps an agent choose the smallest trustworthy next move: close an unclear +contract, trace an unexplained failure, run one disposable probe, deliver a defined change, inspect +structural redundancy, or draft local work items. Codex and DeepSeek Harness are two first-class +loading paths over one canonical skill source; the workflow semantics and evidence fixtures stay +shared. -The entry skill is intentionally thin. Codex first sees its metadata, reads `SKILL.md` only when the -skill applies, and then loads exactly one detailed reference for the current uncertainty. +![Engineer Software runtime-neutral workflow cover showing Codex and DeepSeek Harness feeding one canonical skill into evidence verification](plugins/engineer-software/assets/engineer-software-cover.png) -```mermaid -flowchart LR - R["Thin SKILL.md router"] --> S["Shape work"] - R --> F["Trace failure"] - R --> P["Probe choice"] - R --> D["Deliver change"] - R --> I["Inspect structure"] - R --> W["Manage work items"] - S -. "exit evidence" .-> R - F -. "exit evidence" .-> R - P -. "exit evidence" .-> R - D -. "only if structure is unclear" .-> I -``` +![Dual-runtime shared-core flow](docs/assets/runtime-neutral-flow.svg) -The six modules are alternatives, not a mandatory pipeline: +## 30-second overview -| Module | Use it when | -| --- | --- | -| Shape work | Behavior, scope, compatibility, or acceptance is materially unresolved. | -| Trace failure | A symptom exists but the cause or mechanism is unknown. | -| Probe choice | A disposable experiment can answer one named decision. | -| Deliver change | The production outcome and edit boundary are ready to implement and verify. | -| Inspect structure | Evidence is needed for duplicated ownership, policy, state, or implementation. | -| Manage work items | The output is a local PRD, task set, or triage draft. | +1. The thin router checks whether the request is ordinary work or has material engineering + uncertainty. +2. It starts exactly one primary module and records the evidence needed to leave that module. +3. A later module is entered only when fresh evidence closes the current module and identifies a + different need. +4. The same `SKILL.md`, references, and routing cases are available to both runtimes. -Clear explanations and mechanical reversible operations bypass the workflow. Transitions occur only -after the active module produces evidence that identifies a different unresolved need. +```mermaid +flowchart LR + C["Canonical source\nSKILL.md + references"] --> X["Shared evals\nrouting-cases.json"] + C --> D["Codex entry\nplugin.json + marketplace"] + C --> H["Harness entry\n.dsh/skills projection"] + D --> E["Same evidence\nand module semantics"] + H --> E +``` -GitHub is a distribution target, not a runtime route. The workflow has no GitHub branch, MCP server, -hook, telemetry process, hidden state machine, or external issue-tracker action. Work-item output -stays local unless a separate explicitly authorized workflow publishes it. See [PRIVACY.md](PRIVACY.md) -for the shipped data boundary. +The projection is generated and checked; it is not a second hand-maintained workflow. See +[runtime compatibility](docs/compatibility.md) for the official Harness sources and the preview +status. The deterministic flow diagram is also available as +[SVG](docs/assets/runtime-neutral-flow.svg) for Markdown renderers without Mermaid support. -## Install for the current user +## Quick start -Add the public Git repository as a marketplace, then install the plugin: +### Codex ```powershell codex plugin marketplace add KirschBluteX/engineer-software @@ -54,55 +47,140 @@ codex plugin add engineer-software@engineer-software codex plugin list ``` -Start a new Codex task after installation so the new skill catalog is loaded. Invoke the plugin -explicitly with `$engineer-software`, or let Codex select it when a request matches the bounded skill -description. - -To update an existing installation: +Start a new task after installation, then ask for a substantive software change or invoke +`$engineer-software`. Upgrade with: ```powershell codex plugin marketplace upgrade engineer-software codex plugin add engineer-software@engineer-software ``` -## Validate +Remove it with the installed Codex plugin manager and confirm with `codex plugin list`. The existing +Codex marketplace manifest and plugin path remain unchanged. + +### DeepSeek Harness + +DeepSeek Harness is an official open-source project, currently marked **developer preview**. Its +official local skill provider scans project `.dsh/skills` roots. This checkout includes a generated +projection of the canonical skill: + +```powershell +python scripts/sync_harness_skill.py --check +python scripts/validate_harness.py --check +npx @deepseek-ai/dsh web +``` + +Choose this repository as the Harness workspace and send a software-engineering request. To update +the projection after a canonical edit, run `python scripts/sync_harness_skill.py --write`; to remove +the project-local entry, remove the generated `.dsh/skills/engineer-software/` directory. A user-global +copy can target `$DSH_HOME/skills/engineer-software`; exact install and troubleshooting details are +in [runtime compatibility](docs/compatibility.md). + +There is deliberately no guessed Harness manifest or claim of DeepSeek endorsement. The official +bundle format is for executable Cordis composition layers; a Markdown skill is correctly loaded from +the documented filesystem root. Live Harness/API behavior is not claimed as verified here. + +## What it routes + +| Primary module | Start when | Evidence to leave it | +| --- | --- | --- | +| Shape Work | behavior, compatibility, scope, or acceptance is open | smallest sufficient contract and exclusions | +| Trace Failure | a symptom exists but its cause is unknown | reproduction plus causal evidence | +| Probe Choice | one named decision needs a disposable experiment | observed result and decision consequence | +| Deliver Change | outcome and edit boundary are closed | focused check, implementation, final-state evidence | +| Inspect Structure | ownership or duplication is the question | traced owners, callers, and boundary recommendation | +| Manage Work Items | the requested output is a local PRD/task set | local artifact with acceptance and dependencies | + +The six modules are alternatives, not a mandatory ceremony. Ordinary explanations, translations, +format-only work, and specified reversible file operations bypass the workflow. + +## Real examples + +These prompts are included in [`evals/routing-cases.json`](evals/routing-cases.json) and can be run +through the static fixture validator or the optional Codex runner: + +- “Checkout sometimes creates a duplicate order under load. Find the cause and fix it.” → + **Trace Failure** (the mechanism is unknown). +- “Build a disposable experiment to compare two state-transition models before we choose one.” → + **Probe Choice** (one named decision, throwaway scope). +- “Add the documented `--json` flag to the existing status command and verify the specified output + contract.” → **Deliver Change** (the contract is closed). +- “Explain what this function does and why it returns null here.” → **Bypass** (ordinary code + reading). + +Run deterministic routing checks without model access: + +```powershell +python scripts/validate_evals.py +python scripts/validate_harness.py --check +python scripts/run_routing_eval.py --limit 5 +``` + +Optional live Codex evidence is read-only and environment-dependent: + +```powershell +python scripts/run_routing_eval.py --live --public-submission ` + --output evals/runs/local-routing-results.json +``` + +The Harness projection and the Codex runner use the same cases; no live Harness runner is implied. -Validation requires Python 3.9 or newer. Install the development-only YAML parser, then run every -local release gate: +## Validation + +Use Python 3.9 or newer. The repository is standard-library-first; the development-only +`requirements-dev.txt` contains the YAML parser used by the validators. ```powershell python -m pip install -r requirements-dev.txt python scripts/validate_plugin.py plugins/engineer-software python scripts/validate_evals.py python scripts/validate_project.py +python scripts/validate_harness.py --check python -m unittest discover -s tests -v python -m compileall -q scripts tests ``` -`validate_plugin.py` enforces the stricter public-directory metadata and image limits in addition to -the local package shape. `validate_evals.py` verifies direct, indirect, follow-up, boundary, negative, -and every documented module-transition case. CI runs the same gates on the supported Python matrix. +`validate_project.py` includes the Harness projection and documentation checks. CI keeps the Python +3.9/3.12/3.13 matrix and the same validation, routing, unittest, and compile checks. The workflow +does not enable `setup-python`'s pip cache because this repository has no `requirements.txt` or +`pyproject.toml` cache contract; the development file is installed explicitly. -Optional live routing evidence uses the installed plugin and a read-only ephemeral Codex task: +## Compatibility, limits, and security -```powershell -python scripts/run_routing_eval.py --live --public-submission --output evals/runs/local-routing-results.json -``` +Read [docs/compatibility.md](docs/compatibility.md) for the matrix, install/upgrade/remove paths, +official DeepSeek Harness links, troubleshooting, and the exact “static only / live not verified” +boundary. The short version: + +- DeepSeek Harness is a rapidly changing developer preview; compatibility-breaking changes are + possible. +- The `.dsh/skills` tree is a generated projection. Edit the Codex canonical source and regenerate; + drift fails validation. +- This project does not ship an MCP server, hook, telemetry, credential store, or background + service. Tool permissions, API keys, and model configuration remain the user's runtime policy. +- Never commit API keys, `.env` files, session logs, profile state, generated temporary assets, or + unreviewed screenshots. + +GitHub is a distribution target, not a runtime route. This repository performs no issue-tracker, +telemetry, or remote workflow action when a skill is used. See [PRIVACY.md](PRIVACY.md), +[SECURITY.md](SECURITY.md), and [TERMS.md](TERMS.md). + +## Contributing and roadmap -See [evals/README.md](evals/README.md) for how to interpret environment-dependent model results. +Start with [CONTRIBUTING.md](CONTRIBUTING.md). Keep `plugins/engineer-software/skills/engineer-software/` +as the only editable workflow source, run the projection check after changes, and add routing +fixtures for new transitions. [ROADMAP.md](ROADMAP.md) records the deliberately small next steps; +it does not promise a long-lived adapter framework. -## Release and public directory +## Copy-ready launch text -The release workflow validates and packages the plugin when a matching `v*` tag is pushed. Before a -tag, update the SemVer release base, replace the single `+codex.` suffix, update -[CHANGELOG.md](CHANGELOG.md), and run the full gate above. +> Engineer Software is a runtime-neutral, evidence-driven workflow for AI coding agents. It routes +> substantive software work through one bounded module at a time, keeps Codex and DeepSeek Harness +> on one canonical source, and makes every transition carry fresh verification evidence. -Reviewer-ready listing copy, starter prompts, five positive cases, three negative cases, and release -notes are collected in [docs/public-submission.md](docs/public-submission.md). Public submission also -requires the publisher's verified OpenAI developer identity, region selection, policy attestations, -and a final portal action; those account-level choices are not stored in this repository. +Suggested GitHub description, topics, and homepage are recorded in +[`docs/public-submission.md`](docs/public-submission.md). They are recommendations only; this +repository does not call GitHub APIs or claim users, stars, adoption, or official sponsorship. -## Support and license +## License -Use [SUPPORT.md](SUPPORT.md) for bug-report details and [SECURITY.md](SECURITY.md) for private security -reports. Engineer Software is released under the [MIT License](LICENSE). +Engineer Software is released under the [MIT License](LICENSE). diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..3605f37 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,28 @@ +# Roadmap + +The roadmap keeps Engineer Software lean: one canonical workflow, two documented runtime entries, +and evidence that can be reproduced without a model key. + +## Near term + +- Track the official DeepSeek Harness skill-loader contract across preview releases and update the + projection probe when the upstream contract changes. +- Add a live Harness routing evaluator only when the official CLI exposes a stable, scriptable, + keyless or explicitly gated interface that can be verified locally. +- Keep Codex marketplace preflight and the shared routing fixture suite green while refining module + wording from observed disagreements. + +## Later, if evidence justifies it + +- Offer a thin official-Harness bundle only if a Markdown-skill distribution contract is documented; + do not add a guessed `dsh.bundle` adapter or a general runtime abstraction. +- Add more runtime comparison fixtures when both runtimes can produce comparable route and evidence + records. + +## Explicit non-goals + +- A second public repository or a migration narrative between runtimes. +- Hand-maintained copies of `SKILL.md` or `references/`. +- A generic multi-harness compatibility framework, telemetry service, MCP server, or background + process. +- Claims of DeepSeek sponsorship, official partnership, user counts, stars, or adoption. diff --git a/docs/assets/runtime-neutral-flow.svg b/docs/assets/runtime-neutral-flow.svg new file mode 100644 index 0000000..ac0770f --- /dev/null +++ b/docs/assets/runtime-neutral-flow.svg @@ -0,0 +1,57 @@ + + Engineer Software dual-runtime flow + One canonical skill source is projected to Codex and DeepSeek Harness while shared references and evaluations stay common. + + + + + + + + + + + + + + + + Runtime-neutral, evidence-driven workflow + + + Canonical source + SKILL.md + references + one owner, checked drift + shared routing evals + + + Codex entry + plugin.json + marketplace + native skill catalog + + + Harness entry + .dsh/skills projection + developer-preview contract + + + Evidence surface + same route cases + same module references + fresh verification + + + + + + + + No runtime-specific workflow fork + Only the loading projection changes; evidence and module semantics remain shared. + diff --git a/docs/compatibility.md b/docs/compatibility.md new file mode 100644 index 0000000..b146a2b --- /dev/null +++ b/docs/compatibility.md @@ -0,0 +1,142 @@ +# Runtime compatibility + +Engineer Software is one runtime-neutral workflow. Codex and DeepSeek Harness are independent +entry points over the same canonical skill source; this document records the loading contracts and +the evidence we can verify locally. + +## Official Harness facts + +The implementation follows the official [`deepseek-ai/deepseek-harness`](https://github.com/deepseek-ai/deepseek-harness) +repository, not similarly named community libraries. + +- The official README labels DeepSeek Harness (`dsh`) **developer preview** and warns of + compatibility-breaking changes. +- The official [skills subsystem](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/skills.md) + scans project roots in this order: `.dsh/skills`, `.agents/skills`, configured custom roots, and + user roots. A skill bundle is `/SKILL.md` with relative resources such as `references/`. +- The official [plugin publishing guide](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md) + defines a `package.json` `dsh.bundle.patch` format for executable Cordis composition layers. It + does not define a stable remote manifest for a Markdown-only skill. + +The repository therefore ships a checked-in `.dsh/skills/engineer-software/` projection generated +from `plugins/engineer-software/skills/engineer-software/`. It is a real project-local Harness +entry, not a claim of an official DeepSeek plugin or partnership. Run the deterministic probe: + +The local contract review used official `master` commit +[`47f943859bef60e4160492346772ded9b24f765a`](https://github.com/deepseek-ai/deepseek-harness/commit/47f943859bef60e4160492346772ded9b24f765a) +on 2026-08-13. Recheck the upstream docs before treating this preview contract as stable. + +```powershell +python scripts/validate_harness.py --check +``` + +The probe verifies file identity, frontmatter, resource paths, and the one-source rule. It does not +call a model or a live API. `python scripts/validate_harness.py --live` additionally asks a locally +installed `dsh` executable for `--version` when one is available; a successful version response is +not runtime or API certification. + +## Compatibility matrix + +| Surface | Codex | DeepSeek Harness | Evidence | Status | +| --- | --- | --- | --- | --- | +| Canonical workflow | `plugins/engineer-software/skills/engineer-software/` | same source projected to `.dsh/skills/engineer-software/` | byte-for-byte sync test | verified locally | +| Skill loader | Codex plugin manifest and marketplace | project `.dsh/skills//SKILL.md` | official docs + static probe | verified locally; Harness preview | +| Relative references | `references/*.md` in plugin skill | copied generated `references/*.md` | projection check | verified locally | +| Routing fixtures | `evals/routing-cases.json` and Codex runner | shared fixtures and expected routes | `validate_evals.py` + parity test | static only | +| Live model routing | optional `codex exec --ephemeral` | no live runner is claimed | environment-dependent | not run | +| Install channel | Codex marketplace/plugin commands | project checkout or generated user skill root | commands below | Harness contract may change | + +## Install, upgrade, and remove + +### Codex + +```powershell +codex plugin marketplace add KirschBluteX/engineer-software +codex plugin add engineer-software@engineer-software +codex plugin list +``` + +Start a new task after installation so the skill catalog is refreshed. To upgrade an existing +installation: + +```powershell +codex plugin marketplace upgrade engineer-software +codex plugin add engineer-software@engineer-software +``` + +Remove it with the Codex plugin manager (`codex plugin remove ...`) and confirm with +`codex plugin list`. Exact command spelling is owned by the installed Codex CLI; this project does +not emulate or wrap that manager. + +### DeepSeek Harness (project-local, recommended) + +The project checkout already contains the generated entry. After pulling a change, regenerate and +check it from the repository root: + +```powershell +python scripts/sync_harness_skill.py --write +python scripts/validate_harness.py --check +npx @deepseek-ai/dsh web +``` + +Choose this repository as the Harness workspace, then ask for a software change. The local provider +will discover `.dsh/skills/engineer-software/SKILL.md`; the six references remain relative to that +directory. The `npx` command and Web UI are documented by the official Harness README. No API key is +needed for the static checks; a model session requires the user's own Harness model configuration. + +To remove the project entry, delete the generated `.dsh/skills/engineer-software/` directory from +your checkout, or keep it and disable the skill in your Harness configuration. Do not edit the +projection by hand: rerun the sync command after changing the canonical source. + +### DeepSeek Harness (user-global) + +The official provider also scans `/skills`. A reviewed copy can be written to that root: + +```powershell +python scripts/sync_harness_skill.py --write ` + --target "$env:USERPROFILE\.dsh\skills\engineer-software" +python scripts/validate_harness.py --check ` + --target "$env:USERPROFILE\.dsh\skills\engineer-software" +``` + +Use the equivalent `$DSH_HOME/skills/engineer-software` path on other systems. Removing that target +uninstalls the user-global copy; rerun `--write` after upgrading this repository. The command never +deletes stale files, so inspect and remove obsolete generated files deliberately. + +## Troubleshooting + +**The skill does not appear.** Confirm that Harness is using the intended workspace, that the path is +exactly `.dsh/skills/engineer-software/SKILL.md`, and run `python scripts/validate_harness.py --check`. +The project root is the nearest ancestor containing `.git`; launching from an unrelated directory +will select a different root. + +**The skill appears but a reference cannot be loaded.** Run +`python scripts/sync_harness_skill.py --write`, then check for drift. Every reference must be under +the generated bundle's `references/` directory; nested recursive skill discovery is not part of the +official local provider contract. + +**The projection check reports drift.** Edit only the canonical Codex tree, then regenerate. A +drift report is an integrity failure, not a reason to maintain a second hand-edited copy. + +**A Harness upgrade breaks loading.** Treat this as a preview compatibility issue. Capture the +Harness commit/version, rerun the static probe, and consult the official repository's current skill +and plugin docs before changing this project. Do not infer a manifest or install command from a +community project with a similar name. + +**The live probe is skipped.** That means no `dsh` executable was found locally. It is an honest +environment result; static checks still prove the repository projection and do not imply live API +coverage. + +## Security boundary + +The skill contains instructions only. It has no MCP server, hook, telemetry, credential handling, or +background process. Harness itself may execute tools and may ask for a DeepSeek API key; those +permissions belong to the user's Harness profile and workspace policy. Review generated files before +placing them in a user-global skill directory, and never commit API keys, `.env` files, session logs, +or Harness profile state. + +## 简短中文入口 + +DeepSeek Harness 目前是 developer preview。项目使用官方支持的项目级 `.dsh/skills` 目录加载 +技能;`SKILL.md` 和 `references/` 由脚本从 Codex canonical source 生成,并由静态 probe 检查漂移。 +这不是 DeepSeek 官方插件或合作声明,live API 验证也未执行。 diff --git a/docs/public-submission.md b/docs/public-submission.md index e8dad98..ea9b17c 100644 --- a/docs/public-submission.md +++ b/docs/public-submission.md @@ -67,6 +67,37 @@ background service. The repository includes public-directory metadata and assets routing cases, local validation, CI, privacy/support/security documents, and an optional live read-only routing runner. +The same canonical workflow is also exposed through a generated project-local DeepSeek Harness +skill projection. DeepSeek Harness is a developer preview; this project makes no official +partnership, contributor, or live-API claim. + +## Copy-ready launch text + +Short: + +> Runtime-neutral, evidence-driven software engineering workflow for AI coding agents. + +Long: + +> Engineer Software routes substantive software work through one bounded evidence-driven module at +> a time: shape unclear contracts, trace unknown failures, probe one decision, deliver defined +> changes, inspect structural redundancy, or draft local work items. Codex and DeepSeek Harness use +> one canonical source with deterministic projection checks. + +Suggested GitHub repository description: + +> A runtime-neutral, evidence-driven software engineering workflow for AI coding agents. + +Suggested topics (choose only those that accurately describe the repository): + +`ai-coding-agent`, `agent-skills`, `software-engineering`, `evidence-driven`, `codex`, +`deepseek-harness`, `dsh-plugin` + +Suggested homepage: `https://github.com/KirschBluteX/engineer-software` + +These are copy suggestions only. Do not represent `dsh-plugin` as an official registry, and do not +publish GitHub metadata from this repository without a separate publisher decision. + ## Publisher-only final gate Before selecting **Submit for Review**, the publisher must confirm: @@ -81,4 +112,3 @@ Before selecting **Submit for Review**, the publisher must confirm: Submission begins OpenAI review; approval is followed by a separate publisher-controlled public release in the universal Plugins Directory. - diff --git a/evals/README.md b/evals/README.md index 158444a..71475e8 100644 --- a/evals/README.md +++ b/evals/README.md @@ -1,8 +1,10 @@ # Routing evaluations -`routing-cases.json` is the source of truth for skill activation and module routing. Each case is -self-contained and records the prompt, expected activation or bypass, allowed evidence-driven -transitions, expected result shape, and reproducible fixture. +`routing-cases.json` is the runtime-neutral source of truth for skill activation and module routing. +Each case is self-contained and records the prompt, expected activation or bypass, allowed +evidence-driven transitions, expected result shape, and reproducible fixture. Codex and DeepSeek +Harness consume the same canonical cases; the Harness side is currently a static projection check, +not a live model evaluation. The suite covers: @@ -15,6 +17,7 @@ Validate the case contract without model access: ```powershell python scripts/validate_evals.py +python scripts/validate_harness.py --check ``` Run a live, read-only routing sample through the installed Codex plugin: @@ -25,6 +28,7 @@ python scripts/run_routing_eval.py --live --public-submission --output evals/run Live results are environment-dependent evidence, not deterministic CI fixtures. The runner uses an ephemeral read-only Codex task and records only the route decision. `evals/runs/` is ignored so -model output is never committed accidentally. Review failed cases manually before changing the -skill; a model disagreement is a signal to inspect prompt ambiguity, not an automatic expected-route -rewrite. +model output is never committed accidentally. DeepSeek Harness live routing is not claimed until +the official preview exposes a stable, locally runnable evaluation surface. Review failed cases +manually before changing the skill; a model disagreement is a signal to inspect prompt ambiguity, +not an automatic expected-route rewrite. diff --git a/plugins/engineer-software/.codex-plugin/plugin.json b/plugins/engineer-software/.codex-plugin/plugin.json index a69f658..ed4d284 100644 --- a/plugins/engineer-software/.codex-plugin/plugin.json +++ b/plugins/engineer-software/.codex-plugin/plugin.json @@ -14,13 +14,16 @@ "software-engineering", "debugging", "testing", - "architecture" + "architecture", + "runtime-neutral", + "evidence-driven", + "deepseek-harness" ], "skills": "./skills/", "interface": { "displayName": "Engineer Software", "shortDescription": "Evidence-led software work", - "longDescription": "Routes software tasks to one bounded workflow for shaping, diagnosis, probes, implementation, structural review, or local planning.", + "longDescription": "A runtime-neutral, evidence-driven workflow that routes software tasks to one bounded module for shaping, diagnosis, probes, implementation, structural review, or local planning.", "developerName": "KirschBluteX", "category": "Developer Tools", "capabilities": [ diff --git a/plugins/engineer-software/assets/engineer-software-cover.png b/plugins/engineer-software/assets/engineer-software-cover.png new file mode 100644 index 0000000..e225727 Binary files /dev/null and b/plugins/engineer-software/assets/engineer-software-cover.png differ diff --git a/scripts/sync_harness_skill.py b/scripts/sync_harness_skill.py new file mode 100644 index 0000000..abf9473 --- /dev/null +++ b/scripts/sync_harness_skill.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +"""Synchronize the canonical Engineer Software skill into a Harness skill root. + +The Codex plugin tree is the only editable source. DeepSeek Harness discovers +project skills from ``.dsh/skills`` (or another configured skill root), so this +small projection keeps the two runtimes byte-identical without hand-maintained +copies. The command never deletes files; stale output is reported by +``--check`` and must be removed deliberately by its owner. +""" + +from __future__ import annotations + +import argparse +import shutil +import sys +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +CANONICAL_DIR = ROOT / "plugins" / "engineer-software" / "skills" / "engineer-software" +DEFAULT_TARGET = ROOT / ".dsh" / "skills" / "engineer-software" + + +def expected_files(source_dir: Path = CANONICAL_DIR) -> tuple[Path, ...]: + """Return the source-relative files that form the Harness skill bundle.""" + + references = source_dir / "references" + if not (source_dir / "SKILL.md").is_file(): + raise FileNotFoundError(f"canonical skill is missing: {source_dir / 'SKILL.md'}") + if not references.is_dir(): + raise FileNotFoundError(f"canonical references directory is missing: {references}") + files = [Path("SKILL.md")] + files.extend( + sorted( + path.relative_to(source_dir) + for path in references.glob("*.md") + if path.is_file() + ) + ) + if not files[1:]: + raise FileNotFoundError(f"canonical references are empty: {references}") + return tuple(files) + + +def _file_map(root: Path) -> set[Path]: + if not root.exists(): + return set() + return { + path.relative_to(root) + for path in root.rglob("*") + if path.is_file() + } + + +def compare_projection( + target: Path = DEFAULT_TARGET, + source_dir: Path = CANONICAL_DIR, +) -> list[str]: + """Return deterministic drift errors for one generated projection.""" + + expected = set(expected_files(source_dir)) + actual = _file_map(target) + errors: list[str] = [] + for relative in sorted(expected - actual): + errors.append(f"missing Harness projection file: {target / relative}") + for relative in sorted(actual - expected): + errors.append(f"unexpected Harness projection file: {target / relative}") + for relative in sorted(expected & actual): + source = source_dir / relative + projected = target / relative + if source.read_bytes() != projected.read_bytes(): + errors.append(f"Harness projection drift: {target / relative}") + return errors + + +def write_projection( + target: Path = DEFAULT_TARGET, + source_dir: Path = CANONICAL_DIR, +) -> None: + """Copy the canonical skill files into ``target`` without deleting output.""" + + target.mkdir(parents=True, exist_ok=True) + for relative in expected_files(source_dir): + source = source_dir / relative + destination = target / relative + destination.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(source, destination) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Generate or check the DeepSeek Harness skill projection." + ) + mode = parser.add_mutually_exclusive_group() + mode.add_argument( + "--write", + action="store_true", + help="write canonical files to the target (never removes stale files)", + ) + mode.add_argument( + "--check", + action="store_true", + help="check the target for missing, extra, or drifted files", + ) + parser.add_argument( + "--target", + type=Path, + default=DEFAULT_TARGET, + help="Harness skill bundle directory (default: .dsh/skills/engineer-software)", + ) + return parser.parse_args() + + +def main() -> int: + args = parse_args() + target = args.target.expanduser().resolve() + try: + if args.write: + write_projection(target) + errors = compare_projection(target) + except (OSError, FileNotFoundError) as exc: + print(f"Harness projection failed: {exc}", file=sys.stderr) + return 2 + if errors: + print("Harness projection check failed:", file=sys.stderr) + for error in errors: + print(f"- {error}", file=sys.stderr) + return 1 + action = "written and verified" if args.write else "verified" + print(f"Harness projection {action}: {target}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/validate_harness.py b/scripts/validate_harness.py new file mode 100644 index 0000000..0c4fd50 --- /dev/null +++ b/scripts/validate_harness.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +"""Run a static DeepSeek Harness compatibility probe. + +The probe validates the official filesystem skill contract locally. ``--live`` +only checks whether a local ``dsh`` executable can answer ``--version``; it +does not call a model or claim API compatibility. +""" + +from __future__ import annotations + +import argparse +import os +import shutil +import subprocess +import sys +from pathlib import Path + +from sync_harness_skill import CANONICAL_DIR, DEFAULT_TARGET, compare_projection, expected_files + + +ROOT = Path(__file__).resolve().parents[1] +OFFICIAL_SOURCES = ( + "https://github.com/deepseek-ai/deepseek-harness", + "https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/skills.md", + "https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md", +) + + +def _skill_frontmatter(path: Path) -> str: + text = path.read_text(encoding="utf-8") + if not text.startswith("---\n") or "\n---" not in text[4:]: + raise ValueError(f"{path} does not have closed YAML frontmatter") + return text[4 : text.find("\n---", 4)] + + +def static_errors(target: Path = DEFAULT_TARGET) -> list[str]: + """Return errors for the checked-in projection and its source ownership.""" + + errors = compare_projection(target) + try: + frontmatter = _skill_frontmatter(CANONICAL_DIR / "SKILL.md") + except (OSError, UnicodeError, ValueError) as exc: + errors.append(str(exc)) + frontmatter = "" + if "name: engineer-software" not in frontmatter: + errors.append("canonical SKILL.md frontmatter name is not engineer-software") + if "description:" not in frontmatter: + errors.append("canonical SKILL.md frontmatter description is missing") + + expected = set(expected_files()) + if expected != {Path("SKILL.md"), *(Path("references") / name for name in ( + "deliver-change.md", + "inspect-structure.md", + "manage-work-items.md", + "probe-choice.md", + "shape-work.md", + "trace-failure.md", + ))}: + errors.append("canonical skill file set changed; update the projection contract deliberately") + + # The projection may be duplicated only under the generated Harness root. + for path in ROOT.rglob("SKILL.md"): + if ".git" in path.parts: + continue + relative = path.relative_to(ROOT) + if path == CANONICAL_DIR / "SKILL.md" or path == target / "SKILL.md": + continue + errors.append(f"unexpected non-canonical SKILL.md source: {relative}") + return errors + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Probe the official DeepSeek Harness skill contract.") + parser.add_argument("--target", type=Path, default=DEFAULT_TARGET) + parser.add_argument( + "--check", + action="store_true", + help="run the static probe (the default; accepted for script symmetry)", + ) + parser.add_argument( + "--live", + action="store_true", + help="run local dsh --version when available; never contacts a model", + ) + return parser.parse_args() + + +def live_probe() -> int: + raw = os.environ.get("DSH_BIN", "dsh") + executable = shutil.which(raw) + if executable is None: + print("Live Harness probe: not run (dsh executable not found; static contract only).") + return 0 + try: + completed = subprocess.run( + [executable, "--version"], + cwd=ROOT, + capture_output=True, + text=True, + encoding="utf-8", + errors="replace", + timeout=30, + check=False, + ) + except (OSError, subprocess.TimeoutExpired) as exc: + print(f"Live Harness probe: not verified ({exc}); static contract passed.") + return 0 + output = (completed.stdout or completed.stderr).strip().splitlines() + version = output[0] if output else "no version output" + if completed.returncode: + print(f"Live Harness probe: dsh --version exited {completed.returncode} ({version}); static contract passed.") + return 0 + print(f"Live Harness probe: dsh responded ({version}); skill loading/API still not live-verified.") + return 0 + + +def main() -> int: + args = parse_args() + target = args.target.expanduser().resolve() + errors = static_errors(target) + if errors: + print("DeepSeek Harness static compatibility probe failed:", file=sys.stderr) + for error in errors: + print(f"- {error}", file=sys.stderr) + return 1 + print("DeepSeek Harness static compatibility probe passed.") + print("Official contract: project .dsh/skills//SKILL.md plus relative resources.") + print("Status: developer preview; no live model/API verification was performed.") + if args.live: + return live_probe() + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/validate_project.py b/scripts/validate_project.py index ab913e1..eb5a603 100644 --- a/scripts/validate_project.py +++ b/scripts/validate_project.py @@ -16,6 +16,7 @@ from validate_evals import ROUTES as EXPECTED_ROUTES from validate_evals import load_cases, validate_cases +from validate_harness import static_errors from validate_plugin import validate_plugin @@ -35,6 +36,8 @@ "SECURITY.md", "PRIVACY.md", "TERMS.md", + "ROADMAP.md", + "docs/compatibility.md", } SCAFFOLD_MARKER = "[TO" + "DO" @@ -195,6 +198,8 @@ def validate_public_files(readme: str, license_text: str, errors: list[str]) -> "Python 3.9", "validate_plugin.py", "validate_evals.py", + "runtime-neutral", + ".dsh/skills", ): if phrase not in readme: errors.append(f"README must contain {phrase!r}") @@ -216,6 +221,11 @@ def validate_repository_text(errors: list[str]) -> None: errors.append(f"repository contains a scaffold TODO in {relative(path)}") +def validate_harness_projection(errors: list[str]) -> None: + for error in static_errors(): + errors.append(f"Harness compatibility preflight: {error}") + + def validate_project() -> list[str]: errors: list[str] = [] marketplace = load_json( @@ -252,6 +262,7 @@ def validate_project() -> list[str]: errors.extend(f"routing preflight: {error}" for error in case_errors) validate_public_files(readme, license_text, errors) + validate_harness_projection(errors) validate_repository_text(errors) return errors diff --git a/tests/test_harness.py b/tests/test_harness.py new file mode 100644 index 0000000..04b3202 --- /dev/null +++ b/tests/test_harness.py @@ -0,0 +1,138 @@ +from __future__ import annotations + +import json +import re +import struct +import subprocess +import sys +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +CANONICAL = ROOT / "plugins" / "engineer-software" / "skills" / "engineer-software" +PROJECTION = ROOT / ".dsh" / "skills" / "engineer-software" +CASES = ROOT / "evals" / "routing-cases.json" + +sys.path.insert(0, str(ROOT / "scripts")) +from sync_harness_skill import compare_projection, expected_files # noqa: E402 +from validate_harness import OFFICIAL_SOURCES, static_errors # noqa: E402 + + +class HarnessContractTests(unittest.TestCase): + def test_projection_passes_static_probe(self) -> None: + self.assertEqual([], static_errors(PROJECTION)) + + def test_projection_is_byte_identical_to_canonical_files(self) -> None: + self.assertEqual([], compare_projection(PROJECTION)) + for relative in expected_files(): + with self.subTest(path=relative): + self.assertEqual( + (CANONICAL / relative).read_bytes(), + (PROJECTION / relative).read_bytes(), + ) + + def test_only_one_editable_skill_source_exists(self) -> None: + skill_files = { + path + for path in ROOT.rglob("SKILL.md") + if ".git" not in path.parts + } + self.assertEqual({CANONICAL / "SKILL.md", PROJECTION / "SKILL.md"}, skill_files) + + def test_shared_routing_fixtures_cover_both_runtime_entries(self) -> None: + cases = json.loads(CASES.read_text(encoding="utf-8")) + routes = {case["route"] for case in cases if case["route"] != "bypass"} + canonical_routes = { + path.stem for path in (CANONICAL / "references").glob("*.md") + } + projected_routes = { + path.stem for path in (PROJECTION / "references").glob("*.md") + } + self.assertTrue(routes <= canonical_routes) + self.assertEqual(canonical_routes, projected_routes) + + expected = [ + ( + case["id"], + "bypass" if case["route"] == "bypass" else "activate", + case["route"], + case["expected_behavior"], + case["expected_result"], + ) + for case in cases + ] + # Both runtime labels deliberately point at the same route/evidence record. + runtime_expectations = { + "codex": expected, + "deepseek-harness": expected, + } + self.assertEqual(runtime_expectations["codex"], runtime_expectations["deepseek-harness"]) + + def test_official_contract_sources_are_documented(self) -> None: + readme = (ROOT / "README.md").read_text(encoding="utf-8") + compatibility = (ROOT / "docs" / "compatibility.md").read_text(encoding="utf-8") + for source in OFFICIAL_SOURCES: + with self.subTest(source=source): + self.assertTrue(source in readme or source in compatibility) + + def test_readme_local_links_and_images_exist(self) -> None: + readme = (ROOT / "README.md").read_text(encoding="utf-8") + links = re.findall(r"\]\(([^)]+)\)", readme) + for raw in links: + target = raw.split("#", 1)[0] + if not target or target.startswith(("http://", "https://", "mailto:")): + continue + with self.subTest(target=target): + self.assertTrue((ROOT / target).is_file(), target) + + def test_cover_asset_is_reasonable_png(self) -> None: + cover = ROOT / "plugins" / "engineer-software" / "assets" / "engineer-software-cover.png" + data = cover.read_bytes() + self.assertTrue(data.startswith(b"\x89PNG\r\n\x1a\n")) + width, height = struct.unpack(">II", data[16:24]) + self.assertEqual((1536, 1024), (width, height)) + self.assertLess(len(data), 5 * 1024 * 1024) + + def test_ci_keeps_matrix_and_disables_pip_cache(self) -> None: + workflow = (ROOT / ".github" / "workflows" / "ci.yml").read_text(encoding="utf-8") + self.assertIn('python-version: ["3.9", "3.12", "3.13"]', workflow) + self.assertNotIn("cache: pip", workflow) + self.assertNotIn("cache-dependency-path", workflow) + for command in ( + "python scripts/validate_plugin.py plugins/engineer-software", + "python scripts/validate_evals.py", + "python scripts/validate_project.py", + "python -m unittest discover -s tests -v", + "python -m compileall -q scripts tests", + ): + with self.subTest(command=command): + self.assertIn(command, workflow) + + def test_workflow_is_parseable_yaml(self) -> None: + try: + import yaml + except ImportError: # pragma: no cover - requirements-dev supplies PyYAML + self.skipTest("PyYAML is not installed") + workflow = (ROOT / ".github" / "workflows" / "ci.yml").read_text(encoding="utf-8") + parsed = yaml.safe_load(workflow) + self.assertIsInstance(parsed, dict) + self.assertIn("jobs", parsed) + self.assertIn("validate", parsed["jobs"]) + + def test_probe_command_is_reproducible(self) -> None: + completed = subprocess.run( + [sys.executable, "scripts/validate_harness.py", "--check"], + cwd=ROOT, + capture_output=True, + text=True, + encoding="utf-8", + check=False, + ) + self.assertEqual(0, completed.returncode, completed.stderr) + self.assertIn("static compatibility probe passed", completed.stdout) + self.assertIn("developer preview", completed.stdout) + + +if __name__ == "__main__": + unittest.main()