From 459458268700108f437b102ef70c57d393fb96e1 Mon Sep 17 00:00:00 2001 From: Andyduck-ops Date: Wed, 12 Aug 2026 13:20:08 +0800 Subject: [PATCH] feat: promote lab workflow improvements for 0.3.0 --- .agents/skills/omp-flow-brainstorm/SKILL.md | 17 +- .agents/skills/omp-flow-check/SKILL.md | 9 + .agents/skills/omp-flow-decompose/SKILL.md | 14 +- .agents/skills/omp-flow-design/SKILL.md | 25 +- .agents/skills/omp-flow-finish/SKILL.md | 30 +- .agents/skills/omp-flow-implement/SKILL.md | 11 +- .agents/skills/omp-flow-learn/SKILL.md | 127 +++ .agents/skills/omp-flow-qbd/SKILL.md | 42 +- .agents/skills/omp-flow-research/SKILL.md | 24 +- .agents/skills/omp-flow-sleep/SKILL.md | 63 ++ .agents/skills/omp-flow/SKILL.md | 9 +- .claude/agents/omp-flow-architect.md | 20 +- .claude/agents/omp-flow-check.md | 19 +- .claude/agents/omp-flow-implement.md | 17 +- .claude/agents/omp-flow-qbd.md | 25 +- .claude/agents/omp-flow-research.md | 24 +- .claude/skills/omp-flow-brainstorm/SKILL.md | 17 +- .claude/skills/omp-flow-check/SKILL.md | 9 + .claude/skills/omp-flow-decompose/SKILL.md | 14 +- .claude/skills/omp-flow-design/SKILL.md | 25 +- .claude/skills/omp-flow-finish/SKILL.md | 30 +- .claude/skills/omp-flow-implement/SKILL.md | 11 +- .claude/skills/omp-flow-learn/SKILL.md | 127 +++ .claude/skills/omp-flow-qbd/SKILL.md | 42 +- .claude/skills/omp-flow-research/SKILL.md | 24 +- .claude/skills/omp-flow-sleep/SKILL.md | 63 ++ .claude/skills/omp-flow/SKILL.md | 9 +- .codex/agents/omp-flow-architect.toml | 19 +- .codex/agents/omp-flow-check.toml | 18 +- .codex/agents/omp-flow-implement.toml | 16 +- .codex/agents/omp-flow-qbd.toml | 25 +- .codex/agents/omp-flow-research.toml | 24 +- .codex/hooks/protect-runtime.py | 4 +- .omp/agents/architect.md | 19 +- .omp/agents/executor.md | 17 +- .omp/agents/orchestrator.md | 20 +- .omp/agents/qbd-auditor.md | 26 +- .omp/agents/researcher.md | 26 +- .omp/agents/reviewer.md | 21 +- .omp/skills/omp-flow-brainstorm/SKILL.md | 17 +- .omp/skills/omp-flow-check/SKILL.md | 9 + .omp/skills/omp-flow-decompose/SKILL.md | 14 +- .omp/skills/omp-flow-design/SKILL.md | 25 +- .omp/skills/omp-flow-finish/SKILL.md | 30 +- .omp/skills/omp-flow-implement/SKILL.md | 11 +- .omp/skills/omp-flow-learn/SKILL.md | 127 +++ .omp/skills/omp-flow-qbd/SKILL.md | 42 +- .omp/skills/omp-flow-research/SKILL.md | 24 +- .omp/skills/omp-flow-sleep/SKILL.md | 63 ++ .omp/skills/omp-flow/SKILL.md | 9 +- README.md | 28 + README_EN.md | 22 + package-lock.json | 4 +- package.json | 2 +- src/cli/init.ts | 14 + templates/.omp-flow/learn/daily/index.md | 15 + templates/.omp-flow/learn/index.md | 43 + .../.omp-flow/learn/retrospectives/index.md | 16 + templates/.omp-flow/learn/threads/index.md | 15 + .../.omp-flow/scripts/common/sleep_store.py | 408 +++++++++ .../.omp-flow/scripts/common/task_store.py | 6 +- templates/.omp-flow/scripts/omp_flow.py | 57 +- templates/.omp-flow/workflow.md | 65 +- templates/claude/agents/omp-flow-architect.md | 20 +- templates/claude/agents/omp-flow-check.md | 19 +- templates/claude/agents/omp-flow-implement.md | 17 +- templates/claude/agents/omp-flow-qbd.md | 25 +- templates/claude/agents/omp-flow-research.md | 24 +- .../codex/agents/omp-flow-architect.toml | 19 +- templates/codex/agents/omp-flow-check.toml | 18 +- .../codex/agents/omp-flow-implement.toml | 16 +- templates/codex/agents/omp-flow-qbd.toml | 25 +- templates/codex/agents/omp-flow-research.toml | 24 +- templates/codex/hooks/protect-runtime.py | 4 +- .../skills/omp-flow-brainstorm/SKILL.md | 17 +- .../common/skills/omp-flow-check/SKILL.md | 9 + .../common/skills/omp-flow-decompose/SKILL.md | 14 +- .../common/skills/omp-flow-design/SKILL.md | 25 +- .../common/skills/omp-flow-finish/SKILL.md | 30 +- .../common/skills/omp-flow-implement/SKILL.md | 11 +- .../common/skills/omp-flow-learn/SKILL.md | 127 +++ templates/common/skills/omp-flow-qbd/SKILL.md | 42 +- .../common/skills/omp-flow-research/SKILL.md | 24 +- .../common/skills/omp-flow-sleep/SKILL.md | 63 ++ templates/common/skills/omp-flow/SKILL.md | 9 +- templates/omp/agents/architect.md | 19 +- templates/omp/agents/executor.md | 17 +- templates/omp/agents/orchestrator.md | 20 +- templates/omp/agents/qbd-auditor.md | 26 +- templates/omp/agents/researcher.md | 26 +- templates/omp/agents/reviewer.md | 21 +- tests/learn.test.ts | 484 ++++++++++ tests/omp-flow.test.ts | 865 ++++++++++++++++-- tests/snow-cursor-managed-resources.test.ts | 229 ++++- tests/wiki-sleep.test.py | 608 ++++++++++++ 95 files changed, 4318 insertions(+), 727 deletions(-) create mode 100644 .agents/skills/omp-flow-learn/SKILL.md create mode 100644 .agents/skills/omp-flow-sleep/SKILL.md create mode 100644 .claude/skills/omp-flow-learn/SKILL.md create mode 100644 .claude/skills/omp-flow-sleep/SKILL.md create mode 100644 .omp/skills/omp-flow-learn/SKILL.md create mode 100644 .omp/skills/omp-flow-sleep/SKILL.md create mode 100644 templates/.omp-flow/learn/daily/index.md create mode 100644 templates/.omp-flow/learn/index.md create mode 100644 templates/.omp-flow/learn/retrospectives/index.md create mode 100644 templates/.omp-flow/learn/threads/index.md create mode 100644 templates/.omp-flow/scripts/common/sleep_store.py create mode 100644 templates/common/skills/omp-flow-learn/SKILL.md create mode 100644 templates/common/skills/omp-flow-sleep/SKILL.md create mode 100644 tests/learn.test.ts create mode 100644 tests/wiki-sleep.test.py diff --git a/.agents/skills/omp-flow-brainstorm/SKILL.md b/.agents/skills/omp-flow-brainstorm/SKILL.md index a7c801f8..8f2ddf03 100644 --- a/.agents/skills/omp-flow-brainstorm/SKILL.md +++ b/.agents/skills/omp-flow-brainstorm/SKILL.md @@ -16,10 +16,11 @@ description: Explore and clarify a consented omp-flow task Bundle when direction For a non-trivial Explore, use repository/Wiki evidence and human calibration to form or revise a provisional first-principles anchor(第一性锚定)before broad Research. Keep it in useful authored -prose, not a required file or fixed checklist. It should be sufficient to expose the observable -problem, current principal contradiction(主要矛盾), irreducible outcome, human boundaries, a -strong counter-hypothesis, and evidence that would revise the framing. Mechanical low-ambiguity -work may proceed directly when this step would not improve a decision. +prose, not a required file or fixed checklist. It should be sufficient to expose the concrete +actors and action, observable intended outcome, current principal contradiction(主要矛盾), +irreducible outcome, human boundaries, a strong counter-hypothesis, and evidence that would +revise the framing. Mechanical low-ambiguity work may proceed directly when this would not improve +a decision. Concentrate interaction on the material decision frontier: @@ -33,11 +34,13 @@ Concentrate interaction on the material decision frontier: ## Interview Contract 1. Read the entry Concept and follow only useful links from the Bundle. -2. Record the initial request and known repository facts in the assigned framing Concept. +2. Record the initial request, concrete actors/action/outcome, current principal contradiction, + and known repository facts in the assigned framing Concept. 3. Inspect code, tests, docs, prior tasks, relevant history, and applicable durable knowledge through the native `omp-flow-wiki` Skill before asking repository-answerable questions. -4. Ask the user one material decision question at a time. Ask only about intent, preference, - scope, risk tolerance, or ambiguity that evidence cannot answer. +4. Ask the user one material decision question at a time. Ask only about purpose, value, risk + tolerance, preference, or use that repository and other relevant practice evidence cannot + establish. 5. Keep confirmed facts, assumptions, disagreements, alternatives, constraints, success criteria, and open questions distinct. 6. Present materially different directions only when a real choice exists. Follow the human-first diff --git a/.agents/skills/omp-flow-check/SKILL.md b/.agents/skills/omp-flow-check/SKILL.md index 8402cbde..8bccef4a 100644 --- a/.agents/skills/omp-flow-check/SKILL.md +++ b/.agents/skills/omp-flow-check/SKILL.md @@ -18,6 +18,15 @@ Fail closed unless all are available: ## Review Order +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Reviewer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Reviewer still owns the complete +bounded independent Review and assigned Review Concept: compare actual code and verification with +the intended work/Design consequence, and report evidence contradicting the Design or its +principal-problem framing through that output rather than let a handoff or superficial green check +substitute for the practice result. + 1. Resolve the completed predecessor operation and use its output path as the required handoff. Read the work Concept and handoff, verify they identify each other, then inspect the real diff and changed files. diff --git a/.agents/skills/omp-flow-decompose/SKILL.md b/.agents/skills/omp-flow-decompose/SKILL.md index d76b5885..6231da9f 100644 --- a/.agents/skills/omp-flow-decompose/SKILL.md +++ b/.agents/skills/omp-flow-decompose/SKILL.md @@ -12,6 +12,14 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Architect: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. After linked human QbD 1 approval, the +Architect still owns the complete bounded Decompose responsibility and assigned work outputs: map +the approved Design into bounded, independently reviewable work Concepts and an authored prose +execution view, without inventing approval or encoding a machine DAG. + 1. Identify the smallest independently implementable and reviewable work items. Fold scaffolding and docs into the deliverable that needs them. 2. Write one descriptive work Concept per item with objective, in/out scope, useful linked inputs, @@ -26,8 +34,10 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Exit Gate -Prepare QbD 2 only when every work item is bounded, testable, understandable from its entry path, -and worth independent review. Load `omp-flow-qbd` next. +In Main/coordinator context only, prepare QbD 2 and load `omp-flow-qbd` when every work item is +bounded, testable, understandable from its entry path, and worth independent review. The +already-dispatched Architect returns the assigned work map and does not choose or perform that +transition. ## Red Flags diff --git a/.agents/skills/omp-flow-design/SKILL.md b/.agents/skills/omp-flow-design/SKILL.md index 1bc729a6..8742fc3f 100644 --- a/.agents/skills/omp-flow-design/SKILL.md +++ b/.agents/skills/omp-flow-design/SKILL.md @@ -13,11 +13,20 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re ## Procedure -1. Dispatch the native Architect with Bundle root, selected synthesis entry, bounded objective, - relevant linked Concepts, explicit output ownership, actor ID, and receipt. Create the - operation first and forward its complete returned assignment unchanged with native item - `id = actor_id = actorId` and matching descriptor role. Preserve the strict v1 - `ompFlowDispatch` descriptor as the first non-blank line. +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Architect: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Architect still owns +the complete bounded Design responsibility and assigned PRD/Design/decision/interface outputs: +explain each proposed component's concrete causal purpose in plain language, without relying on its +own terminology, and solve the evidenced principal contradiction rather than a secondary or +invented mechanism. + +1. In Main/coordinator context only, dispatch the native Architect with Bundle root, selected + synthesis entry, bounded objective, relevant linked Concepts, explicit output ownership, actor + ID, and receipt. Create the operation first and forward its complete returned assignment + unchanged with native item `id = actor_id = actorId` and matching descriptor role. Preserve the + strict v1 `ompFlowDispatch` descriptor as the first non-blank line. 2. Rewrite `prd.md` into observable requirements, non-goals, constraints, acceptance criteria, and unresolved product decisions. Remove temporary brainstorm duplication. 3. Write `design.md` with components, interfaces, data flow, state ownership, error behavior, migration/compatibility, verification strategy, and rejected alternatives. 4. Add linked decision, interface, brief, or finding Concepts only when they improve navigation or @@ -34,8 +43,10 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re - No unresolved question blocks decomposition. - Linked sources and accepted contracts agree with the Design. -Load `omp-flow-qbd` for independent challenge and record the human decision as a linked Concept. -Do not create implementation work before human QbD 1 approval. +In Main/coordinator context only, load `omp-flow-qbd` for independent challenge and obtain and +record the human decision as a linked Concept. The already-dispatched Architect returns its +assigned outputs and does not choose or perform that transition. Do not create implementation work +before human QbD 1 approval. ## Red Flags diff --git a/.agents/skills/omp-flow-finish/SKILL.md b/.agents/skills/omp-flow-finish/SKILL.md index d2f76d56..95cf9c1a 100644 --- a/.agents/skills/omp-flow-finish/SKILL.md +++ b/.agents/skills/omp-flow-finish/SKILL.md @@ -17,14 +17,34 @@ description: Complete integration verification, deliberate knowledge harvest, co 2. Compare the integrated result against PRD acceptance criteria, cross-row interfaces, migrations, docs, and compatibility requirements. 3. Resolve failures through the owning work/design Concept and repeat independent review or the applicable gate. Do not hide failures with warning-only fallbacks. -4. Review accepted decisions, repeated patterns, and confirmed findings for durable value. -5. Use the native `omp-flow-wiki` Skill to promote only evidenced, reusable knowledge. If nothing qualifies, state that no harvest was needed. -6. Inspect final diff and repository status. Commit through the Harness-native Git workflow when requested. -7. Archive the Bundle only after completion is real and no runtime operation is active. +4. Review accepted decisions, repeated patterns, and confirmed findings for immediate durable value. + Use the native `omp-flow-wiki` Skill only when the evidence already supports promotion; do not + invent knowledge to satisfy Finish. +5. Inspect final diff and repository status. Create the requested Git checkpoint before Archive so + the Task Bundle has a reproducible source commit/tree. +6. Archive the Bundle only after completion is real and no runtime operation is active. Inspect the + returned `sleepSource`; never reconstruct one from the archive path. +7. When `sleepSource.ready` is true, run `sleep start --source --actor-id `, + load the native `omp-flow-sleep` Skill, and forward its complete assignment unchanged as the sole + native assignment input. Normal `sleep start` delivery is primary. If that delivery is lost or + visibly truncated while its active receipt is known, recover only by capturing the complete + `sleep show ` subprocess/API stdout through successful process completion, parsing all + captured stdout as JSON into the show run mapping, requiring string `run.assignment`, and + forwarding that decoded string unchanged as the sole native assignment input, including its + trailing LF. Rendered Bash/terminal output is diagnostic only: never copy or parse it, add a + prefix or suffix, reconstruct or reserialize the assignment, fall back to `sleep list`, or issue + a duplicate `sleep start`. A nonzero exit, incomplete capture, invalid JSON, or missing or + non-string `run.assignment` is delivery failure and must stop before native dispatch. Complete + the Sleep run before final handoff; zero Candidates is valid. +8. When the source is not ready, report its exact reason instead of asking the user to operate Sleep + manually or manufacturing a checkpoint. Sleep Candidate review and Wiki promotion remain + separate work after the run. ## Final Handoff -Report behavior delivered, important decisions, verification results, archived task path, commit identity when created, and remaining non-blocking risks. +Report behavior delivered, important decisions, verification results, archived task path, commit +identity when created, Sleep run/Candidate outputs or the exact unavailable reason, and remaining +non-blocking risks. ## Red Flags diff --git a/.agents/skills/omp-flow-implement/SKILL.md b/.agents/skills/omp-flow-implement/SKILL.md index e4bd10ca..46380aca 100644 --- a/.agents/skills/omp-flow-implement/SKILL.md +++ b/.agents/skills/omp-flow-implement/SKILL.md @@ -18,6 +18,14 @@ Fail closed unless all are available: ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Implementer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Implementer still owns the +complete bounded implementation and assigned handoff: return the approved Design to practice +through code, execution, and real verification, and report contradictory evidence as a +Design-return signal rather than special-case reality to preserve Design authority. + 1. Read the work Concept first. Follow only useful links to design, decisions, sources, and relevant existing code/tests. 2. Restate the bounded objective, output boundary, done conditions, and verification before editing. @@ -32,7 +40,8 @@ Fail closed unless all are available: Write or update the promised handoff Concept and link it back to the work it implements. Return `DONE`, `DONE_WITH_CONCERNS`, `NEEDS_CONTEXT`, or `BLOCKED`, plus changed files, commands, test counts, decisions, caveats, output path, actor ID, and receipt. Do not mutate runtime/session -records. Implementation success goes to an independent review operation. +records. The Implementer returns this assigned handoff; only Main/coordinator chooses and +dispatches the independent Review operation. ## Red Flags diff --git a/.agents/skills/omp-flow-learn/SKILL.md b/.agents/skills/omp-flow-learn/SKILL.md new file mode 100644 index 00000000..c986e8ca --- /dev/null +++ b/.agents/skills/omp-flow-learn/SKILL.md @@ -0,0 +1,127 @@ +--- +name: omp-flow-learn +description: Maintain and use repository-root .omp-flow/learn for deliberate, reciprocal, resumable Human–Agent co-learning when a human is present and pursuing understanding rather than production execution. +--- + +# OMP-Flow Learn + +Use repository-root `.omp-flow/learn/` when a human is actively pursuing mutual understanding, +explanation, challenge, reconsideration, or reflection. Learn is a human-present dialogue in which +both participants may correct their models; autonomous harvesting, passive one-way tutoring, or +summary generation is not a substitute. + +Production work normally pauses during a Learn conversation. Source and code inspection, worked +examples, counterexamples, and discussion remain available, but do not execute production work +until the human returns the conversation to production. + +## Consult and bootstrap + +Open a known Learn Concept directly when its path is available. Otherwise start at +`.omp-flow/learn/index.md` and follow only ordinary links useful to the current discussion. Indexes +support navigation; they are not exhaustive manifests. + +When Learn is genuinely needed and the root is absent, bootstrap only the root index and the +`daily/`, `threads/`, and `retrospectives/` indexes described by the canonical minimal structure. +Do not pre-populate speculative encounters, a taxonomy, or companion records. + +## Preserve a resumable checkpoint + +Use judgment to select or create a bundle immediately below the relevant stable directory. Name a +new bundle `YYYY-MM-DD-/` and maintain its authored `index.md` so a later human and Agent can +recover the useful current understanding, disagreement, correction, or open point. Add only +concrete descriptive Markdown Concepts that make the learning easier to resume or challenge. + +A Daily records a useful dated encounter and may stand alone. A Thread is warranted only when a +topic needs continuity across encounters. A Retrospective is warranted only for a substantive +lesson about understanding or collaboration. Do not manufacture a Thread or Retrospective to +complete a set. + +Treat the human's corrections, rejected premises, values, business context, and objections as +learning material. Make corrected Agent assumptions visible when that helps resumption. Accuracy +comes from reciprocal correction and evidence, not from fluent prose or Agent confidence. + +## Authority and continuity boundaries + +Learn is provisional authored context, not proof of understanding or completion. + +- A Learn artifact cannot advance, pause-state, approve, dispatch, or otherwise alter an omp-flow + Task. A Task link is contextual; commitments remain authored in the applicable Task Bundle. +- A Learn artifact is not Wiki authority and is never promoted automatically. Durable knowledge + reaches `.omp-flow/wiki/` only through ordinary evidence-based Wiki maintenance. +- Cross-session continuity is limited to visible authored artifacts. Never claim a hidden user + profile, persistent personal memory, or model-weight change. + +## Select the smallest useful lens + +The lenses below are a selectable conversational repertoire, not stages, a checklist, a catechism, +an assessment, or an Agent-led teaching script. Choose the smallest lens that addresses the live +misunderstanding. Combine lenses only when one supplies a relevant corrective to another. Concrete +project facts, code, sources, worked cases, and the human's correction outrank philosophical labels. +Stop when the participants have a useful explanation, disagreement, or open point; do not march +through the remaining lenses. + +### Feynman-style self-explanation + +Invite a plain account of one concrete causal link. Find the first hidden term, unsupported leap, or +failed application, then repair it from a source or worked case. Fluency is only a possible gap +diagnostic and never proof of mastery. Do not attribute the modern packaged “Feynman Technique” to +Feynman. + +### Cargo Cult Science integrity + +For a consequential explanation, volunteer the material contrary fact, plausible alternative, +uncertainty, and observation that could change the conclusion so the other participant can judge +it. This is judgment about material disclosure, not four mandatory headings, a fixed response form, +or a ritual inventory of every caveat. + +### Grounded first principles + +Distinguish observed fact, definition, hard constraint, value choice, assumption, and convention. +Trace only premises capable of changing the present conclusion, retain the conditions under which +it should be revised, and stop when further reduction would not help. Existing knowledge and +history are evidence to examine, not impurities to discard. + +### Practice-led principal-contradiction analysis + +Offer the principal contradiction, dominant aspect, and material secondary coupling only as a +revisable prioritization hypothesis tied to current effects. Name the changed condition or practical +observation that would reorder it. Returning to practice may mean sources, code inspection, +examples, counterexamples, a diagram, or later observable verification; it does not authorize +production execution while Learn is paused. Do not import a universal single-cause claim or +political doctrine. + +### Material history or genealogy + +Use a concise temporal account only when it clarifies the present. Connect a concrete problem and +conditions to a prior arrangement, emergence or adoption, limitation, and later change; include a +discontinuity where needed and label interpretive causality. Reject inevitable or present-purpose +origin stories, mechanically economic single-causality, and political doctrine; examine interacting +causes and source support. + +### Reciprocal Socratic questioning + +Use a few genuine reasons, counterexamples, and consequence questions to test either participant's +claim. Either participant may reject a premise, ask the Agent to answer directly, or leave an aporia +open. Questions yield to direct explanation or admitted uncertainty when more useful and never +steer assent toward a conclusion the Agent selected in advance. + +### Minimal structural box-drawing + +Draw labeled ASCII, Unicode, or Mermaid boxes and arrows only when a few elements at one useful +abstraction level make a particular structural inference cheaper than prose. Check the picture +against sources, code, examples, or the participants' model; revise or discard it when it does not +help. A diagram is not inherently clarifying. + +These lenses create optional corrective friction rather than a composite routine: explanation +answers to integrity and evidence; alleged hard constraints to history; principal ranking to +secondary couplings and changed conditions; historical narrative to discontinuity and interacting +causes; questions to reciprocal answerability; and diagrams to prose, source, or practice +comparison. They do not adopt a complete philosophical school or establish mastery. + +## Keep Learn conversational + +Do not introduce an entry command, pause or save signal, fixed encounter stages, required +transcript or summary, mandatory headings, score, metric, completion gate, approval ceremony, or +per-edit human approval rule. There is no parsed body schema, lifecycle record, second task system, +or automatic learning judgment. Preserve only what is genuinely useful for reciprocal resumption, +and return to production only when the human changes the conversation back to production work. diff --git a/.agents/skills/omp-flow-qbd/SKILL.md b/.agents/skills/omp-flow-qbd/SKILL.md index 9b092c0e..686d6174 100644 --- a/.agents/skills/omp-flow-qbd/SKILL.md +++ b/.agents/skills/omp-flow-qbd/SKILL.md @@ -19,17 +19,27 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Auditor: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Auditor still owns the +complete bounded independent audit and assigned audit Concept: reconstruct the concrete problem +without solution jargon, challenge whether the selected problem and current principal +contradiction still hold before judging architecture completeness, preserve the mechanical safety +analysis, and report the required verdict, findings, evidence, and contradictions through that +output boundary. + 1. Identify the design or work-map entry Concept and an explicit audit output Concept. Through its useful links, bind the audit to the current decision, unacceptable consequences, current scope/change, and relevant closed findings, residual risks, and human decisions. Do not require a fixed audit-brief file or field shape; no prior findings is normal for a first audit. -2. Start one independent QbD operation with Bundle root, role, bounded objective, entry, output, - actor ID, and optional predecessor receipt. -3. Dispatch one independent native `qbd-auditor`. Pass the paths and opaque receipt returned by - the runtime by forwarding the complete returned assignment unchanged. Keep its strict v1 - `ompFlowDispatch` descriptor as the first non-blank line, set native item - `id = actor_id = actorId`, and use the matching descriptor role. Do not render the Bundle, - reconstruct the descriptor, or prepend audit prose. +2. In Main/coordinator context only, start one independent QbD operation with Bundle root, role, + bounded objective, entry, output, actor ID, and optional predecessor receipt. +3. In Main/coordinator context only, dispatch one independent native `qbd-auditor`. Pass the paths + and opaque receipt returned by the runtime by forwarding the complete returned assignment + unchanged. Keep its strict v1 `ompFlowDispatch` descriptor as the first non-blank line, set + native item `id = actor_id = actorId`, and use the matching descriptor role. Do not render the + Bundle, reconstruct the descriptor, or prepend audit prose. 4. Require an explicit verdict with these semantics: - `FAIL` requires evidence of a critical falsehood, authorization or data violation, irreversible harm, or an unrealizable/unverifiable core path for which safe degradation is @@ -42,15 +52,21 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl decision, give the smallest remedy, and explain why hiding, `unavailable`, disabling, narrowing, refusal to write, or another safe degradation is insufficient. Findings without that chain are advisory. -6. Confirm the promised audit Concept exists, links to what it evaluated, and records material - findings. Finish the runtime operation with the same actor ID. -7. Present material findings and the applicable governance options to the user. Only the user - decides calibration; the verdict itself authorizes no repair, re-audit, or forward transition. -8. Record the human decision in a linked decision Concept. Do not encode approval, materiality, or - risk as runtime phase or parsed state. +6. In Main/coordinator context only, confirm the promised audit Concept exists, links to what it + evaluated, and records material findings, then finish the runtime operation with the same actor + ID. The already-dispatched Auditor returns that assigned audit output; it does not finish or + correlate the coordinator's operation. +7. In Main/coordinator context only, present material findings and applicable governance options + to the user. Only the user decides calibration; the verdict itself authorizes no repair, + re-audit, or forward transition. +8. In Main/coordinator context only, record the human decision in a linked decision Concept. Do + not encode approval, materiality, or risk as runtime phase or parsed state. ## Transitions +These routing choices are Main/coordinator-only and inapplicable to an already-dispatched Auditor, +which returns the assigned audit findings and verdict without choosing or performing a transition. + - Recorded QbD 1 human PASS -> load `omp-flow-decompose`. - Recorded QbD 2 human PASS -> load `omp-flow-execute`. - Advisory risk, `PASS` residual risk, or risk made non-blocking by removal, disabling, narrowing, diff --git a/.agents/skills/omp-flow-research/SKILL.md b/.agents/skills/omp-flow-research/SKILL.md index 0a79cf04..ae06c006 100644 --- a/.agents/skills/omp-flow-research/SKILL.md +++ b/.agents/skills/omp-flow-research/SKILL.md @@ -29,13 +29,22 @@ Choose and persist one of: ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Researcher: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Researcher still owns +the complete bounded Research responsibility and assigned output: test the framing against +practice, distinguish what evidence proves, does not prove, and merely makes possible, and report a +materially changed principal contradiction as a Brainstorm-return signal rather than protect the +earlier framing. + 1. Split uncertainty into independently investigable questions and create descriptive output paths. -2. Dispatch Harness-native researcher agents when questions can be investigated independently. - Pass Bundle root, role, objective, entry Concept, exact output path, actor ID, receipt, and the - no-implementation boundary. - Start one operation per native task item, then forward its complete returned assignment - unchanged with item `id = actor_id = actorId` and matching descriptor role. The strict v1 - `ompFlowDispatch` descriptor remains the first non-blank line; do not decorate or reconstruct it. +2. In Main/coordinator context only, dispatch Harness-native researcher agents when questions can + be investigated independently. Pass Bundle root, role, objective, entry Concept, exact output + path, actor ID, receipt, and the no-implementation boundary. Start one operation per native task + item, then forward its complete returned assignment unchanged with + `id = actor_id = actorId` and matching descriptor role. The strict v1 `ompFlowDispatch` + descriptor remains the first non-blank line; do not decorate or reconstruct it. 3. Separate facts, interpretations, counter-evidence, unknowns, and recommendations. Actively seek the strongest evidence against the current framing, not only confirmation. Internal claims use `file:line`; external claims use stable source URLs and version/date where relevant. @@ -61,7 +70,8 @@ Choose and persist one of: next decision. - The synthesis lets an Architect design without reconstructing research from chat. -Load `omp-flow-design` next. +In Main/coordinator context only, load `omp-flow-design` next. The already-dispatched Researcher +returns the assigned synthesis/output and does not choose or perform that transition. ## Red Flags diff --git a/.agents/skills/omp-flow-sleep/SKILL.md b/.agents/skills/omp-flow-sleep/SKILL.md new file mode 100644 index 00000000..dcf957bd --- /dev/null +++ b/.agents/skills/omp-flow-sleep/SKILL.md @@ -0,0 +1,63 @@ +--- +name: omp-flow-sleep +description: Consolidate one exact archived OKF Task into reviewable cross-task knowledge candidates after Finish, without machine clustering or direct Wiki promotion. +--- + +# OMP-Flow Sleep + +Use this Skill only with a complete assignment whose first non-blank line is an exact +`{"ompFlowSleep":{...}}` descriptor produced by `.omp-flow/scripts/omp_flow.py sleep start`. +Do not reconstruct, summarize, or guess a descriptor from an archived path. + +## Descriptor contract + +Require `version`, `sourceReceipt`, `sourceTask`, `sourceCommit`, `sourceTree`, `entry`, +`sleepIndex`, `runOutput`, `candidateRoot`, `actorId`, `receipt`, and `harvesterRevision`. +Require `version` exactly `1`, the assignment actor to match `actorId`, and every supplied path to +remain within the repository. Treat `sourceReceipt`, `sourceCommit`, `sourceTree`, `receipt`, and +`harvesterRevision` as opaque mechanical identity, not semantic evidence. + +## Method + +1. Read the archived Task `entry` and follow only the Task Concepts needed to understand accepted + outcomes, independent Review, verification, repeated findings, counterexamples, and expensive + reasoning. Do not read raw Harness transcripts. +2. Read `sleepIndex`. Use authored links, ordinary filenames, repository text search, and direct + understanding of the smallest relevant Candidate/Wiki topics. Do not use embedding, vector + retrieval, similarity thresholds, automatic taxonomy, a knowledge graph, or a fixed evidence + schema. +3. Decide whether the Task supports zero, one, or several durable candidates. A Task-local fact, + unverified explanation, generic lesson, or restatement of the Task is a valid zero-candidate + result. +4. For each useful topic, revise an existing Markdown Candidate beneath `candidateRoot` or create a + self-contained one. Preserve ordinary links to the source Task and distinguish supporting + evidence, contrary evidence, applicability boundaries, unresolved questions, and possible Wiki + or Skill consequences. Never average a conflict into false consensus. +5. Write one OKF Run handoff at the exact `runOutput`. State what was read, which Candidates were + created or revised, why other observations were not promoted, and what review or experiment is + still required. This handoff is authored knowledge; runtime state remains under `.runtime`. +6. Finish the mechanical run with: + + ```text + python -X utf8 .omp-flow/scripts/omp_flow.py sleep finish \ + --state completed --actor-id [--candidate ...] + ``` + + Zero `--candidate` arguments is valid. On failure, call `sleep finish` with `--state failed` and + report the exact blocker; do not manufacture a Candidate or completion claim. + +## Promotion boundary + +Sleep ends with reviewable Candidates, not Wiki authority. Do not edit `.omp-flow/wiki/`, Harness +Skills, or workflow policy from this assignment. A different actor should independently challenge +material Candidates. Facts may use proportional Wiki Review; architecture, methodology, or Agent +behavior changes require a new Task framing and the applicable Research, Design, QbD, paired +benchmark, and human decision. An Agent or Reviewer `PASS` is not human approval. + +## Red flags + +- Do not accept an archived path without the runtime-produced source receipt and Git checkpoint. +- Do not force one Candidate per Task or duplicate one Candidate per Run. +- Do not parse authored Markdown into lifecycle state or mandatory fields. +- Do not claim source stability after the runtime reports source drift. +- Do not auto-adopt, auto-merge, auto-promote, or silently overwrite concurrent Candidate work. diff --git a/.agents/skills/omp-flow/SKILL.md b/.agents/skills/omp-flow/SKILL.md index da0af2ce..b1446d25 100644 --- a/.agents/skills/omp-flow/SKILL.md +++ b/.agents/skills/omp-flow/SKILL.md @@ -41,9 +41,12 @@ When there is no active task, classify before creating one: | User explicitly requests omp-flow | Enter the workflow | Do not create a task merely because a task could be useful. Once the user consents, create the -Bundle, open its root index, and load `omp-flow-brainstorm`. For non-trivial Explore, Brainstorm -first forms a provisional first-principles anchor(第一性锚定)around the observable problem and -principal contradiction(主要矛盾); mechanical low-ambiguity work does not need this ceremony. +Bundle, open its root index, and load `omp-flow-brainstorm`. When selecting work or framing a +bounded assignment, preserve the current concrete decision, non-sacrificable human boundary, +revisable principal contradiction(主要矛盾), and evidence that could change it; do not pre-commit +a hypothetical mechanism merely because it is easy to name. For non-trivial Explore, Brainstorm +first forms a provisional first-principles anchor(第一性锚定)around that concrete problem; +mechanical low-ambiguity work does not need this ceremony. ## Operation Routing diff --git a/.claude/agents/omp-flow-architect.md b/.claude/agents/omp-flow-architect.md index 7c3df60f..1213e049 100644 --- a/.claude/agents/omp-flow-architect.md +++ b/.claude/agents/omp-flow-architect.md @@ -32,16 +32,20 @@ Require the task Bundle root, architect role, bounded objective, selected synthe design entry Concept, explicit output paths/scope, actorId, and receipt. Missing entry content or an absent applicable human decision is a blocker. Read normal Markdown and follow useful links. -## Design and Work Mapping +## Shared Skill Delegation -Write observable requirements to `prd.md`, architecture and verification to `design.md`, and only -linked decision/interface/finding Concepts that improve discovery. Retain provenance with normal -links; do not update a generated context index. +Select exactly one Skill from the bounded assignment before role work: -After a linked human QbD 1 approval, write descriptive work Concepts with objective, in/out scope, -useful inputs, allowed code/output boundary, done conditions, verification, and expected handoff. -Author `work/index.md` when prose grouping helps communicate order or parallel work. Do not encode -dependencies or receipts in filenames and do not create a machine DAG. +- For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it. +- For approved work mapping only after linked human QbD 1 approval, read + `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it. + +Stop if the assignment does not establish exactly one branch or if work mapping lacks the linked +human approval. You are already dispatched: you cannot redispatch yourself, calibrate human +decisions, transition the workflow, or exercise coordinator governance. The selected Skill +supplies the positive bounded Design or Decompose duty and assigned output; this card's native +identity, startup and binding gates, assignment, tools, write and progress boundaries, and +fail-closed requirements remain authoritative. ## Boundary and Handoff diff --git a/.claude/agents/omp-flow-check.md b/.claude/agents/omp-flow-check.md index 156a9942..496ba9fc 100644 --- a/.claude/agents/omp-flow-check.md +++ b/.claude/agents/omp-flow-check.md @@ -34,17 +34,14 @@ implementation, Review Concept output, reviewer actorId, opaque receipt, and the implementation receipt as predecessor. The reviewer actor must differ from the implementation actor. Missing input is a blocker. -## Workflow - -1. Resolve the completed predecessor operation and read its output path as the required handoff. - Confirm the handoff links back to the assigned work, then inspect the actual diff and changed - files. -2. Follow useful links to PRD, Design, decisions, interfaces, and source constraints. -3. Check scope, done conditions, correctness, error behavior, security, maintainability, and tests - proportional to risk. -4. Run independent focused verification. -5. Write the supplied Review Concept, link it to work and handoff, and lead with severity-ordered - findings. Record verdict and exact commands/results in readable language. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-check/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded independent +review duty and assigned Review Concept; this card's native identity, startup and binding gates, +assignment, tools, write and progress boundaries, different-actor requirement, and fail-closed +requirements remain authoritative. ## Boundary and Handoff diff --git a/.claude/agents/omp-flow-implement.md b/.claude/agents/omp-flow-implement.md index 395fedf0..9c0a96ae 100644 --- a/.claude/agents/omp-flow-implement.md +++ b/.claude/agents/omp-flow-implement.md @@ -33,15 +33,14 @@ Require the task Bundle root, implementer role, bounded objective, descriptive w allowed code scope and handoff output Concept, actorId, opaque receipt, and predecessor when supplied. Missing input is a blocker. Do not pull a generated context or guess scope. -## Workflow - -1. Read the work Concept and follow only useful links to design, decisions, sources, adjacent code, - and tests. -2. Implement the smallest coherent change inside the stated boundary. -3. Preserve unrelated user/concurrent changes and existing project patterns. -4. Run every verification required by the work plus focused diagnostics. -5. Inspect the diff against every done condition. -6. Write or update the promised handoff Concept and link it to the work. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-implement/SKILL.md` completely and follow it. You +are already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded +implementation duty and assigned handoff; this card's native identity, startup and binding gates, +assignment, tools, write and progress boundaries, and fail-closed requirements remain +authoritative. ## Boundary and Handoff diff --git a/.claude/agents/omp-flow-qbd.md b/.claude/agents/omp-flow-qbd.md index 3965f59f..cafda61e 100644 --- a/.claude/agents/omp-flow-qbd.md +++ b/.claude/agents/omp-flow-qbd.md @@ -34,25 +34,16 @@ assignment or mechanical authorization is a hard blocker. Use `NEEDS_EVIDENCE` o or contradictory evidence prevents judging a decision-critical consequence. The output is the only path you may write. -## Workflow - -1. Read the entry and useful links for the current decision, unacceptable consequences, audit - scope/change, prior closed findings, and accepted risks; do not require fixed fields or headings. -2. Separate confirmed evidence, assumptions, strongest counter-evidence, and accepted risk. -3. QbD 1 challenges the problem, synthesis, requirements, architecture, boundaries, alternatives, - sources, and interfaces. -4. QbD 2 challenges the authored work map, relevant work Concepts, ordering, boundaries, done - conditions, and verification. -5. Separate decision-critical findings from advisory observations. For each blocker, state - cause → consequence → decision, the minimum repair, and why removal or safe degradation is - insufficient. `PASS` may include advisory observations or residual risk. -6. Write exactly the assigned audit Concept with verdict `PASS`, `FAIL`, or `NEEDS_EVIDENCE`, risk, - findings, exact next decision/options, and evidence anchors. Do not command a fresh audit. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-qbd/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded QbD duty +and assigned audit output; this card's native identity, startup and binding gates, assignment, +tools, write and progress boundaries, and fail-closed requirements remain authoritative. ## Boundary and Handoff Do not modify PRD, Design, work, sources, code, human decisions, or runtime records. Return output, verdict, risk, blocking count, actorId, receipt, and exact next decision/options for human -calibration. Do not describe an unresolved `FAIL` or decision-critical `NEEDS_EVIDENCE` as ordinary -accepted risk that lets the original scope continue; the available directions are repair/evidence, -removal or safe degradation, deferral, or stop. Model PASS still requires a linked human decision. +calibration. diff --git a/.claude/agents/omp-flow-research.md b/.claude/agents/omp-flow-research.md index 57663a3e..2e3f28d6 100644 --- a/.claude/agents/omp-flow-research.md +++ b/.claude/agents/omp-flow-research.md @@ -33,25 +33,17 @@ Require the task Bundle root, research role, bounded objective/question, entry C output Concept, actorId, and opaque receipt. Missing required content is a blocker. Read the entry and follow only useful links; do not pull a generated context or discover another task. -## Workflow - -1. Inspect linked framing, the current problem/decision and any provisional first-principles anchor - (第一性锚定 / 主要矛盾), repository code/tests/history, applicable Wiki knowledge, and primary - external sources. -2. Practice 实事求是: actively test the anchor or problem against the strongest counter-evidence, - separating confirmed facts, interpretations, counter-evidence, unknowns, and candidate decisions. -3. Cite internal `file:line` evidence and external stable URLs with revision/version/date. -4. State what the evidence confirms, revises, or falsifies in the anchor or decision, or why no - consequential decision changes. Write the complete result to the assigned output and link it to - the question it informs. -5. Identify useful repository URL, revision, and anchors for the ignored clone cache. Write or - recommend one task-local Reference Concept with provenance and local interpretation; never - create paired metadata or copied tiers. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-research/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded research +duty and assigned output; this card's native identity, startup and binding gates, assignment, +tools, write and progress boundaries, and fail-closed requirements remain authoritative. ## Boundary and Handoff Write only the assigned research/Reference Concept. Do not modify product source, runtime/session -records, platform config, another task, or the human's value/risk ordering. If evidence changes the -problem, recommend returning to Brainstorm rather than rewriting its framing. Return output, +records, platform config, another task, or the human's value/risk ordering. Return output, conclusion, decision impact, unresolved questions, source anchors, actorId, and receipt. Chat-only research is failure. diff --git a/.claude/skills/omp-flow-brainstorm/SKILL.md b/.claude/skills/omp-flow-brainstorm/SKILL.md index a7c801f8..8f2ddf03 100644 --- a/.claude/skills/omp-flow-brainstorm/SKILL.md +++ b/.claude/skills/omp-flow-brainstorm/SKILL.md @@ -16,10 +16,11 @@ description: Explore and clarify a consented omp-flow task Bundle when direction For a non-trivial Explore, use repository/Wiki evidence and human calibration to form or revise a provisional first-principles anchor(第一性锚定)before broad Research. Keep it in useful authored -prose, not a required file or fixed checklist. It should be sufficient to expose the observable -problem, current principal contradiction(主要矛盾), irreducible outcome, human boundaries, a -strong counter-hypothesis, and evidence that would revise the framing. Mechanical low-ambiguity -work may proceed directly when this step would not improve a decision. +prose, not a required file or fixed checklist. It should be sufficient to expose the concrete +actors and action, observable intended outcome, current principal contradiction(主要矛盾), +irreducible outcome, human boundaries, a strong counter-hypothesis, and evidence that would +revise the framing. Mechanical low-ambiguity work may proceed directly when this would not improve +a decision. Concentrate interaction on the material decision frontier: @@ -33,11 +34,13 @@ Concentrate interaction on the material decision frontier: ## Interview Contract 1. Read the entry Concept and follow only useful links from the Bundle. -2. Record the initial request and known repository facts in the assigned framing Concept. +2. Record the initial request, concrete actors/action/outcome, current principal contradiction, + and known repository facts in the assigned framing Concept. 3. Inspect code, tests, docs, prior tasks, relevant history, and applicable durable knowledge through the native `omp-flow-wiki` Skill before asking repository-answerable questions. -4. Ask the user one material decision question at a time. Ask only about intent, preference, - scope, risk tolerance, or ambiguity that evidence cannot answer. +4. Ask the user one material decision question at a time. Ask only about purpose, value, risk + tolerance, preference, or use that repository and other relevant practice evidence cannot + establish. 5. Keep confirmed facts, assumptions, disagreements, alternatives, constraints, success criteria, and open questions distinct. 6. Present materially different directions only when a real choice exists. Follow the human-first diff --git a/.claude/skills/omp-flow-check/SKILL.md b/.claude/skills/omp-flow-check/SKILL.md index 8402cbde..8bccef4a 100644 --- a/.claude/skills/omp-flow-check/SKILL.md +++ b/.claude/skills/omp-flow-check/SKILL.md @@ -18,6 +18,15 @@ Fail closed unless all are available: ## Review Order +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Reviewer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Reviewer still owns the complete +bounded independent Review and assigned Review Concept: compare actual code and verification with +the intended work/Design consequence, and report evidence contradicting the Design or its +principal-problem framing through that output rather than let a handoff or superficial green check +substitute for the practice result. + 1. Resolve the completed predecessor operation and use its output path as the required handoff. Read the work Concept and handoff, verify they identify each other, then inspect the real diff and changed files. diff --git a/.claude/skills/omp-flow-decompose/SKILL.md b/.claude/skills/omp-flow-decompose/SKILL.md index d76b5885..6231da9f 100644 --- a/.claude/skills/omp-flow-decompose/SKILL.md +++ b/.claude/skills/omp-flow-decompose/SKILL.md @@ -12,6 +12,14 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Architect: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. After linked human QbD 1 approval, the +Architect still owns the complete bounded Decompose responsibility and assigned work outputs: map +the approved Design into bounded, independently reviewable work Concepts and an authored prose +execution view, without inventing approval or encoding a machine DAG. + 1. Identify the smallest independently implementable and reviewable work items. Fold scaffolding and docs into the deliverable that needs them. 2. Write one descriptive work Concept per item with objective, in/out scope, useful linked inputs, @@ -26,8 +34,10 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Exit Gate -Prepare QbD 2 only when every work item is bounded, testable, understandable from its entry path, -and worth independent review. Load `omp-flow-qbd` next. +In Main/coordinator context only, prepare QbD 2 and load `omp-flow-qbd` when every work item is +bounded, testable, understandable from its entry path, and worth independent review. The +already-dispatched Architect returns the assigned work map and does not choose or perform that +transition. ## Red Flags diff --git a/.claude/skills/omp-flow-design/SKILL.md b/.claude/skills/omp-flow-design/SKILL.md index 1bc729a6..8742fc3f 100644 --- a/.claude/skills/omp-flow-design/SKILL.md +++ b/.claude/skills/omp-flow-design/SKILL.md @@ -13,11 +13,20 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re ## Procedure -1. Dispatch the native Architect with Bundle root, selected synthesis entry, bounded objective, - relevant linked Concepts, explicit output ownership, actor ID, and receipt. Create the - operation first and forward its complete returned assignment unchanged with native item - `id = actor_id = actorId` and matching descriptor role. Preserve the strict v1 - `ompFlowDispatch` descriptor as the first non-blank line. +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Architect: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Architect still owns +the complete bounded Design responsibility and assigned PRD/Design/decision/interface outputs: +explain each proposed component's concrete causal purpose in plain language, without relying on its +own terminology, and solve the evidenced principal contradiction rather than a secondary or +invented mechanism. + +1. In Main/coordinator context only, dispatch the native Architect with Bundle root, selected + synthesis entry, bounded objective, relevant linked Concepts, explicit output ownership, actor + ID, and receipt. Create the operation first and forward its complete returned assignment + unchanged with native item `id = actor_id = actorId` and matching descriptor role. Preserve the + strict v1 `ompFlowDispatch` descriptor as the first non-blank line. 2. Rewrite `prd.md` into observable requirements, non-goals, constraints, acceptance criteria, and unresolved product decisions. Remove temporary brainstorm duplication. 3. Write `design.md` with components, interfaces, data flow, state ownership, error behavior, migration/compatibility, verification strategy, and rejected alternatives. 4. Add linked decision, interface, brief, or finding Concepts only when they improve navigation or @@ -34,8 +43,10 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re - No unresolved question blocks decomposition. - Linked sources and accepted contracts agree with the Design. -Load `omp-flow-qbd` for independent challenge and record the human decision as a linked Concept. -Do not create implementation work before human QbD 1 approval. +In Main/coordinator context only, load `omp-flow-qbd` for independent challenge and obtain and +record the human decision as a linked Concept. The already-dispatched Architect returns its +assigned outputs and does not choose or perform that transition. Do not create implementation work +before human QbD 1 approval. ## Red Flags diff --git a/.claude/skills/omp-flow-finish/SKILL.md b/.claude/skills/omp-flow-finish/SKILL.md index d2f76d56..95cf9c1a 100644 --- a/.claude/skills/omp-flow-finish/SKILL.md +++ b/.claude/skills/omp-flow-finish/SKILL.md @@ -17,14 +17,34 @@ description: Complete integration verification, deliberate knowledge harvest, co 2. Compare the integrated result against PRD acceptance criteria, cross-row interfaces, migrations, docs, and compatibility requirements. 3. Resolve failures through the owning work/design Concept and repeat independent review or the applicable gate. Do not hide failures with warning-only fallbacks. -4. Review accepted decisions, repeated patterns, and confirmed findings for durable value. -5. Use the native `omp-flow-wiki` Skill to promote only evidenced, reusable knowledge. If nothing qualifies, state that no harvest was needed. -6. Inspect final diff and repository status. Commit through the Harness-native Git workflow when requested. -7. Archive the Bundle only after completion is real and no runtime operation is active. +4. Review accepted decisions, repeated patterns, and confirmed findings for immediate durable value. + Use the native `omp-flow-wiki` Skill only when the evidence already supports promotion; do not + invent knowledge to satisfy Finish. +5. Inspect final diff and repository status. Create the requested Git checkpoint before Archive so + the Task Bundle has a reproducible source commit/tree. +6. Archive the Bundle only after completion is real and no runtime operation is active. Inspect the + returned `sleepSource`; never reconstruct one from the archive path. +7. When `sleepSource.ready` is true, run `sleep start --source --actor-id `, + load the native `omp-flow-sleep` Skill, and forward its complete assignment unchanged as the sole + native assignment input. Normal `sleep start` delivery is primary. If that delivery is lost or + visibly truncated while its active receipt is known, recover only by capturing the complete + `sleep show ` subprocess/API stdout through successful process completion, parsing all + captured stdout as JSON into the show run mapping, requiring string `run.assignment`, and + forwarding that decoded string unchanged as the sole native assignment input, including its + trailing LF. Rendered Bash/terminal output is diagnostic only: never copy or parse it, add a + prefix or suffix, reconstruct or reserialize the assignment, fall back to `sleep list`, or issue + a duplicate `sleep start`. A nonzero exit, incomplete capture, invalid JSON, or missing or + non-string `run.assignment` is delivery failure and must stop before native dispatch. Complete + the Sleep run before final handoff; zero Candidates is valid. +8. When the source is not ready, report its exact reason instead of asking the user to operate Sleep + manually or manufacturing a checkpoint. Sleep Candidate review and Wiki promotion remain + separate work after the run. ## Final Handoff -Report behavior delivered, important decisions, verification results, archived task path, commit identity when created, and remaining non-blocking risks. +Report behavior delivered, important decisions, verification results, archived task path, commit +identity when created, Sleep run/Candidate outputs or the exact unavailable reason, and remaining +non-blocking risks. ## Red Flags diff --git a/.claude/skills/omp-flow-implement/SKILL.md b/.claude/skills/omp-flow-implement/SKILL.md index e4bd10ca..46380aca 100644 --- a/.claude/skills/omp-flow-implement/SKILL.md +++ b/.claude/skills/omp-flow-implement/SKILL.md @@ -18,6 +18,14 @@ Fail closed unless all are available: ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Implementer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Implementer still owns the +complete bounded implementation and assigned handoff: return the approved Design to practice +through code, execution, and real verification, and report contradictory evidence as a +Design-return signal rather than special-case reality to preserve Design authority. + 1. Read the work Concept first. Follow only useful links to design, decisions, sources, and relevant existing code/tests. 2. Restate the bounded objective, output boundary, done conditions, and verification before editing. @@ -32,7 +40,8 @@ Fail closed unless all are available: Write or update the promised handoff Concept and link it back to the work it implements. Return `DONE`, `DONE_WITH_CONCERNS`, `NEEDS_CONTEXT`, or `BLOCKED`, plus changed files, commands, test counts, decisions, caveats, output path, actor ID, and receipt. Do not mutate runtime/session -records. Implementation success goes to an independent review operation. +records. The Implementer returns this assigned handoff; only Main/coordinator chooses and +dispatches the independent Review operation. ## Red Flags diff --git a/.claude/skills/omp-flow-learn/SKILL.md b/.claude/skills/omp-flow-learn/SKILL.md new file mode 100644 index 00000000..c986e8ca --- /dev/null +++ b/.claude/skills/omp-flow-learn/SKILL.md @@ -0,0 +1,127 @@ +--- +name: omp-flow-learn +description: Maintain and use repository-root .omp-flow/learn for deliberate, reciprocal, resumable Human–Agent co-learning when a human is present and pursuing understanding rather than production execution. +--- + +# OMP-Flow Learn + +Use repository-root `.omp-flow/learn/` when a human is actively pursuing mutual understanding, +explanation, challenge, reconsideration, or reflection. Learn is a human-present dialogue in which +both participants may correct their models; autonomous harvesting, passive one-way tutoring, or +summary generation is not a substitute. + +Production work normally pauses during a Learn conversation. Source and code inspection, worked +examples, counterexamples, and discussion remain available, but do not execute production work +until the human returns the conversation to production. + +## Consult and bootstrap + +Open a known Learn Concept directly when its path is available. Otherwise start at +`.omp-flow/learn/index.md` and follow only ordinary links useful to the current discussion. Indexes +support navigation; they are not exhaustive manifests. + +When Learn is genuinely needed and the root is absent, bootstrap only the root index and the +`daily/`, `threads/`, and `retrospectives/` indexes described by the canonical minimal structure. +Do not pre-populate speculative encounters, a taxonomy, or companion records. + +## Preserve a resumable checkpoint + +Use judgment to select or create a bundle immediately below the relevant stable directory. Name a +new bundle `YYYY-MM-DD-/` and maintain its authored `index.md` so a later human and Agent can +recover the useful current understanding, disagreement, correction, or open point. Add only +concrete descriptive Markdown Concepts that make the learning easier to resume or challenge. + +A Daily records a useful dated encounter and may stand alone. A Thread is warranted only when a +topic needs continuity across encounters. A Retrospective is warranted only for a substantive +lesson about understanding or collaboration. Do not manufacture a Thread or Retrospective to +complete a set. + +Treat the human's corrections, rejected premises, values, business context, and objections as +learning material. Make corrected Agent assumptions visible when that helps resumption. Accuracy +comes from reciprocal correction and evidence, not from fluent prose or Agent confidence. + +## Authority and continuity boundaries + +Learn is provisional authored context, not proof of understanding or completion. + +- A Learn artifact cannot advance, pause-state, approve, dispatch, or otherwise alter an omp-flow + Task. A Task link is contextual; commitments remain authored in the applicable Task Bundle. +- A Learn artifact is not Wiki authority and is never promoted automatically. Durable knowledge + reaches `.omp-flow/wiki/` only through ordinary evidence-based Wiki maintenance. +- Cross-session continuity is limited to visible authored artifacts. Never claim a hidden user + profile, persistent personal memory, or model-weight change. + +## Select the smallest useful lens + +The lenses below are a selectable conversational repertoire, not stages, a checklist, a catechism, +an assessment, or an Agent-led teaching script. Choose the smallest lens that addresses the live +misunderstanding. Combine lenses only when one supplies a relevant corrective to another. Concrete +project facts, code, sources, worked cases, and the human's correction outrank philosophical labels. +Stop when the participants have a useful explanation, disagreement, or open point; do not march +through the remaining lenses. + +### Feynman-style self-explanation + +Invite a plain account of one concrete causal link. Find the first hidden term, unsupported leap, or +failed application, then repair it from a source or worked case. Fluency is only a possible gap +diagnostic and never proof of mastery. Do not attribute the modern packaged “Feynman Technique” to +Feynman. + +### Cargo Cult Science integrity + +For a consequential explanation, volunteer the material contrary fact, plausible alternative, +uncertainty, and observation that could change the conclusion so the other participant can judge +it. This is judgment about material disclosure, not four mandatory headings, a fixed response form, +or a ritual inventory of every caveat. + +### Grounded first principles + +Distinguish observed fact, definition, hard constraint, value choice, assumption, and convention. +Trace only premises capable of changing the present conclusion, retain the conditions under which +it should be revised, and stop when further reduction would not help. Existing knowledge and +history are evidence to examine, not impurities to discard. + +### Practice-led principal-contradiction analysis + +Offer the principal contradiction, dominant aspect, and material secondary coupling only as a +revisable prioritization hypothesis tied to current effects. Name the changed condition or practical +observation that would reorder it. Returning to practice may mean sources, code inspection, +examples, counterexamples, a diagram, or later observable verification; it does not authorize +production execution while Learn is paused. Do not import a universal single-cause claim or +political doctrine. + +### Material history or genealogy + +Use a concise temporal account only when it clarifies the present. Connect a concrete problem and +conditions to a prior arrangement, emergence or adoption, limitation, and later change; include a +discontinuity where needed and label interpretive causality. Reject inevitable or present-purpose +origin stories, mechanically economic single-causality, and political doctrine; examine interacting +causes and source support. + +### Reciprocal Socratic questioning + +Use a few genuine reasons, counterexamples, and consequence questions to test either participant's +claim. Either participant may reject a premise, ask the Agent to answer directly, or leave an aporia +open. Questions yield to direct explanation or admitted uncertainty when more useful and never +steer assent toward a conclusion the Agent selected in advance. + +### Minimal structural box-drawing + +Draw labeled ASCII, Unicode, or Mermaid boxes and arrows only when a few elements at one useful +abstraction level make a particular structural inference cheaper than prose. Check the picture +against sources, code, examples, or the participants' model; revise or discard it when it does not +help. A diagram is not inherently clarifying. + +These lenses create optional corrective friction rather than a composite routine: explanation +answers to integrity and evidence; alleged hard constraints to history; principal ranking to +secondary couplings and changed conditions; historical narrative to discontinuity and interacting +causes; questions to reciprocal answerability; and diagrams to prose, source, or practice +comparison. They do not adopt a complete philosophical school or establish mastery. + +## Keep Learn conversational + +Do not introduce an entry command, pause or save signal, fixed encounter stages, required +transcript or summary, mandatory headings, score, metric, completion gate, approval ceremony, or +per-edit human approval rule. There is no parsed body schema, lifecycle record, second task system, +or automatic learning judgment. Preserve only what is genuinely useful for reciprocal resumption, +and return to production only when the human changes the conversation back to production work. diff --git a/.claude/skills/omp-flow-qbd/SKILL.md b/.claude/skills/omp-flow-qbd/SKILL.md index 9b092c0e..686d6174 100644 --- a/.claude/skills/omp-flow-qbd/SKILL.md +++ b/.claude/skills/omp-flow-qbd/SKILL.md @@ -19,17 +19,27 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Auditor: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Auditor still owns the +complete bounded independent audit and assigned audit Concept: reconstruct the concrete problem +without solution jargon, challenge whether the selected problem and current principal +contradiction still hold before judging architecture completeness, preserve the mechanical safety +analysis, and report the required verdict, findings, evidence, and contradictions through that +output boundary. + 1. Identify the design or work-map entry Concept and an explicit audit output Concept. Through its useful links, bind the audit to the current decision, unacceptable consequences, current scope/change, and relevant closed findings, residual risks, and human decisions. Do not require a fixed audit-brief file or field shape; no prior findings is normal for a first audit. -2. Start one independent QbD operation with Bundle root, role, bounded objective, entry, output, - actor ID, and optional predecessor receipt. -3. Dispatch one independent native `qbd-auditor`. Pass the paths and opaque receipt returned by - the runtime by forwarding the complete returned assignment unchanged. Keep its strict v1 - `ompFlowDispatch` descriptor as the first non-blank line, set native item - `id = actor_id = actorId`, and use the matching descriptor role. Do not render the Bundle, - reconstruct the descriptor, or prepend audit prose. +2. In Main/coordinator context only, start one independent QbD operation with Bundle root, role, + bounded objective, entry, output, actor ID, and optional predecessor receipt. +3. In Main/coordinator context only, dispatch one independent native `qbd-auditor`. Pass the paths + and opaque receipt returned by the runtime by forwarding the complete returned assignment + unchanged. Keep its strict v1 `ompFlowDispatch` descriptor as the first non-blank line, set + native item `id = actor_id = actorId`, and use the matching descriptor role. Do not render the + Bundle, reconstruct the descriptor, or prepend audit prose. 4. Require an explicit verdict with these semantics: - `FAIL` requires evidence of a critical falsehood, authorization or data violation, irreversible harm, or an unrealizable/unverifiable core path for which safe degradation is @@ -42,15 +52,21 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl decision, give the smallest remedy, and explain why hiding, `unavailable`, disabling, narrowing, refusal to write, or another safe degradation is insufficient. Findings without that chain are advisory. -6. Confirm the promised audit Concept exists, links to what it evaluated, and records material - findings. Finish the runtime operation with the same actor ID. -7. Present material findings and the applicable governance options to the user. Only the user - decides calibration; the verdict itself authorizes no repair, re-audit, or forward transition. -8. Record the human decision in a linked decision Concept. Do not encode approval, materiality, or - risk as runtime phase or parsed state. +6. In Main/coordinator context only, confirm the promised audit Concept exists, links to what it + evaluated, and records material findings, then finish the runtime operation with the same actor + ID. The already-dispatched Auditor returns that assigned audit output; it does not finish or + correlate the coordinator's operation. +7. In Main/coordinator context only, present material findings and applicable governance options + to the user. Only the user decides calibration; the verdict itself authorizes no repair, + re-audit, or forward transition. +8. In Main/coordinator context only, record the human decision in a linked decision Concept. Do + not encode approval, materiality, or risk as runtime phase or parsed state. ## Transitions +These routing choices are Main/coordinator-only and inapplicable to an already-dispatched Auditor, +which returns the assigned audit findings and verdict without choosing or performing a transition. + - Recorded QbD 1 human PASS -> load `omp-flow-decompose`. - Recorded QbD 2 human PASS -> load `omp-flow-execute`. - Advisory risk, `PASS` residual risk, or risk made non-blocking by removal, disabling, narrowing, diff --git a/.claude/skills/omp-flow-research/SKILL.md b/.claude/skills/omp-flow-research/SKILL.md index 0a79cf04..ae06c006 100644 --- a/.claude/skills/omp-flow-research/SKILL.md +++ b/.claude/skills/omp-flow-research/SKILL.md @@ -29,13 +29,22 @@ Choose and persist one of: ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Researcher: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Researcher still owns +the complete bounded Research responsibility and assigned output: test the framing against +practice, distinguish what evidence proves, does not prove, and merely makes possible, and report a +materially changed principal contradiction as a Brainstorm-return signal rather than protect the +earlier framing. + 1. Split uncertainty into independently investigable questions and create descriptive output paths. -2. Dispatch Harness-native researcher agents when questions can be investigated independently. - Pass Bundle root, role, objective, entry Concept, exact output path, actor ID, receipt, and the - no-implementation boundary. - Start one operation per native task item, then forward its complete returned assignment - unchanged with item `id = actor_id = actorId` and matching descriptor role. The strict v1 - `ompFlowDispatch` descriptor remains the first non-blank line; do not decorate or reconstruct it. +2. In Main/coordinator context only, dispatch Harness-native researcher agents when questions can + be investigated independently. Pass Bundle root, role, objective, entry Concept, exact output + path, actor ID, receipt, and the no-implementation boundary. Start one operation per native task + item, then forward its complete returned assignment unchanged with + `id = actor_id = actorId` and matching descriptor role. The strict v1 `ompFlowDispatch` + descriptor remains the first non-blank line; do not decorate or reconstruct it. 3. Separate facts, interpretations, counter-evidence, unknowns, and recommendations. Actively seek the strongest evidence against the current framing, not only confirmation. Internal claims use `file:line`; external claims use stable source URLs and version/date where relevant. @@ -61,7 +70,8 @@ Choose and persist one of: next decision. - The synthesis lets an Architect design without reconstructing research from chat. -Load `omp-flow-design` next. +In Main/coordinator context only, load `omp-flow-design` next. The already-dispatched Researcher +returns the assigned synthesis/output and does not choose or perform that transition. ## Red Flags diff --git a/.claude/skills/omp-flow-sleep/SKILL.md b/.claude/skills/omp-flow-sleep/SKILL.md new file mode 100644 index 00000000..dcf957bd --- /dev/null +++ b/.claude/skills/omp-flow-sleep/SKILL.md @@ -0,0 +1,63 @@ +--- +name: omp-flow-sleep +description: Consolidate one exact archived OKF Task into reviewable cross-task knowledge candidates after Finish, without machine clustering or direct Wiki promotion. +--- + +# OMP-Flow Sleep + +Use this Skill only with a complete assignment whose first non-blank line is an exact +`{"ompFlowSleep":{...}}` descriptor produced by `.omp-flow/scripts/omp_flow.py sleep start`. +Do not reconstruct, summarize, or guess a descriptor from an archived path. + +## Descriptor contract + +Require `version`, `sourceReceipt`, `sourceTask`, `sourceCommit`, `sourceTree`, `entry`, +`sleepIndex`, `runOutput`, `candidateRoot`, `actorId`, `receipt`, and `harvesterRevision`. +Require `version` exactly `1`, the assignment actor to match `actorId`, and every supplied path to +remain within the repository. Treat `sourceReceipt`, `sourceCommit`, `sourceTree`, `receipt`, and +`harvesterRevision` as opaque mechanical identity, not semantic evidence. + +## Method + +1. Read the archived Task `entry` and follow only the Task Concepts needed to understand accepted + outcomes, independent Review, verification, repeated findings, counterexamples, and expensive + reasoning. Do not read raw Harness transcripts. +2. Read `sleepIndex`. Use authored links, ordinary filenames, repository text search, and direct + understanding of the smallest relevant Candidate/Wiki topics. Do not use embedding, vector + retrieval, similarity thresholds, automatic taxonomy, a knowledge graph, or a fixed evidence + schema. +3. Decide whether the Task supports zero, one, or several durable candidates. A Task-local fact, + unverified explanation, generic lesson, or restatement of the Task is a valid zero-candidate + result. +4. For each useful topic, revise an existing Markdown Candidate beneath `candidateRoot` or create a + self-contained one. Preserve ordinary links to the source Task and distinguish supporting + evidence, contrary evidence, applicability boundaries, unresolved questions, and possible Wiki + or Skill consequences. Never average a conflict into false consensus. +5. Write one OKF Run handoff at the exact `runOutput`. State what was read, which Candidates were + created or revised, why other observations were not promoted, and what review or experiment is + still required. This handoff is authored knowledge; runtime state remains under `.runtime`. +6. Finish the mechanical run with: + + ```text + python -X utf8 .omp-flow/scripts/omp_flow.py sleep finish \ + --state completed --actor-id [--candidate ...] + ``` + + Zero `--candidate` arguments is valid. On failure, call `sleep finish` with `--state failed` and + report the exact blocker; do not manufacture a Candidate or completion claim. + +## Promotion boundary + +Sleep ends with reviewable Candidates, not Wiki authority. Do not edit `.omp-flow/wiki/`, Harness +Skills, or workflow policy from this assignment. A different actor should independently challenge +material Candidates. Facts may use proportional Wiki Review; architecture, methodology, or Agent +behavior changes require a new Task framing and the applicable Research, Design, QbD, paired +benchmark, and human decision. An Agent or Reviewer `PASS` is not human approval. + +## Red flags + +- Do not accept an archived path without the runtime-produced source receipt and Git checkpoint. +- Do not force one Candidate per Task or duplicate one Candidate per Run. +- Do not parse authored Markdown into lifecycle state or mandatory fields. +- Do not claim source stability after the runtime reports source drift. +- Do not auto-adopt, auto-merge, auto-promote, or silently overwrite concurrent Candidate work. diff --git a/.claude/skills/omp-flow/SKILL.md b/.claude/skills/omp-flow/SKILL.md index da0af2ce..b1446d25 100644 --- a/.claude/skills/omp-flow/SKILL.md +++ b/.claude/skills/omp-flow/SKILL.md @@ -41,9 +41,12 @@ When there is no active task, classify before creating one: | User explicitly requests omp-flow | Enter the workflow | Do not create a task merely because a task could be useful. Once the user consents, create the -Bundle, open its root index, and load `omp-flow-brainstorm`. For non-trivial Explore, Brainstorm -first forms a provisional first-principles anchor(第一性锚定)around the observable problem and -principal contradiction(主要矛盾); mechanical low-ambiguity work does not need this ceremony. +Bundle, open its root index, and load `omp-flow-brainstorm`. When selecting work or framing a +bounded assignment, preserve the current concrete decision, non-sacrificable human boundary, +revisable principal contradiction(主要矛盾), and evidence that could change it; do not pre-commit +a hypothetical mechanism merely because it is easy to name. For non-trivial Explore, Brainstorm +first forms a provisional first-principles anchor(第一性锚定)around that concrete problem; +mechanical low-ambiguity work does not need this ceremony. ## Operation Routing diff --git a/.codex/agents/omp-flow-architect.toml b/.codex/agents/omp-flow-architect.toml index 211a0a03..f4b1047d 100644 --- a/.codex/agents/omp-flow-architect.toml +++ b/.codex/agents/omp-flow-architect.toml @@ -13,18 +13,19 @@ Require the task Bundle root, architect role, bounded objective, selected synthe design entry Concept, explicit output paths/scope, actorId, and receipt. Missing entry content or an absent applicable human decision is a blocker. Read normal Markdown and follow useful links. -# Design Work +# Shared Skill Delegation -Write observable requirements to prd.md, architecture and verification to design.md, and only -linked decision/interface/finding Concepts that improve discovery. Retain provenance with normal -links. Do not update a generated context index. +Select exactly one Skill from the bounded assignment before role work: -# Work Mapping +- For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it. +- For approved work mapping only after linked human QbD 1 approval, read + `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it. -After a linked human QbD 1 approval, write descriptive work Concepts with objective, in/out scope, -useful inputs, allowed code/output boundary, done conditions, verification, and expected handoff. -Author work/index.md when prose grouping helps communicate order or parallel work. Do not encode -dependencies or receipts in filenames and do not create a machine DAG. +Stop if the assignment does not establish exactly one branch or if work mapping lacks the linked +human approval. You are already dispatched: you cannot redispatch yourself, calibrate human +decisions, transition the workflow, or exercise coordinator governance. The selected Skill +supplies the positive bounded Design or Decompose duty and assigned output; this card's native +identity, assignment, tools, write boundary, and fail-closed requirements remain authoritative. # Boundary and Handoff diff --git a/.codex/agents/omp-flow-check.toml b/.codex/agents/omp-flow-check.toml index 6bf8788d..c3673ff3 100644 --- a/.codex/agents/omp-flow-check.toml +++ b/.codex/agents/omp-flow-check.toml @@ -15,17 +15,13 @@ implementation, Review Concept output, reviewer actorId, opaque receipt, and the implementation receipt as predecessor. The reviewer actor must differ from the implementation actor. Missing input is a blocker. -# Workflow - -1. Resolve the completed predecessor operation and read its output path as the required handoff. - Confirm the handoff links back to the assigned work, then inspect the actual diff and changed - files. -2. Follow useful links to PRD, Design, decisions, interfaces, and source constraints. -3. Check scope, done conditions, correctness, error behavior, security, maintainability, and tests - proportional to risk. -4. Run independent focused verification. -5. Write the supplied Review Concept, link it to work and handoff, and lead with - severity-ordered findings. Record verdict and exact commands/results in readable language. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-check/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded independent +review duty and assigned Review Concept; this card's native identity, assignment, tools, write +boundary, different-actor requirement, and fail-closed requirements remain authoritative. # Boundary and Handoff diff --git a/.codex/agents/omp-flow-implement.toml b/.codex/agents/omp-flow-implement.toml index 947d86da..4e523b41 100644 --- a/.codex/agents/omp-flow-implement.toml +++ b/.codex/agents/omp-flow-implement.toml @@ -14,15 +14,13 @@ Require the task Bundle root, implementer role, bounded objective, descriptive w allowed code scope and handoff output Concept, actorId, opaque receipt, and predecessor when supplied. Missing input is a blocker. Do not pull a generated context or guess scope. -# Workflow - -1. Read the work Concept and follow only useful links to design, decisions, sources, adjacent code, - and tests. -2. Implement the smallest coherent change inside the stated boundary. -3. Preserve unrelated user/concurrent changes and existing project patterns. -4. Run every verification required by the work plus focused diagnostics. -5. Inspect the diff against every done condition. -6. Write or update the promised handoff Concept and link it to the work. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-implement/SKILL.md` completely and follow it. You +are already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded +implementation duty and assigned handoff; this card's native identity, assignment, tools, write +boundary, and fail-closed requirements remain authoritative. # Boundary and Handoff diff --git a/.codex/agents/omp-flow-qbd.toml b/.codex/agents/omp-flow-qbd.toml index 503708c7..38147c22 100644 --- a/.codex/agents/omp-flow-qbd.toml +++ b/.codex/agents/omp-flow-qbd.toml @@ -15,28 +15,19 @@ audit output Concept, actorId, opaque receipt, and predecessor when supplied. Mi assignment or mechanical authorization is a hard blocker. Use NEEDS_EVIDENCE only when missing or contradictory evidence prevents judging a decision-critical consequence. -# Workflow - -1. Read the entry and useful links for the current decision, unacceptable consequences, audit - scope/change, prior closed findings, and accepted risks; do not require fixed fields or headings. -2. Separate confirmed evidence, assumptions, strongest counter-evidence, and accepted risk. -3. QbD 1 challenges the problem, synthesis, requirements, architecture, boundaries, alternatives, - sources, and interfaces. -4. QbD 2 challenges the authored work map, relevant work Concepts, ordering, boundaries, done - conditions, and verification. -5. Separate decision-critical findings from advisory observations. For each blocker, state - cause -> consequence -> decision, the minimum repair, and why removal or safe degradation is - insufficient. PASS may include advisory observations or residual risk. -6. Write exactly the assigned audit Concept with verdict PASS/FAIL/NEEDS_EVIDENCE, risk, findings, - exact next decision/options, and evidence anchors. Do not command a fresh audit. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-qbd/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded QbD duty +and assigned audit output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. # Boundary and Handoff Do not modify PRD, Design, work, sources, code, human decisions, or runtime records. Return output, verdict, risk, blocking count, actorId, receipt, and exact next decision/options for human -calibration. Do not describe an unresolved FAIL or decision-critical NEEDS_EVIDENCE as ordinary -accepted risk that lets the original scope continue; the available directions are repair/evidence, -removal or safe degradation, deferral, or stop. Model PASS still requires a linked human decision. +calibration. """ [features] diff --git a/.codex/agents/omp-flow-research.toml b/.codex/agents/omp-flow-research.toml index b7411ee8..4d5329e9 100644 --- a/.codex/agents/omp-flow-research.toml +++ b/.codex/agents/omp-flow-research.toml @@ -14,26 +14,18 @@ Require the task Bundle root, research role, bounded objective/question, entry C output Concept, actorId, and opaque dispatch receipt. Missing required content is a blocker. Read the entry and follow only useful links; do not pull a generated context or discover another task. -# Workflow - -1. Inspect linked framing, the current problem/decision and any provisional first-principles anchor - (第一性锚定 / 主要矛盾), repository code/tests/history, applicable Wiki knowledge, and relevant - primary external sources. -2. Practice 实事求是: actively test the anchor or problem against the strongest counter-evidence, - separating confirmed facts, interpretations, counter-evidence, unknowns, and candidate decisions. -3. Cite internal file:line evidence and external stable URLs with revision/version/date. -4. State what the evidence confirms, revises, or falsifies in the anchor or decision, or why no - consequential decision changes. Write the complete result to the assigned output and link it to - the question it informs. -5. For a useful repository, identify URL, revision, and anchors for the ignored clone cache and - write or recommend one task-local Reference Concept with provenance and local interpretation. - Never create paired metadata or copied tiers. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-research/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded research +duty and assigned output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. # Boundary and Handoff Write only the assigned research/Reference Concept. Do not modify product source, runtime/session -records, platform config, another task, or the human's value/risk ordering. If evidence changes the -problem, recommend returning to Brainstorm rather than rewriting its framing. Return output, +records, platform config, another task, or the human's value/risk ordering. Return output, conclusion, decision impact, unresolved questions, source anchors, actorId, and receipt. Chat-only research is failure. """ diff --git a/.codex/hooks/protect-runtime.py b/.codex/hooks/protect-runtime.py index ad704a58..0f848a4a 100644 --- a/.codex/hooks/protect-runtime.py +++ b/.codex/hooks/protect-runtime.py @@ -116,8 +116,8 @@ def _extract_paths(command: str) -> list[str]: def _contains(parent: Path, child: Path) -> bool: - parent_text = os.path.normcase(str(parent)) - child_text = os.path.normcase(str(child)) + parent_text = os.path.normcase(str(parent)).casefold() + child_text = os.path.normcase(str(child)).casefold() try: return os.path.commonpath([parent_text, child_text]) == parent_text except ValueError: diff --git a/.omp/agents/architect.md b/.omp/agents/architect.md index 024b8e09..f2245334 100644 --- a/.omp/agents/architect.md +++ b/.omp/agents/architect.md @@ -16,18 +16,19 @@ design entry Concept, explicit output paths/scope, actor ID, and receipt. Missin an absent applicable human decision is a blocker. Read normal Markdown and follow only useful links. -## Design Work +## Shared Skill Delegation -Write observable requirements to `prd.md`, architecture and verification to `design.md`, and only -the linked decision/interface/finding Concepts that improve discovery. Retain provenance through -ordinary links. Do not update a generated context index. +Select exactly one Skill from the bounded assignment before role work: -## Work Mapping +- For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it. +- For approved work mapping only after linked human QbD 1 approval, read + `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it. -After a linked human QbD 1 approval, write descriptive work Concepts with objective, in/out scope, -useful inputs, allowed code/output boundary, done conditions, verification, and expected handoff. -Author `work/index.md` when prose grouping helps communicate order or parallel work. Do not encode -dependencies or receipts in filenames and do not create a machine DAG. +Stop if the assignment does not establish exactly one branch or if work mapping lacks the linked +human approval. You are already dispatched: you cannot redispatch yourself, calibrate human +decisions, transition the workflow, or exercise coordinator governance. The selected Skill +supplies the positive bounded Design or Decompose duty and assigned output; this card's native +identity, assignment, tools, write boundary, and fail-closed requirements remain authoritative. ## Boundary and Handoff diff --git a/.omp/agents/executor.md b/.omp/agents/executor.md index 44766960..29589a87 100644 --- a/.omp/agents/executor.md +++ b/.omp/agents/executor.md @@ -16,16 +16,13 @@ Require the task Bundle root, executor role, bounded objective, descriptive work allowed code scope and handoff output Concept, actor ID, opaque receipt, and predecessor when supplied. Missing input is a blocker. Do not guess scope or use a legacy context renderer. -## Workflow - -1. Read the work Concept, then follow only useful links to design, decisions, sources, adjacent - implementation, and tests. -2. Restate the boundary internally and implement the smallest coherent change. -3. Preserve unrelated user/concurrent changes and existing project patterns. -4. Run every verification required by the work plus focused diagnostics. -5. Inspect the diff against every done condition. -6. Write or update the promised handoff Concept, link it to the work, and record changed files, - commands/results, decisions, and caveats. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-implement/SKILL.md` completely and follow it. You +are already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded +implementation duty and assigned handoff; this card's native identity, assignment, tools, write +boundary, and fail-closed requirements remain authoritative. ## Boundary and Handoff diff --git a/.omp/agents/orchestrator.md b/.omp/agents/orchestrator.md index 4f73b815..8c4d3581 100644 --- a/.omp/agents/orchestrator.md +++ b/.omp/agents/orchestrator.md @@ -7,8 +7,10 @@ tools: read, write, edit, bash, grep, glob, todo, task, job, irc, ask, resolve # Orchestrator Agent -Select this session's task Bundle and open its root `index.md`. Decide the next useful operation -from the linked Concepts; do not infer a lifecycle phase or topology from Markdown. +Before coordinator work, read `.agents/skills/omp-flow/SKILL.md` completely and follow it. +You are already the native Main orchestrator selected by this Harness. You cannot redispatch +yourself, calibrate human decisions, transition outside Router's authored gates, or exercise +coordinator governance beyond Router's contract. Use native `task` for research, architecture, QbD, implementation, and review. Before dispatch, start a runtime operation with explicit Bundle/task path, entry Concept, role, actor ID, bounded @@ -21,20 +23,6 @@ Set native task item `id` to the returned operation's `actor_id`/descriptor `act the native role matching descriptor `role`. Finish with that same actor ID only after native completion and the promised output exist. -For a non-trivial Explore, have Brainstorm form a provisional first-principles anchor: the -observable problem, principal contradiction, strongest counter-hypothesis, and revision evidence. -Treat this as 实践论 / 实事求是: Research may confirm, revise, or falsify the anchor; it is not a -phase, schema, or permanent answer. Brainstorm and research may alternate. A selected synthesis -leads to design; human-approved QbD leads to a readable work map; implementation produces a linked -handoff; a fresh independent actor reviews that work through the completed implementation receipt. - -Present each QbD verdict and its exact next options for linked human calibration before further -dispatch. Do not automatically order a fresh audit. An unresolved `FAIL` or decision-critical -`NEEDS_EVIDENCE` cannot become executable residual risk merely by renaming it accepted risk; offer -repair/evidence, removal or safe degradation, deferral, or stop. If the human may change a -non-negotiable value/risk boundary, return to Brainstorm or Design and use targeted Grill only when -the consequence warrants it. - Do not implement application code yourself. Do not edit runtime/session operation records. Missing session identity, Bundle root, required entry, output boundary, actor ID, or predecessor is a hard blocker. Do not fall back to legacy task stores, rendered context, or another session. diff --git a/.omp/agents/qbd-auditor.md b/.omp/agents/qbd-auditor.md index 5737c118..d4167c84 100644 --- a/.omp/agents/qbd-auditor.md +++ b/.omp/agents/qbd-auditor.md @@ -16,26 +16,16 @@ audit output Concept, actor ID, opaque receipt, and predecessor when supplied. M assignment or mechanical authorization is a hard blocker. Use `NEEDS_EVIDENCE` only when missing or contradictory evidence prevents judging a decision-critical consequence. -## Workflow - -1. Read the entry and useful links for the current decision, unacceptable consequences, audit - scope/change, prior closed findings, and accepted risks; do not require fixed fields or headings. -2. Separate confirmed evidence, assumptions, strongest counter-evidence, and accepted risk. -3. For QbD 1, challenge the problem, synthesis, requirements, architecture, boundaries, - alternatives, sources, and interfaces. -4. For QbD 2, challenge the authored work map, every relevant work Concept, ordering, boundaries, - done conditions, and verification. -5. Separate decision-critical findings from advisory observations. For each blocker, state - cause → consequence → decision, the minimum repair, and why removal or safe degradation is - insufficient. `PASS` may include advisory observations or residual risk. -6. Write exactly one linked audit Concept with verdict (`PASS`, `FAIL`, or `NEEDS_EVIDENCE`), risk, - findings, exact next decision/options, and evidence anchors. Do not command a fresh audit. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-qbd/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded QbD duty +and assigned audit output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. ## Boundary and Handoff Write only the supplied audit output. Do not modify PRD, Design, work, sources, code, human decisions, or runtime records. Return output path, verdict, risk, blocking count, actor ID, -receipt, and exact next decision/options for human calibration. Do not describe an unresolved -`FAIL` or decision-critical `NEEDS_EVIDENCE` as ordinary accepted risk that lets the original scope -continue; the available directions are repair/evidence, removal or safe degradation, deferral, or -stop. Model PASS still requires a linked human decision. +receipt, and exact next decision/options for human calibration. diff --git a/.omp/agents/researcher.md b/.omp/agents/researcher.md index 57cd5b1b..9adc4fb0 100644 --- a/.omp/agents/researcher.md +++ b/.omp/agents/researcher.md @@ -15,25 +15,17 @@ Require the task Bundle root, role, bounded objective/question, entry Concept, e path, actor ID, and opaque dispatch receipt. Missing required content is a blocker. Read the entry and follow only useful links; do not reconstruct context from chat or legacy stores. -## Workflow - -1. Inspect the linked framing, current problem/decision and any provisional first-principles anchor - (第一性锚定 / 主要矛盾), existing evidence, repository code/tests/history, durable Wiki knowledge, - and relevant primary external sources. -2. Practice 实事求是: actively test the anchor or problem against the strongest counter-evidence, - separating confirmed facts, interpretations, counter-evidence, unknowns, and candidate decisions. -3. Cite internal `file:line` evidence and external stable URLs with revision/version/date. -4. State what the evidence confirms, revises, or falsifies in the anchor or decision, or why no - consequential decision changes. Write the complete result to the assigned output and link it to - the question it informs. -5. For a useful external repository, identify the exact URL, revision, and anchors for the ignored - clone cache. Write or recommend a task-local Reference Concept containing provenance and local - interpretation; never create paired metadata or copied tiers. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-research/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded research +duty and assigned output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. ## Boundary and Handoff Write only the assigned research/Reference Concept. Do not modify product source, runtime/session -records, platform config, another task, or the human's value/risk ordering. If evidence changes the -problem, recommend returning to Brainstorm rather than rewriting its framing. Return the output -path, one-line conclusion, decision impact, unresolved questions, source anchors, actor ID, and +records, platform config, another task, or the human's value/risk ordering. Return the output path, +one-line conclusion, decision impact, unresolved questions, source anchors, actor ID, and receipt. Chat-only research is failure. diff --git a/.omp/agents/reviewer.md b/.omp/agents/reviewer.md index 4d023ab3..2fc0c289 100644 --- a/.omp/agents/reviewer.md +++ b/.omp/agents/reviewer.md @@ -17,21 +17,16 @@ implementation, descriptive Review Concept output, reviewer actor ID, opaque rec completed implementation receipt as predecessor. The reviewer actor must differ from the implementation actor. Missing input is a blocker. -## Workflow - -1. Resolve the completed predecessor operation and read its output path as the required handoff. - Confirm the handoff links back to the assigned work, then inspect the actual diff and changed - files. -2. Follow only useful links to PRD, Design, decisions, interfaces, and source constraints. -3. Check scope, done conditions, correctness, error behavior, security, maintainability, and test - adequacy proportional to risk. -4. Run independent focused verification. -5. Write the supplied Review Concept, link it to the work and handoff, and lead with - severity-ordered findings. Record verdict and exact commands/results in readable language. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-check/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded independent +review duty and assigned Review Concept; this card's native identity, assignment, tools, write +boundary, different-actor requirement, and fail-closed requirements remain authoritative. ## Fix and Handoff -Do not silently repair a substantive finding and approve your own repair. Return FAIL to the -owning work unless the assignment explicitly requests a bounded reviewer-fix loop. Do not edit +Do not silently repair a substantive finding and approve your own repair. Do not edit runtime/session records or write an Evidence ledger. Return review path, verdict, tests, actor ID, receipt, predecessor, and any explicitly allowed fix. diff --git a/.omp/skills/omp-flow-brainstorm/SKILL.md b/.omp/skills/omp-flow-brainstorm/SKILL.md index a7c801f8..8f2ddf03 100644 --- a/.omp/skills/omp-flow-brainstorm/SKILL.md +++ b/.omp/skills/omp-flow-brainstorm/SKILL.md @@ -16,10 +16,11 @@ description: Explore and clarify a consented omp-flow task Bundle when direction For a non-trivial Explore, use repository/Wiki evidence and human calibration to form or revise a provisional first-principles anchor(第一性锚定)before broad Research. Keep it in useful authored -prose, not a required file or fixed checklist. It should be sufficient to expose the observable -problem, current principal contradiction(主要矛盾), irreducible outcome, human boundaries, a -strong counter-hypothesis, and evidence that would revise the framing. Mechanical low-ambiguity -work may proceed directly when this step would not improve a decision. +prose, not a required file or fixed checklist. It should be sufficient to expose the concrete +actors and action, observable intended outcome, current principal contradiction(主要矛盾), +irreducible outcome, human boundaries, a strong counter-hypothesis, and evidence that would +revise the framing. Mechanical low-ambiguity work may proceed directly when this would not improve +a decision. Concentrate interaction on the material decision frontier: @@ -33,11 +34,13 @@ Concentrate interaction on the material decision frontier: ## Interview Contract 1. Read the entry Concept and follow only useful links from the Bundle. -2. Record the initial request and known repository facts in the assigned framing Concept. +2. Record the initial request, concrete actors/action/outcome, current principal contradiction, + and known repository facts in the assigned framing Concept. 3. Inspect code, tests, docs, prior tasks, relevant history, and applicable durable knowledge through the native `omp-flow-wiki` Skill before asking repository-answerable questions. -4. Ask the user one material decision question at a time. Ask only about intent, preference, - scope, risk tolerance, or ambiguity that evidence cannot answer. +4. Ask the user one material decision question at a time. Ask only about purpose, value, risk + tolerance, preference, or use that repository and other relevant practice evidence cannot + establish. 5. Keep confirmed facts, assumptions, disagreements, alternatives, constraints, success criteria, and open questions distinct. 6. Present materially different directions only when a real choice exists. Follow the human-first diff --git a/.omp/skills/omp-flow-check/SKILL.md b/.omp/skills/omp-flow-check/SKILL.md index 8402cbde..8bccef4a 100644 --- a/.omp/skills/omp-flow-check/SKILL.md +++ b/.omp/skills/omp-flow-check/SKILL.md @@ -18,6 +18,15 @@ Fail closed unless all are available: ## Review Order +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Reviewer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Reviewer still owns the complete +bounded independent Review and assigned Review Concept: compare actual code and verification with +the intended work/Design consequence, and report evidence contradicting the Design or its +principal-problem framing through that output rather than let a handoff or superficial green check +substitute for the practice result. + 1. Resolve the completed predecessor operation and use its output path as the required handoff. Read the work Concept and handoff, verify they identify each other, then inspect the real diff and changed files. diff --git a/.omp/skills/omp-flow-decompose/SKILL.md b/.omp/skills/omp-flow-decompose/SKILL.md index d76b5885..6231da9f 100644 --- a/.omp/skills/omp-flow-decompose/SKILL.md +++ b/.omp/skills/omp-flow-decompose/SKILL.md @@ -12,6 +12,14 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Architect: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. After linked human QbD 1 approval, the +Architect still owns the complete bounded Decompose responsibility and assigned work outputs: map +the approved Design into bounded, independently reviewable work Concepts and an authored prose +execution view, without inventing approval or encoding a machine DAG. + 1. Identify the smallest independently implementable and reviewable work items. Fold scaffolding and docs into the deliverable that needs them. 2. Write one descriptive work Concept per item with objective, in/out scope, useful linked inputs, @@ -26,8 +34,10 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Exit Gate -Prepare QbD 2 only when every work item is bounded, testable, understandable from its entry path, -and worth independent review. Load `omp-flow-qbd` next. +In Main/coordinator context only, prepare QbD 2 and load `omp-flow-qbd` when every work item is +bounded, testable, understandable from its entry path, and worth independent review. The +already-dispatched Architect returns the assigned work map and does not choose or perform that +transition. ## Red Flags diff --git a/.omp/skills/omp-flow-design/SKILL.md b/.omp/skills/omp-flow-design/SKILL.md index 1bc729a6..8742fc3f 100644 --- a/.omp/skills/omp-flow-design/SKILL.md +++ b/.omp/skills/omp-flow-design/SKILL.md @@ -13,11 +13,20 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re ## Procedure -1. Dispatch the native Architect with Bundle root, selected synthesis entry, bounded objective, - relevant linked Concepts, explicit output ownership, actor ID, and receipt. Create the - operation first and forward its complete returned assignment unchanged with native item - `id = actor_id = actorId` and matching descriptor role. Preserve the strict v1 - `ompFlowDispatch` descriptor as the first non-blank line. +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Architect: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Architect still owns +the complete bounded Design responsibility and assigned PRD/Design/decision/interface outputs: +explain each proposed component's concrete causal purpose in plain language, without relying on its +own terminology, and solve the evidenced principal contradiction rather than a secondary or +invented mechanism. + +1. In Main/coordinator context only, dispatch the native Architect with Bundle root, selected + synthesis entry, bounded objective, relevant linked Concepts, explicit output ownership, actor + ID, and receipt. Create the operation first and forward its complete returned assignment + unchanged with native item `id = actor_id = actorId` and matching descriptor role. Preserve the + strict v1 `ompFlowDispatch` descriptor as the first non-blank line. 2. Rewrite `prd.md` into observable requirements, non-goals, constraints, acceptance criteria, and unresolved product decisions. Remove temporary brainstorm duplication. 3. Write `design.md` with components, interfaces, data flow, state ownership, error behavior, migration/compatibility, verification strategy, and rejected alternatives. 4. Add linked decision, interface, brief, or finding Concepts only when they improve navigation or @@ -34,8 +43,10 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re - No unresolved question blocks decomposition. - Linked sources and accepted contracts agree with the Design. -Load `omp-flow-qbd` for independent challenge and record the human decision as a linked Concept. -Do not create implementation work before human QbD 1 approval. +In Main/coordinator context only, load `omp-flow-qbd` for independent challenge and obtain and +record the human decision as a linked Concept. The already-dispatched Architect returns its +assigned outputs and does not choose or perform that transition. Do not create implementation work +before human QbD 1 approval. ## Red Flags diff --git a/.omp/skills/omp-flow-finish/SKILL.md b/.omp/skills/omp-flow-finish/SKILL.md index d2f76d56..95cf9c1a 100644 --- a/.omp/skills/omp-flow-finish/SKILL.md +++ b/.omp/skills/omp-flow-finish/SKILL.md @@ -17,14 +17,34 @@ description: Complete integration verification, deliberate knowledge harvest, co 2. Compare the integrated result against PRD acceptance criteria, cross-row interfaces, migrations, docs, and compatibility requirements. 3. Resolve failures through the owning work/design Concept and repeat independent review or the applicable gate. Do not hide failures with warning-only fallbacks. -4. Review accepted decisions, repeated patterns, and confirmed findings for durable value. -5. Use the native `omp-flow-wiki` Skill to promote only evidenced, reusable knowledge. If nothing qualifies, state that no harvest was needed. -6. Inspect final diff and repository status. Commit through the Harness-native Git workflow when requested. -7. Archive the Bundle only after completion is real and no runtime operation is active. +4. Review accepted decisions, repeated patterns, and confirmed findings for immediate durable value. + Use the native `omp-flow-wiki` Skill only when the evidence already supports promotion; do not + invent knowledge to satisfy Finish. +5. Inspect final diff and repository status. Create the requested Git checkpoint before Archive so + the Task Bundle has a reproducible source commit/tree. +6. Archive the Bundle only after completion is real and no runtime operation is active. Inspect the + returned `sleepSource`; never reconstruct one from the archive path. +7. When `sleepSource.ready` is true, run `sleep start --source --actor-id `, + load the native `omp-flow-sleep` Skill, and forward its complete assignment unchanged as the sole + native assignment input. Normal `sleep start` delivery is primary. If that delivery is lost or + visibly truncated while its active receipt is known, recover only by capturing the complete + `sleep show ` subprocess/API stdout through successful process completion, parsing all + captured stdout as JSON into the show run mapping, requiring string `run.assignment`, and + forwarding that decoded string unchanged as the sole native assignment input, including its + trailing LF. Rendered Bash/terminal output is diagnostic only: never copy or parse it, add a + prefix or suffix, reconstruct or reserialize the assignment, fall back to `sleep list`, or issue + a duplicate `sleep start`. A nonzero exit, incomplete capture, invalid JSON, or missing or + non-string `run.assignment` is delivery failure and must stop before native dispatch. Complete + the Sleep run before final handoff; zero Candidates is valid. +8. When the source is not ready, report its exact reason instead of asking the user to operate Sleep + manually or manufacturing a checkpoint. Sleep Candidate review and Wiki promotion remain + separate work after the run. ## Final Handoff -Report behavior delivered, important decisions, verification results, archived task path, commit identity when created, and remaining non-blocking risks. +Report behavior delivered, important decisions, verification results, archived task path, commit +identity when created, Sleep run/Candidate outputs or the exact unavailable reason, and remaining +non-blocking risks. ## Red Flags diff --git a/.omp/skills/omp-flow-implement/SKILL.md b/.omp/skills/omp-flow-implement/SKILL.md index e4bd10ca..46380aca 100644 --- a/.omp/skills/omp-flow-implement/SKILL.md +++ b/.omp/skills/omp-flow-implement/SKILL.md @@ -18,6 +18,14 @@ Fail closed unless all are available: ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Implementer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Implementer still owns the +complete bounded implementation and assigned handoff: return the approved Design to practice +through code, execution, and real verification, and report contradictory evidence as a +Design-return signal rather than special-case reality to preserve Design authority. + 1. Read the work Concept first. Follow only useful links to design, decisions, sources, and relevant existing code/tests. 2. Restate the bounded objective, output boundary, done conditions, and verification before editing. @@ -32,7 +40,8 @@ Fail closed unless all are available: Write or update the promised handoff Concept and link it back to the work it implements. Return `DONE`, `DONE_WITH_CONCERNS`, `NEEDS_CONTEXT`, or `BLOCKED`, plus changed files, commands, test counts, decisions, caveats, output path, actor ID, and receipt. Do not mutate runtime/session -records. Implementation success goes to an independent review operation. +records. The Implementer returns this assigned handoff; only Main/coordinator chooses and +dispatches the independent Review operation. ## Red Flags diff --git a/.omp/skills/omp-flow-learn/SKILL.md b/.omp/skills/omp-flow-learn/SKILL.md new file mode 100644 index 00000000..c986e8ca --- /dev/null +++ b/.omp/skills/omp-flow-learn/SKILL.md @@ -0,0 +1,127 @@ +--- +name: omp-flow-learn +description: Maintain and use repository-root .omp-flow/learn for deliberate, reciprocal, resumable Human–Agent co-learning when a human is present and pursuing understanding rather than production execution. +--- + +# OMP-Flow Learn + +Use repository-root `.omp-flow/learn/` when a human is actively pursuing mutual understanding, +explanation, challenge, reconsideration, or reflection. Learn is a human-present dialogue in which +both participants may correct their models; autonomous harvesting, passive one-way tutoring, or +summary generation is not a substitute. + +Production work normally pauses during a Learn conversation. Source and code inspection, worked +examples, counterexamples, and discussion remain available, but do not execute production work +until the human returns the conversation to production. + +## Consult and bootstrap + +Open a known Learn Concept directly when its path is available. Otherwise start at +`.omp-flow/learn/index.md` and follow only ordinary links useful to the current discussion. Indexes +support navigation; they are not exhaustive manifests. + +When Learn is genuinely needed and the root is absent, bootstrap only the root index and the +`daily/`, `threads/`, and `retrospectives/` indexes described by the canonical minimal structure. +Do not pre-populate speculative encounters, a taxonomy, or companion records. + +## Preserve a resumable checkpoint + +Use judgment to select or create a bundle immediately below the relevant stable directory. Name a +new bundle `YYYY-MM-DD-/` and maintain its authored `index.md` so a later human and Agent can +recover the useful current understanding, disagreement, correction, or open point. Add only +concrete descriptive Markdown Concepts that make the learning easier to resume or challenge. + +A Daily records a useful dated encounter and may stand alone. A Thread is warranted only when a +topic needs continuity across encounters. A Retrospective is warranted only for a substantive +lesson about understanding or collaboration. Do not manufacture a Thread or Retrospective to +complete a set. + +Treat the human's corrections, rejected premises, values, business context, and objections as +learning material. Make corrected Agent assumptions visible when that helps resumption. Accuracy +comes from reciprocal correction and evidence, not from fluent prose or Agent confidence. + +## Authority and continuity boundaries + +Learn is provisional authored context, not proof of understanding or completion. + +- A Learn artifact cannot advance, pause-state, approve, dispatch, or otherwise alter an omp-flow + Task. A Task link is contextual; commitments remain authored in the applicable Task Bundle. +- A Learn artifact is not Wiki authority and is never promoted automatically. Durable knowledge + reaches `.omp-flow/wiki/` only through ordinary evidence-based Wiki maintenance. +- Cross-session continuity is limited to visible authored artifacts. Never claim a hidden user + profile, persistent personal memory, or model-weight change. + +## Select the smallest useful lens + +The lenses below are a selectable conversational repertoire, not stages, a checklist, a catechism, +an assessment, or an Agent-led teaching script. Choose the smallest lens that addresses the live +misunderstanding. Combine lenses only when one supplies a relevant corrective to another. Concrete +project facts, code, sources, worked cases, and the human's correction outrank philosophical labels. +Stop when the participants have a useful explanation, disagreement, or open point; do not march +through the remaining lenses. + +### Feynman-style self-explanation + +Invite a plain account of one concrete causal link. Find the first hidden term, unsupported leap, or +failed application, then repair it from a source or worked case. Fluency is only a possible gap +diagnostic and never proof of mastery. Do not attribute the modern packaged “Feynman Technique” to +Feynman. + +### Cargo Cult Science integrity + +For a consequential explanation, volunteer the material contrary fact, plausible alternative, +uncertainty, and observation that could change the conclusion so the other participant can judge +it. This is judgment about material disclosure, not four mandatory headings, a fixed response form, +or a ritual inventory of every caveat. + +### Grounded first principles + +Distinguish observed fact, definition, hard constraint, value choice, assumption, and convention. +Trace only premises capable of changing the present conclusion, retain the conditions under which +it should be revised, and stop when further reduction would not help. Existing knowledge and +history are evidence to examine, not impurities to discard. + +### Practice-led principal-contradiction analysis + +Offer the principal contradiction, dominant aspect, and material secondary coupling only as a +revisable prioritization hypothesis tied to current effects. Name the changed condition or practical +observation that would reorder it. Returning to practice may mean sources, code inspection, +examples, counterexamples, a diagram, or later observable verification; it does not authorize +production execution while Learn is paused. Do not import a universal single-cause claim or +political doctrine. + +### Material history or genealogy + +Use a concise temporal account only when it clarifies the present. Connect a concrete problem and +conditions to a prior arrangement, emergence or adoption, limitation, and later change; include a +discontinuity where needed and label interpretive causality. Reject inevitable or present-purpose +origin stories, mechanically economic single-causality, and political doctrine; examine interacting +causes and source support. + +### Reciprocal Socratic questioning + +Use a few genuine reasons, counterexamples, and consequence questions to test either participant's +claim. Either participant may reject a premise, ask the Agent to answer directly, or leave an aporia +open. Questions yield to direct explanation or admitted uncertainty when more useful and never +steer assent toward a conclusion the Agent selected in advance. + +### Minimal structural box-drawing + +Draw labeled ASCII, Unicode, or Mermaid boxes and arrows only when a few elements at one useful +abstraction level make a particular structural inference cheaper than prose. Check the picture +against sources, code, examples, or the participants' model; revise or discard it when it does not +help. A diagram is not inherently clarifying. + +These lenses create optional corrective friction rather than a composite routine: explanation +answers to integrity and evidence; alleged hard constraints to history; principal ranking to +secondary couplings and changed conditions; historical narrative to discontinuity and interacting +causes; questions to reciprocal answerability; and diagrams to prose, source, or practice +comparison. They do not adopt a complete philosophical school or establish mastery. + +## Keep Learn conversational + +Do not introduce an entry command, pause or save signal, fixed encounter stages, required +transcript or summary, mandatory headings, score, metric, completion gate, approval ceremony, or +per-edit human approval rule. There is no parsed body schema, lifecycle record, second task system, +or automatic learning judgment. Preserve only what is genuinely useful for reciprocal resumption, +and return to production only when the human changes the conversation back to production work. diff --git a/.omp/skills/omp-flow-qbd/SKILL.md b/.omp/skills/omp-flow-qbd/SKILL.md index 9b092c0e..686d6174 100644 --- a/.omp/skills/omp-flow-qbd/SKILL.md +++ b/.omp/skills/omp-flow-qbd/SKILL.md @@ -19,17 +19,27 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Auditor: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Auditor still owns the +complete bounded independent audit and assigned audit Concept: reconstruct the concrete problem +without solution jargon, challenge whether the selected problem and current principal +contradiction still hold before judging architecture completeness, preserve the mechanical safety +analysis, and report the required verdict, findings, evidence, and contradictions through that +output boundary. + 1. Identify the design or work-map entry Concept and an explicit audit output Concept. Through its useful links, bind the audit to the current decision, unacceptable consequences, current scope/change, and relevant closed findings, residual risks, and human decisions. Do not require a fixed audit-brief file or field shape; no prior findings is normal for a first audit. -2. Start one independent QbD operation with Bundle root, role, bounded objective, entry, output, - actor ID, and optional predecessor receipt. -3. Dispatch one independent native `qbd-auditor`. Pass the paths and opaque receipt returned by - the runtime by forwarding the complete returned assignment unchanged. Keep its strict v1 - `ompFlowDispatch` descriptor as the first non-blank line, set native item - `id = actor_id = actorId`, and use the matching descriptor role. Do not render the Bundle, - reconstruct the descriptor, or prepend audit prose. +2. In Main/coordinator context only, start one independent QbD operation with Bundle root, role, + bounded objective, entry, output, actor ID, and optional predecessor receipt. +3. In Main/coordinator context only, dispatch one independent native `qbd-auditor`. Pass the paths + and opaque receipt returned by the runtime by forwarding the complete returned assignment + unchanged. Keep its strict v1 `ompFlowDispatch` descriptor as the first non-blank line, set + native item `id = actor_id = actorId`, and use the matching descriptor role. Do not render the + Bundle, reconstruct the descriptor, or prepend audit prose. 4. Require an explicit verdict with these semantics: - `FAIL` requires evidence of a critical falsehood, authorization or data violation, irreversible harm, or an unrealizable/unverifiable core path for which safe degradation is @@ -42,15 +52,21 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl decision, give the smallest remedy, and explain why hiding, `unavailable`, disabling, narrowing, refusal to write, or another safe degradation is insufficient. Findings without that chain are advisory. -6. Confirm the promised audit Concept exists, links to what it evaluated, and records material - findings. Finish the runtime operation with the same actor ID. -7. Present material findings and the applicable governance options to the user. Only the user - decides calibration; the verdict itself authorizes no repair, re-audit, or forward transition. -8. Record the human decision in a linked decision Concept. Do not encode approval, materiality, or - risk as runtime phase or parsed state. +6. In Main/coordinator context only, confirm the promised audit Concept exists, links to what it + evaluated, and records material findings, then finish the runtime operation with the same actor + ID. The already-dispatched Auditor returns that assigned audit output; it does not finish or + correlate the coordinator's operation. +7. In Main/coordinator context only, present material findings and applicable governance options + to the user. Only the user decides calibration; the verdict itself authorizes no repair, + re-audit, or forward transition. +8. In Main/coordinator context only, record the human decision in a linked decision Concept. Do + not encode approval, materiality, or risk as runtime phase or parsed state. ## Transitions +These routing choices are Main/coordinator-only and inapplicable to an already-dispatched Auditor, +which returns the assigned audit findings and verdict without choosing or performing a transition. + - Recorded QbD 1 human PASS -> load `omp-flow-decompose`. - Recorded QbD 2 human PASS -> load `omp-flow-execute`. - Advisory risk, `PASS` residual risk, or risk made non-blocking by removal, disabling, narrowing, diff --git a/.omp/skills/omp-flow-research/SKILL.md b/.omp/skills/omp-flow-research/SKILL.md index 0a79cf04..ae06c006 100644 --- a/.omp/skills/omp-flow-research/SKILL.md +++ b/.omp/skills/omp-flow-research/SKILL.md @@ -29,13 +29,22 @@ Choose and persist one of: ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Researcher: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Researcher still owns +the complete bounded Research responsibility and assigned output: test the framing against +practice, distinguish what evidence proves, does not prove, and merely makes possible, and report a +materially changed principal contradiction as a Brainstorm-return signal rather than protect the +earlier framing. + 1. Split uncertainty into independently investigable questions and create descriptive output paths. -2. Dispatch Harness-native researcher agents when questions can be investigated independently. - Pass Bundle root, role, objective, entry Concept, exact output path, actor ID, receipt, and the - no-implementation boundary. - Start one operation per native task item, then forward its complete returned assignment - unchanged with item `id = actor_id = actorId` and matching descriptor role. The strict v1 - `ompFlowDispatch` descriptor remains the first non-blank line; do not decorate or reconstruct it. +2. In Main/coordinator context only, dispatch Harness-native researcher agents when questions can + be investigated independently. Pass Bundle root, role, objective, entry Concept, exact output + path, actor ID, receipt, and the no-implementation boundary. Start one operation per native task + item, then forward its complete returned assignment unchanged with + `id = actor_id = actorId` and matching descriptor role. The strict v1 `ompFlowDispatch` + descriptor remains the first non-blank line; do not decorate or reconstruct it. 3. Separate facts, interpretations, counter-evidence, unknowns, and recommendations. Actively seek the strongest evidence against the current framing, not only confirmation. Internal claims use `file:line`; external claims use stable source URLs and version/date where relevant. @@ -61,7 +70,8 @@ Choose and persist one of: next decision. - The synthesis lets an Architect design without reconstructing research from chat. -Load `omp-flow-design` next. +In Main/coordinator context only, load `omp-flow-design` next. The already-dispatched Researcher +returns the assigned synthesis/output and does not choose or perform that transition. ## Red Flags diff --git a/.omp/skills/omp-flow-sleep/SKILL.md b/.omp/skills/omp-flow-sleep/SKILL.md new file mode 100644 index 00000000..dcf957bd --- /dev/null +++ b/.omp/skills/omp-flow-sleep/SKILL.md @@ -0,0 +1,63 @@ +--- +name: omp-flow-sleep +description: Consolidate one exact archived OKF Task into reviewable cross-task knowledge candidates after Finish, without machine clustering or direct Wiki promotion. +--- + +# OMP-Flow Sleep + +Use this Skill only with a complete assignment whose first non-blank line is an exact +`{"ompFlowSleep":{...}}` descriptor produced by `.omp-flow/scripts/omp_flow.py sleep start`. +Do not reconstruct, summarize, or guess a descriptor from an archived path. + +## Descriptor contract + +Require `version`, `sourceReceipt`, `sourceTask`, `sourceCommit`, `sourceTree`, `entry`, +`sleepIndex`, `runOutput`, `candidateRoot`, `actorId`, `receipt`, and `harvesterRevision`. +Require `version` exactly `1`, the assignment actor to match `actorId`, and every supplied path to +remain within the repository. Treat `sourceReceipt`, `sourceCommit`, `sourceTree`, `receipt`, and +`harvesterRevision` as opaque mechanical identity, not semantic evidence. + +## Method + +1. Read the archived Task `entry` and follow only the Task Concepts needed to understand accepted + outcomes, independent Review, verification, repeated findings, counterexamples, and expensive + reasoning. Do not read raw Harness transcripts. +2. Read `sleepIndex`. Use authored links, ordinary filenames, repository text search, and direct + understanding of the smallest relevant Candidate/Wiki topics. Do not use embedding, vector + retrieval, similarity thresholds, automatic taxonomy, a knowledge graph, or a fixed evidence + schema. +3. Decide whether the Task supports zero, one, or several durable candidates. A Task-local fact, + unverified explanation, generic lesson, or restatement of the Task is a valid zero-candidate + result. +4. For each useful topic, revise an existing Markdown Candidate beneath `candidateRoot` or create a + self-contained one. Preserve ordinary links to the source Task and distinguish supporting + evidence, contrary evidence, applicability boundaries, unresolved questions, and possible Wiki + or Skill consequences. Never average a conflict into false consensus. +5. Write one OKF Run handoff at the exact `runOutput`. State what was read, which Candidates were + created or revised, why other observations were not promoted, and what review or experiment is + still required. This handoff is authored knowledge; runtime state remains under `.runtime`. +6. Finish the mechanical run with: + + ```text + python -X utf8 .omp-flow/scripts/omp_flow.py sleep finish \ + --state completed --actor-id [--candidate ...] + ``` + + Zero `--candidate` arguments is valid. On failure, call `sleep finish` with `--state failed` and + report the exact blocker; do not manufacture a Candidate or completion claim. + +## Promotion boundary + +Sleep ends with reviewable Candidates, not Wiki authority. Do not edit `.omp-flow/wiki/`, Harness +Skills, or workflow policy from this assignment. A different actor should independently challenge +material Candidates. Facts may use proportional Wiki Review; architecture, methodology, or Agent +behavior changes require a new Task framing and the applicable Research, Design, QbD, paired +benchmark, and human decision. An Agent or Reviewer `PASS` is not human approval. + +## Red flags + +- Do not accept an archived path without the runtime-produced source receipt and Git checkpoint. +- Do not force one Candidate per Task or duplicate one Candidate per Run. +- Do not parse authored Markdown into lifecycle state or mandatory fields. +- Do not claim source stability after the runtime reports source drift. +- Do not auto-adopt, auto-merge, auto-promote, or silently overwrite concurrent Candidate work. diff --git a/.omp/skills/omp-flow/SKILL.md b/.omp/skills/omp-flow/SKILL.md index da0af2ce..b1446d25 100644 --- a/.omp/skills/omp-flow/SKILL.md +++ b/.omp/skills/omp-flow/SKILL.md @@ -41,9 +41,12 @@ When there is no active task, classify before creating one: | User explicitly requests omp-flow | Enter the workflow | Do not create a task merely because a task could be useful. Once the user consents, create the -Bundle, open its root index, and load `omp-flow-brainstorm`. For non-trivial Explore, Brainstorm -first forms a provisional first-principles anchor(第一性锚定)around the observable problem and -principal contradiction(主要矛盾); mechanical low-ambiguity work does not need this ceremony. +Bundle, open its root index, and load `omp-flow-brainstorm`. When selecting work or framing a +bounded assignment, preserve the current concrete decision, non-sacrificable human boundary, +revisable principal contradiction(主要矛盾), and evidence that could change it; do not pre-commit +a hypothetical mechanism merely because it is easy to name. For non-trivial Explore, Brainstorm +first forms a provisional first-principles anchor(第一性锚定)around that concrete problem; +mechanical low-ambiguity work does not need this ceremony. ## Operation Routing diff --git a/README.md b/README.md index 6f1cfc16..10fcaefd 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,34 @@ brainstorm ↔ research → design → QbD → work map → QbD → implementati 这是一条推理方向,不是 runtime phase state。证据可以让工作回到 framing 或 design;实现结果也必须经过不同 actor 的独立复核。完整语义见 [workflow.md](templates/.omp-flow/workflow.md)。 +## 项目知识与文档系统 + +omp-flow 把不同生命周期和可信度的知识分开放置,但全部保持为普通 Markdown: + +| 位置 | 用途 | 边界 | +| --- | --- | --- | +| `.omp-flow/tasks//` | 当前任务的问题、来源、需求、设计、决定、交接与复核 | 属于一个具体 Task Bundle;完成后可归档 | +| `.omp-flow/wiki/` | 跨任务复用的架构、约定、经验与项目事实 | 只保存已有证据支持、值得长期维护的知识 | +| `.omp-flow/learn/` | 人与 Agent 共同学习时形成的可恢复理解 | Daily 记录有价值的当次学习;Thread 延续跨次主题;Retrospective 保留重要反思 | +| `.omp-flow/sleep/` | 从已归档 Task 提炼出的跨任务知识候选 | Candidate 必须复核后才能进入 Wiki,不会自动晋升 | + +`omp-flow init` 和 `omp-flow update` 会安装并维护这些目录所需的模板、Skills 与运行时。 +Learn 没有额外的开始/保存命令:当你明确希望一起理解、解释、质疑或复盘时,Agent 会按需维护 +`.omp-flow/learn/`,而不是保存整段聊天、打分或制造第二套任务系统。 + +任务完成并归档后,Sleep 可以读取那个精确的 Git checkpoint,生成零个或多个可审查的 +Candidate。它不会读取原始 Harness transcript,也不会使用向量聚类自动改写 Wiki;最终是否 +沉淀为长期项目知识仍由人和 Agent 根据证据判断。 + +```text +Task Bundle → finish / archive → Sleep Candidate ──人工复核──→ Wiki + 人与 Agent 的共同理解与纠正 ───────────────→ Learn +``` + +`0.3.0` 同时更新了共享 Workflow Skills 与各 Harness 的原生 Agent 指令,使 Brainstorm、 +Research、Design、QbD、Implementation、Review 和 Finish 更强调实践证据、独立复核、 +可恢复 assignment,以及人类决定与模型判断之间的边界。 + ## 致谢 diff --git a/README_EN.md b/README_EN.md index 3e0c246b..50935d28 100644 --- a/README_EN.md +++ b/README_EN.md @@ -75,6 +75,28 @@ brainstorm ↔ research → design → QbD → work map → QbD → implementati This is a reasoning direction, not runtime phase state. Evidence can return work to framing or design, and implementation results still require independent review by a different actor. See [workflow.md](templates/.omp-flow/workflow.md) for the complete semantics. +## Project knowledge and documentation + +omp-flow separates knowledge with different lifetimes and confidence levels while keeping all of it as ordinary Markdown: + +| Location | Purpose | Boundary | +| --- | --- | --- | +| `.omp-flow/tasks//` | The current task's problem, sources, requirements, design, decisions, handoffs, and reviews | Belongs to one Task Bundle and can be archived after completion | +| `.omp-flow/wiki/` | Reusable architecture, conventions, experience, and project facts | Keeps evidenced knowledge worth maintaining across tasks | +| `.omp-flow/learn/` | Resumable understanding formed through Human–Agent co-learning | Daily captures a useful encounter; Threads continue cross-encounter topics; Retrospectives preserve substantive reflection | +| `.omp-flow/sleep/` | Cross-task knowledge candidates distilled from an archived Task | A Candidate requires review before entering the Wiki and is never promoted automatically | + +`omp-flow init` and `omp-flow update` install and maintain the templates, Skills, and runtime needed by these directories. Learn has no extra start or save command: when you explicitly want to understand, explain, challenge, or reflect together, the Agent maintains `.omp-flow/learn/` as needed instead of storing the whole chat, scoring the encounter, or creating a second task system. + +After a completed Task is archived, Sleep can read that exact Git checkpoint and produce zero or more reviewable Candidates. It does not read raw Harness transcripts or use vector clustering to rewrite the Wiki automatically; people and Agents still decide from evidence whether a Candidate deserves durable project authority. + +```text +Task Bundle → finish / archive → Sleep Candidate ──human review──→ Wiki + Human–Agent understanding and correction ────────────→ Learn +``` + +`0.3.0` also updates the shared Workflow Skills and Harness-native Agent instructions so Brainstorm, Research, Design, QbD, Implementation, Review, and Finish more clearly preserve practice evidence, independent review, recoverable assignments, and the boundary between human decisions and model judgment. + ## Credits - [pi-maestro-flow](https://github.com/catlog22/pi-maestro-flow/blob/089f067ca669b90de7b80b38251ae3d9dfddad98/README.md) inspired the public README presentation. diff --git a/package-lock.json b/package-lock.json index ac4b2c25..302e4e22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "omp-flow", - "version": "0.2.7", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omp-flow", - "version": "0.2.7", + "version": "0.3.0", "license": "MIT", "dependencies": { "inquirer": "^9.3.7" diff --git a/package.json b/package.json index 529eac16..08234877 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omp-flow", - "version": "0.2.7", + "version": "0.3.0", "description": "Agent-native OKF task Bundles with a minimal portable runtime kernel.", "type": "module", "main": "dist/index.js", diff --git a/src/cli/init.ts b/src/cli/init.ts index 5af3884b..f78613b1 100644 --- a/src/cli/init.ts +++ b/src/cli/init.ts @@ -92,13 +92,21 @@ const SKILL_NAMES = [ 'omp-flow-execute', 'omp-flow-finish', 'omp-flow-implement', + 'omp-flow-learn', 'omp-flow-qbd', 'omp-flow-research', + 'omp-flow-sleep', 'omp-flow-ui-designer', 'omp-flow-wiki', ] as const; const FLOW_STATUS_SKILL_NAME = 'flow-status' as const; +const LEARN_INDEX_FILES = [ + 'index.md', + 'daily/index.md', + 'threads/index.md', + 'retrospectives/index.md', +] as const; const CODEX_AGENT_FILES = [ 'omp-flow-architect.toml', @@ -117,6 +125,7 @@ const PYTHON_CORE_FILES = [ 'common/active_task.py', 'common/task_store.py', 'common/operation_store.py', + 'common/sleep_store.py', ] as const; const CORE_RESOURCES: readonly ManagedResource[] = [ @@ -130,6 +139,11 @@ const CORE_RESOURCES: readonly ManagedResource[] = [ destinationPath: path.join('.omp-flow', 'workflow.md'), group: 'core', }, + ...LEARN_INDEX_FILES.map(fileName => ({ + sourcePath: path.join('templates', '.omp-flow', 'learn', ...fileName.split('/')), + destinationPath: path.join('.omp-flow', 'learn', ...fileName.split('/')), + group: 'core' as const, + })), ...PYTHON_CORE_FILES.map(fileName => ({ sourcePath: path.join('templates', '.omp-flow', 'scripts', ...fileName.split('/')), destinationPath: path.join('.omp-flow', 'scripts', ...fileName.split('/')), diff --git a/templates/.omp-flow/learn/daily/index.md b/templates/.omp-flow/learn/daily/index.md new file mode 100644 index 00000000..e525fead --- /dev/null +++ b/templates/.omp-flow/learn/daily/index.md @@ -0,0 +1,15 @@ +--- +type: "Learn Daily Index" +title: "Daily learning encounters" +--- + +# Daily learning encounters + +Daily bundles preserve a useful, resumable checkpoint from one real dated Human–Agent co-learning +encounter: its discussion, challenge, examples, corrections, current understanding, or open point. +Create one only when the encounter benefits from preservation. + +Name a bundle `YYYY-MM-DD-/` and give it an authored `index.md` that orients a returning human +and Agent. Add only descriptive Markdown Concepts warranted by the encounter. A Daily may stand +alone; it never requires a Thread or Retrospective companion. This index aids navigation and need +not exhaustively list every bundle. diff --git a/templates/.omp-flow/learn/index.md b/templates/.omp-flow/learn/index.md new file mode 100644 index 00000000..9141413b --- /dev/null +++ b/templates/.omp-flow/learn/index.md @@ -0,0 +1,43 @@ +--- +type: "Learn Index" +title: "Human–Agent Learn" +--- + +# Human–Agent Learn + +Learn is the repository space for deliberate, human-present Human–Agent co-learning: provisional +digestion, explanation, challenge, correction, and reflection that may help both participants revise +their understanding. Production work normally pauses while a Learn conversation is underway and +resumes only when the human returns the conversation to production. + +## Stable affordances + +- [Daily](daily/index.md) preserves a useful checkpoint from one dated co-learning encounter. +- [Threads](threads/index.md) carries a shared model, live disagreement, and useful links across + encounters when continuity is actually needed. +- [Retrospectives](retrospectives/index.md) reflects on a substantive change, problem, or lesson in + technical understanding, human digestion, Agent explanation or assumptions, or collaboration. + +These indexes are navigation aids, not exhaustive manifests. The directories are distinct stable +capabilities, not a required companion set: a Daily may stand alone, and a Thread or Retrospective +is created only when the learning warrants it. + +## Dated bundles + +Place a bundle immediately below the relevant stable directory and name it +`YYYY-MM-DD-/`, using its establishment date and a readable topic. Every bundle has an +authored `index.md` that gives a returning human and Agent the useful current understanding or open +question and links to related Concepts only when those links aid resumption. + +A bundle may also contain concrete, descriptive Markdown Concepts warranted by the discussion, +such as a worked example, counterargument, shared model, explanation to revisit, open question, or +reflection. There is no required companion bundle, transcript, fixed body schema, lifecycle, +machine-validated identifier, or exhaustive bundle index. + +## Authority boundary + +Learn is provisional authored context. It does not advance, pause-state, approve, or otherwise +alter an omp-flow Task; Task commitments remain in the applicable Task Bundle. It is not Wiki +authority and is never promoted automatically; established knowledge reaches the Wiki only through +ordinary evidence-based Wiki maintenance. Ordinary links to Task or Wiki Concepts provide context, +not authority transfer. diff --git a/templates/.omp-flow/learn/retrospectives/index.md b/templates/.omp-flow/learn/retrospectives/index.md new file mode 100644 index 00000000..0b681a59 --- /dev/null +++ b/templates/.omp-flow/learn/retrospectives/index.md @@ -0,0 +1,16 @@ +--- +type: "Learn Retrospective Index" +title: "Learning retrospectives" +--- + +# Learning retrospectives + +Retrospective bundles reflect on a substantive change, problem, or lesson in technical +understanding, human digestion, Agent explanations or assumptions, or the way the participants +collaborate. Create one only when reflection itself will help a later encounter; do not create one +to complete a companion set. + +Name a warranted bundle `YYYY-MM-DD-/` and give it an authored `index.md` for resumption, +with optional descriptive Markdown Concepts when useful. A Daily may stand alone without a +Retrospective. This index supports discovery rather than an exhaustive inventory or completion +record. diff --git a/templates/.omp-flow/learn/threads/index.md b/templates/.omp-flow/learn/threads/index.md new file mode 100644 index 00000000..6fcf386e --- /dev/null +++ b/templates/.omp-flow/learn/threads/index.md @@ -0,0 +1,15 @@ +--- +type: "Learn Thread Index" +title: "Cross-encounter learning threads" +--- + +# Cross-encounter learning threads + +Thread bundles preserve continuity only when a topic genuinely spans encounters. They can maintain +the current shared model, a live disagreement or unresolved question, and useful ordinary links to +the Daily encounters that changed the topic. + +Name a warranted bundle `YYYY-MM-DD-/` and maintain an authored `index.md` for resumption, +with optional descriptive Markdown Concepts only when useful. A Daily does not require a Thread, +and a Thread is not a task, dependency graph, or learning lifecycle. This index aids navigation and +is not an exhaustive manifest. diff --git a/templates/.omp-flow/scripts/common/sleep_store.py b/templates/.omp-flow/scripts/common/sleep_store.py new file mode 100644 index 00000000..ea1b1566 --- /dev/null +++ b/templates/.omp-flow/scripts/common/sleep_store.py @@ -0,0 +1,408 @@ +from __future__ import annotations + +import hashlib +import json +import os +import subprocess +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + +from .io import WorkflowError, atomic_write_json, atomic_write_text, confined_path, read_json +from .paths import flow_dir + + +SLEEP_DESCRIPTOR_VERSION = 1 +TERMINAL_STATES = {"completed", "failed"} + + +def _runtime_root(repo: Path) -> Path: + return flow_dir(repo) / ".runtime" / "sleep" + + +def _source_path(repo: Path, receipt: str) -> Path: + _validate_receipt(receipt) + return _runtime_root(repo) / "sources" / f"{receipt}.json" + + +def _run_path(repo: Path, receipt: str) -> Path: + _validate_receipt(receipt) + return _runtime_root(repo) / "runs" / f"{receipt}.json" + + +def _run_lock(repo: Path, receipt: str) -> Path: + return flow_dir(repo) / ".runtime" / "locks" / f"sleep-{receipt}.lock" + + +def _validate_receipt(receipt: str) -> None: + if len(receipt) != 64 or any(character not in "0123456789abcdef" for character in receipt): + raise WorkflowError(f"Invalid Sleep receipt: {receipt}") + + +def _git(repo: Path, *arguments: str) -> str: + result = subprocess.run( + ["git", *arguments], + cwd=repo, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="utf-8", + errors="replace", + check=False, + ) + if result.returncode != 0: + detail = result.stderr.strip() or result.stdout.strip() or "Git command failed" + raise WorkflowError(detail) + return result.stdout.strip() + + +def _directory_digest(root: Path) -> str: + if not root.is_dir(): + raise WorkflowError(f"Sleep source directory not found: {root}") + digest = hashlib.sha256() + entries = sorted(root.rglob("*"), key=lambda path: path.relative_to(root).as_posix()) + for path in entries: + relative = path.relative_to(root).as_posix() + if path.is_symlink(): + raise WorkflowError(f"Sleep source contains unsupported symlink: {relative}") + if not path.is_file(): + continue + digest.update(relative.encode("utf-8")) + digest.update(b"\0") + with path.open("rb") as stream: + while True: + chunk = stream.read(1024 * 1024) + if not chunk: + break + digest.update(chunk) + digest.update(b"\0") + return digest.hexdigest() + + +def _skill_path(repo: Path) -> Path: + candidates = ( + repo / ".agents" / "skills" / "omp-flow-sleep" / "SKILL.md", + repo / ".omp" / "skills" / "omp-flow-sleep" / "SKILL.md", + repo / ".claude" / "skills" / "omp-flow-sleep" / "SKILL.md", + ) + for path in candidates: + if path.is_file(): + return path + raise WorkflowError("omp-flow-sleep Skill is not installed") + + +def _skill_revision(repo: Path) -> str: + return hashlib.sha256(_skill_path(repo).read_bytes()).hexdigest() + + +def _git_task_snapshot(repo: Path, source: Path) -> tuple[str, str]: + source_relative = source.resolve().relative_to(repo.resolve()).as_posix() + commit = _git(repo, "rev-parse", "--verify", "HEAD") + dirty = subprocess.run( + ["git", "diff", "--quiet", commit, "--", source_relative], + cwd=repo, + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE, + check=False, + ) + if dirty.returncode == 1: + raise WorkflowError("Task Bundle differs from its Git checkpoint") + if dirty.returncode != 0: + raise WorkflowError(dirty.stderr.decode("utf-8", errors="replace").strip() or "Cannot inspect Task checkpoint") + untracked = _git(repo, "ls-files", "--others", "--exclude-standard", "--", source_relative) + if untracked: + raise WorkflowError("Task Bundle contains untracked files") + tree = _git(repo, "rev-parse", f"{commit}:{source_relative}") + if _git(repo, "cat-file", "-t", tree) != "tree": + raise WorkflowError("Task checkpoint is not a Git tree") + return commit, tree + + +def prepare_sleep_source( + repo: Path, + task_id: str, + source: Path, + destination: Path, +) -> dict[str, Any]: + archived_relative = destination.resolve().relative_to(repo.resolve()).as_posix() + try: + commit, tree = _git_task_snapshot(repo, source) + archive_digest = _directory_digest(source) + receipt = hashlib.sha256( + f"{task_id}\0{commit}\0{tree}\0{archive_digest}".encode("utf-8") + ).hexdigest() + return { + "ready": True, + "receipt": receipt, + "taskId": task_id, + "sourcePath": source.resolve().relative_to(repo.resolve()).as_posix(), + "archivedPath": archived_relative, + "sourceCommit": commit, + "sourceTree": tree, + "archiveDigest": archive_digest, + } + except (OSError, ValueError, WorkflowError) as exc: + return { + "ready": False, + "taskId": task_id, + "archivedPath": archived_relative, + "reason": str(exc), + } + + +def finalize_sleep_source(repo: Path, prepared: dict[str, Any], destination: Path) -> dict[str, Any]: + if not prepared.get("ready"): + return prepared + try: + if _directory_digest(destination) != prepared.get("archiveDigest"): + raise WorkflowError("Archived Task content changed during relocation") + receipt = str(prepared["receipt"]) + record = { + **prepared, + "state": "ready", + "createdAt": datetime.now(timezone.utc).isoformat(), + } + path = _source_path(repo, receipt) + if path.exists(): + existing = read_json(path) + stable_fields = ("taskId", "sourceCommit", "sourceTree", "archiveDigest", "archivedPath") + if any(existing.get(field) != record.get(field) for field in stable_fields): + raise WorkflowError(f"Sleep source receipt collision: {receipt}") + return existing + atomic_write_json(path, record) + return record + except (OSError, ValueError, WorkflowError) as exc: + return { + "ready": False, + "taskId": prepared.get("taskId"), + "archivedPath": prepared.get("archivedPath"), + "reason": str(exc), + } + + +def read_sleep_source(repo: Path, receipt: str) -> dict[str, Any]: + value = read_json(_source_path(repo, receipt)) + if value.get("receipt") != receipt or value.get("state") != "ready": + raise WorkflowError(f"Sleep source identity mismatch: {receipt}") + return value + + +def _ensure_sleep_root(repo: Path) -> None: + root = flow_dir(repo) / "sleep" + index = root / "index.md" + if not index.exists(): + atomic_write_text( + index, + "---\nokf_version: \"0.2\"\n---\n\n# Wiki Sleep\n\n" + "Candidate knowledge awaiting review and possible Wiki promotion belongs here.\n", + ) + (root / "candidates").mkdir(parents=True, exist_ok=True) + (root / "runs").mkdir(parents=True, exist_ok=True) + + +def _archived_root(repo: Path, source: dict[str, Any]) -> Path: + archived = confined_path(repo, str(source["archivedPath"])) + archive_root = (flow_dir(repo) / "tasks" / "archive").resolve() + try: + archived.relative_to(archive_root) + except ValueError as exc: + raise WorkflowError("Sleep source escapes the Task archive") from exc + if not archived.is_dir() or not (archived / "index.md").is_file(): + raise WorkflowError("Archived Sleep source or Bundle index is missing") + return archived + + +def _verify_source_content(repo: Path, source: dict[str, Any]) -> Path: + archived = _archived_root(repo, source) + if _directory_digest(archived) != source.get("archiveDigest"): + raise WorkflowError("Archived Sleep source has drifted from its receipt") + return archived + + +def _sleep_assignment(run: dict[str, Any]) -> str: + descriptor = { + "ompFlowSleep": { + "version": SLEEP_DESCRIPTOR_VERSION, + "sourceReceipt": run["sourceReceipt"], + "sourceTask": run["sourceTask"], + "sourceCommit": run["sourceCommit"], + "sourceTree": run["sourceTree"], + "entry": run["entry"], + "sleepIndex": run["sleepIndex"], + "runOutput": run["runOutput"], + "candidateRoot": run["candidateRoot"], + "actorId": run["actorId"], + "receipt": run["receipt"], + "harvesterRevision": run["harvesterRevision"], + } + } + first_line = json.dumps(descriptor, ensure_ascii=False, separators=(",", ":")) + return ( + f"{first_line}\n\n" + f"Archived Task: {run['sourceTask']}\n" + f"Entry Concept: {run['entry']}\n" + f"Sleep index: {run['sleepIndex']}\n" + f"Run output: {run['runOutput']}\n" + f"Candidate root: {run['candidateRoot']}\n" + f"Actor ID: {run['actorId']}\n" + f"Sleep receipt: {run['receipt']}\n" + ) + + +def start_sleep_run(repo: Path, source_receipt: str, actor_id: str) -> dict[str, Any]: + cleaned_actor = actor_id.strip() + if not cleaned_actor: + raise WorkflowError("Sleep actor identity is required") + source = read_sleep_source(repo, source_receipt) + archived = _verify_source_content(repo, source) + harvester_revision = _skill_revision(repo) + receipt = hashlib.sha256( + f"{source_receipt}\0{harvester_revision}".encode("utf-8") + ).hexdigest() + lock = _acquire_run_lock(repo, receipt) + try: + month = Path(str(source["archivedPath"])).parent.name + run_directory = ( + flow_dir(repo) + / "sleep" + / "runs" + / month + / f"{source['taskId']}--{str(source['sourceTree'])[:12]}--{harvester_revision[:12]}" + ) + run_output = run_directory / "receipt.md" + if _run_path(repo, receipt).exists() or run_output.exists(): + raise WorkflowError(f"Sleep run already exists: {receipt}") + _ensure_sleep_root(repo) + now = datetime.now(timezone.utc).isoformat() + run = { + "receipt": receipt, + "sourceReceipt": source_receipt, + "sourceTask": archived.relative_to(repo.resolve()).as_posix(), + "sourceCommit": source["sourceCommit"], + "sourceTree": source["sourceTree"], + "archiveDigest": source["archiveDigest"], + "entry": (archived / "index.md").relative_to(repo.resolve()).as_posix(), + "sleepIndex": ".omp-flow/sleep/index.md", + "runOutput": run_output.relative_to(repo.resolve()).as_posix(), + "candidateRoot": ".omp-flow/sleep/candidates", + "actorId": cleaned_actor, + "harvesterRevision": harvester_revision, + "state": "active", + "candidates": [], + "createdAt": now, + "updatedAt": now, + } + run["assignment"] = _sleep_assignment(run) + atomic_write_json(_run_path(repo, receipt), run) + return {"run": run, "assignment": run["assignment"]} + finally: + _release_run_lock(lock) + + +def read_sleep_run(repo: Path, receipt: str) -> dict[str, Any]: + value = read_json(_run_path(repo, receipt)) + if value.get("receipt") != receipt: + raise WorkflowError(f"Sleep run identity mismatch: {receipt}") + return value + + +def list_sleep_runs(repo: Path) -> list[dict[str, Any]]: + root = _runtime_root(repo) / "runs" + if not root.is_dir(): + return [] + return [read_sleep_run(repo, path.stem) for path in sorted(root.glob("*.json"))] + + +def _lock_descriptor(descriptor: int) -> bool: + if os.name == "nt": + import msvcrt + + # Locking beyond EOF is explicitly allowed; touching the byte before + # locking could hit a live holder's lock and raise PermissionError. + os.lseek(descriptor, 0, os.SEEK_SET) + try: + msvcrt.locking(descriptor, msvcrt.LK_NBLCK, 1) + except OSError: + return False + return True + import fcntl + + try: + fcntl.flock(descriptor, fcntl.LOCK_EX | fcntl.LOCK_NB) + except OSError: + return False + return True + + +def _acquire_run_lock(repo: Path, receipt: str) -> int: + """Hold an OS-level exclusive lock for the receipt's critical section. + + The descriptor stays open until _release_run_lock. The OS releases the + lock on close, process exit, or kill, so a crashed or stopped holder can + never strand a receipt and no stale-lock reclaimer is needed. Lock files + are permanent rendezvous points and are never deleted. + """ + _validate_receipt(receipt) + path = _run_lock(repo, receipt) + path.parent.mkdir(parents=True, exist_ok=True) + descriptor = os.open(path, os.O_CREAT | os.O_RDWR, 0o600) + if not _lock_descriptor(descriptor): + os.close(descriptor) + raise WorkflowError(f"Sleep run is busy: {receipt}") + return descriptor + + +def _release_run_lock(descriptor: int) -> None: + os.close(descriptor) + + +def finish_sleep_run( + repo: Path, + receipt: str, + *, + state: str, + actor_id: str, + candidates: list[str], +) -> dict[str, Any]: + if state not in TERMINAL_STATES: + raise WorkflowError(f"Invalid terminal Sleep state: {state}") + cleaned_actor = actor_id.strip() + if not cleaned_actor: + raise WorkflowError("Sleep actor identity is required") + lock = _acquire_run_lock(repo, receipt) + try: + run = read_sleep_run(repo, receipt) + if run.get("state") != "active": + raise WorkflowError(f"Sleep run is already terminal: {receipt}") + if run.get("actorId") != cleaned_actor: + raise WorkflowError("Sleep actor identity mismatch") + output_paths: list[str] = [] + if state == "completed": + source = read_sleep_source(repo, str(run["sourceReceipt"])) + _verify_source_content(repo, source) + run_output = confined_path(repo, str(run["runOutput"])) + if not run_output.is_file(): + raise WorkflowError("Sleep run receipt output is missing") + candidate_root = confined_path(repo, str(run["candidateRoot"])) + seen: set[str] = set() + for value in candidates: + candidate = confined_path(candidate_root, value) + try: + relative = candidate.relative_to(candidate_root.resolve()).as_posix() + except ValueError as exc: + raise WorkflowError(f"Sleep candidate escapes candidate root: {value}") from exc + if candidate.suffix.lower() != ".md" or not candidate.is_file(): + raise WorkflowError(f"Sleep candidate Markdown not found: {value}") + if relative in seen: + raise WorkflowError(f"Duplicate Sleep candidate output: {value}") + seen.add(relative) + output_paths.append(candidate.relative_to(repo.resolve()).as_posix()) + elif candidates: + raise WorkflowError("Failed Sleep run cannot claim candidate outputs") + run.pop("assignment", None) + run["state"] = state + run["candidates"] = output_paths + run["updatedAt"] = datetime.now(timezone.utc).isoformat() + atomic_write_json(_run_path(repo, receipt), run) + return run + finally: + _release_run_lock(lock) diff --git a/templates/.omp-flow/scripts/common/task_store.py b/templates/.omp-flow/scripts/common/task_store.py index 09372964..ad33a4a6 100644 --- a/templates/.omp-flow/scripts/common/task_store.py +++ b/templates/.omp-flow/scripts/common/task_store.py @@ -125,9 +125,10 @@ def list_tasks(repo: Path) -> list[dict[str, Any]]: return result -def archive_task(repo: Path, task_id: str) -> Path: +def archive_task(repo: Path, task_id: str) -> tuple[Path, dict[str, Any]]: source = task_dir(repo, task_id) from .operation_store import has_active_operations + from .sleep_store import finalize_sleep_source, prepare_sleep_source if has_active_operations(repo, task_id): raise WorkflowError("Task has active runtime operations") @@ -135,7 +136,8 @@ def archive_task(repo: Path, task_id: str) -> Path: destination = tasks_dir(repo) / "archive" / month / task_id if destination.exists(): raise WorkflowError(f"Archive destination exists: {destination}") + sleep_source = prepare_sleep_source(repo, task_id, source, destination) destination.parent.mkdir(parents=True, exist_ok=True) source.replace(destination) clear_task_sessions(repo, task_id) - return destination + return destination, finalize_sleep_source(repo, sleep_source, destination) diff --git a/templates/.omp-flow/scripts/omp_flow.py b/templates/.omp-flow/scripts/omp_flow.py index c6844ca2..8a0733d8 100644 --- a/templates/.omp-flow/scripts/omp_flow.py +++ b/templates/.omp-flow/scripts/omp_flow.py @@ -33,6 +33,12 @@ list_operations, read_operation, ) +from common.sleep_store import ( + finish_sleep_run, + list_sleep_runs, + read_sleep_run, + start_sleep_run, +) from common.paths import find_repo_root, task_dir from common.task_store import archive_task, create_task, list_tasks @@ -146,11 +152,12 @@ def _task_command(args: argparse.Namespace) -> Any: task_id = args.task or _selected_task(repo) return _task_locator(repo, task_id) if args.task_action == "archive": - task_id = _selected_task(repo, args.task) - destination = archive_task(repo, task_id) + task_id = args.task or _selected_task(repo) + destination, sleep_source = archive_task(repo, task_id) return { "taskId": task_id, "archivedTo": destination.relative_to(repo).as_posix(), + "sleepSource": sleep_source, } raise WorkflowError(f"Unknown task action: {args.task_action}") @@ -241,6 +248,25 @@ def _operation_command(args: argparse.Namespace) -> Any: raise WorkflowError(f"Unknown operation action: {args.operation_action}") +def _sleep_command(args: argparse.Namespace) -> Any: + repo = _repo(args) + if args.sleep_action == "start": + return start_sleep_run(repo, args.source, args.actor_id) + if args.sleep_action == "show": + return read_sleep_run(repo, args.run) + if args.sleep_action == "list": + return list_sleep_runs(repo) + if args.sleep_action == "finish": + return finish_sleep_run( + repo, + args.run, + state=args.state, + actor_id=args.actor_id, + candidates=args.candidate, + ) + raise WorkflowError(f"Unknown Sleep action: {args.sleep_action}") + + EPILOG = ( "Examples:\n" " omp_flow.py status\n" @@ -252,6 +278,8 @@ def _operation_command(args: argparse.Namespace) -> Any: "--role executor --actor-id --objective \"Implement the linked work\"\n" " omp_flow.py operation finish --state completed " "--actor-id --external-receipt \n" + " omp_flow.py sleep start --source --actor-id \n" + " omp_flow.py sleep finish --state completed --actor-id \n" ) @@ -318,6 +346,29 @@ def leaf( finish.add_argument("--actor-id", required=True) finish.add_argument("--external-receipt") + sleep = leaf(sub, "sleep", "Run post-archive OKF knowledge consolidation") + sleep_sub = sleep.add_subparsers(dest="sleep_action", required=True) + sleep_start = leaf(sleep_sub, "start", "Create an archived-source Sleep assignment") + sleep_start.add_argument("--source", required=True, help="Archive-produced Sleep source receipt") + sleep_start.add_argument("--actor-id", required=True) + sleep_show = leaf( + sleep_sub, + "show", + "Read one mechanical Sleep run; an active revised run contains its recoverable assignment", + ) + sleep_show.add_argument("run") + leaf(sleep_sub, "list", "List mechanical Sleep runs") + sleep_finish = leaf(sleep_sub, "finish", "Finish or fail a Sleep run as its bound actor") + sleep_finish.add_argument("run") + sleep_finish.add_argument("--state", required=True, choices=("completed", "failed")) + sleep_finish.add_argument("--actor-id", required=True) + sleep_finish.add_argument( + "--candidate", + action="append", + default=[], + help="Candidate Markdown path relative to .omp-flow/sleep/candidates", + ) + status = leaf(sub, "status", "Show mechanical session or inspect read-only Flow Status") status_sub = status.add_subparsers(dest="status_action") inspect = leaf(status_sub, "inspect", "Inspect the latest validated Flow Status snapshot") @@ -371,6 +422,8 @@ def main() -> int: result = _task_command(args) elif args.command == "operation": result = _operation_command(args) + elif args.command == "sleep": + result = _sleep_command(args) elif args.command == "status" and args.status_action == "observe": result = observe_and_cache( _repo(args), diff --git a/templates/.omp-flow/workflow.md b/templates/.omp-flow/workflow.md index 52abb922..5b7456c1 100644 --- a/templates/.omp-flow/workflow.md +++ b/templates/.omp-flow/workflow.md @@ -4,22 +4,40 @@ 1. Each task directory is one portable OKF v0.2 Bundle. Markdown Concepts, authored indexes, prose, placement, and ordinary relative links carry task meaning. -2. A non-trivial Explore starts with a provisional first-principles anchor(第一性锚定): the - observable problem, principal contradiction(主要矛盾), irreducible outcome, human boundaries, - counter-hypothesis, and evidence that would revise it. This is authored direction, not a fixed - file, checklist, or lifecycle phase; mechanical low-ambiguity work may proceed directly. -3. Brainstorm and research are distinct operations in one Explore spiral. Questions drive - investigation; practice tests(实践检验)confirm, revise, or falsify the anchor and may reframe - the question. -4. Investigation precedes accepted design; design precedes implementation. -5. Agents receive paths and read normal Markdown. OmpFlow does not parse Concept bodies, fixed - headings, lists, filenames, or arbitrary frontmatter into workflow state. -6. Code owns only irreducible mechanics: session and actor identity, safe paths, locks, atomic - external side effects, opaque dispatch receipts, and requested directory operations. -7. Harness-native agents, models, dispatch, concurrency, progress, cancellation, and result - delivery remain native. -8. Missing required entry content or mechanical identity fails visibly. Optional links remain - best-effort and there is no legacy fallback. +2. Reality and practice outrank authored theory. Preserve the authority relationship + `stable dialectical core -> necessary procedural safeguards -> replaceable Skills, cards, + tests, and Harness surfaces`; delivery may change, but it must not reverse the core or weaken + the safeguards. +3. A non-trivial Explore starts with a provisional first-principles anchor(第一性锚定): the + concrete problem, irreducible outcome, non-sacrificable human boundaries, counter-hypothesis, + and evidence that would revise it. This is authored direction, not a fixed file, checklist, or + lifecycle phase; mechanical low-ambiguity work may proceed directly. +4. Contradiction analysis(矛盾分析)identifies the changing conflict that currently governs the + decision: the principal contradiction(主要矛盾). Track how practice transforms it; do not let + a secondary or invented problem displace it merely because that problem has fluent terminology. +5. Brainstorm and research are distinct operations in one Explore spiral. Questions drive + investigation; practice-led reasoning and practice tests(实践论、实践检验)use repository, + runtime, user, and other relevant reality to confirm, revise, or falsify provisional knowledge + before that knowledge returns to implementation, verification, and feedback. +6. Apply concrete-problem analysis(具体问题具体分析)and anti-formalism(反形式主义): + choose rigor in proportion to actual consequences and remove ceremony that does not improve a + real decision, without weakening necessary safeguards. +7. Use the Feynman Technique(费曼技巧)and “do not fool yourself” for important causal claims: + explain cause and effect in plain language, expose gaps hidden by workflow or solution jargon, + distinguish evidence from inference and unknowns, and return unsupported claims to evidence or + human calibration. +8. These anchors are flexible aids with observable work consequences, not required headings, + teach-back artifacts, question counts, checklists, parser inputs, runtime fields, phases, gates, + or model-thought scripts. Their wording and delivery remain replaceable as practice changes. +9. Investigation precedes accepted design; design precedes implementation. +10. Agents receive paths and read normal Markdown. OmpFlow does not parse Concept bodies, fixed + headings, lists, filenames, or arbitrary frontmatter into workflow state. +11. Code owns only irreducible mechanics: session and actor identity, safe paths, locks, atomic + external side effects, opaque dispatch receipts, and requested directory operations. +12. Harness-native agents, models, dispatch, concurrency, progress, cancellation, and result + delivery remain native. +13. Missing required entry content or mechanical identity fails visibly. Optional links remain + best-effort and there is no legacy fallback. ## Knowledge Map @@ -64,7 +82,9 @@ native implementation → linked handoff ↓ independent review → linked Review Concept ↓ -integration → Wiki harvest when useful → commit → archive +integration → immediate Wiki harvest when already evidenced → commit checkpoint → archive + ↓ +archived-source handoff → `omp-flow-sleep` → zero or more reviewable Candidates ``` This is a normal reasoning direction, not a Python lifecycle. Values, risk tolerance, and @@ -204,12 +224,15 @@ pointer, digest, parsed frontmatter, or Hook inference. ## Completion and Archive Finish only after accepted work has current linked independent reviews and integration checks -satisfy the PRD. Use the native `omp-flow-wiki` Skill to promote evidenced reusable knowledge; -temporary task reasoning remains in the task Bundle. +satisfy the PRD. Use the native `omp-flow-wiki` Skill when evidence already supports immediate +promotion; temporary task reasoning remains in the Task Bundle. Archive is an explicit directory operation. It is blocked while runtime operations are active and -preserves relative navigation. Git is the Bundle's history; runtime/session data and acquisition -caches remain ignored. +preserves relative navigation. A committed Task checkpoint lets Archive issue a source commit/tree +and opaque archived-source receipt. Finish forwards that receipt to the native `omp-flow-sleep` +Skill; it never reconstructs an assignment from the moved path. Sleep creates reviewable Candidate +Concepts but cannot grant Wiki authority. Git is the authored history; runtime/session data and +acquisition caches remain ignored. ## Guardrails diff --git a/templates/claude/agents/omp-flow-architect.md b/templates/claude/agents/omp-flow-architect.md index 7c3df60f..1213e049 100644 --- a/templates/claude/agents/omp-flow-architect.md +++ b/templates/claude/agents/omp-flow-architect.md @@ -32,16 +32,20 @@ Require the task Bundle root, architect role, bounded objective, selected synthe design entry Concept, explicit output paths/scope, actorId, and receipt. Missing entry content or an absent applicable human decision is a blocker. Read normal Markdown and follow useful links. -## Design and Work Mapping +## Shared Skill Delegation -Write observable requirements to `prd.md`, architecture and verification to `design.md`, and only -linked decision/interface/finding Concepts that improve discovery. Retain provenance with normal -links; do not update a generated context index. +Select exactly one Skill from the bounded assignment before role work: -After a linked human QbD 1 approval, write descriptive work Concepts with objective, in/out scope, -useful inputs, allowed code/output boundary, done conditions, verification, and expected handoff. -Author `work/index.md` when prose grouping helps communicate order or parallel work. Do not encode -dependencies or receipts in filenames and do not create a machine DAG. +- For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it. +- For approved work mapping only after linked human QbD 1 approval, read + `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it. + +Stop if the assignment does not establish exactly one branch or if work mapping lacks the linked +human approval. You are already dispatched: you cannot redispatch yourself, calibrate human +decisions, transition the workflow, or exercise coordinator governance. The selected Skill +supplies the positive bounded Design or Decompose duty and assigned output; this card's native +identity, startup and binding gates, assignment, tools, write and progress boundaries, and +fail-closed requirements remain authoritative. ## Boundary and Handoff diff --git a/templates/claude/agents/omp-flow-check.md b/templates/claude/agents/omp-flow-check.md index 156a9942..496ba9fc 100644 --- a/templates/claude/agents/omp-flow-check.md +++ b/templates/claude/agents/omp-flow-check.md @@ -34,17 +34,14 @@ implementation, Review Concept output, reviewer actorId, opaque receipt, and the implementation receipt as predecessor. The reviewer actor must differ from the implementation actor. Missing input is a blocker. -## Workflow - -1. Resolve the completed predecessor operation and read its output path as the required handoff. - Confirm the handoff links back to the assigned work, then inspect the actual diff and changed - files. -2. Follow useful links to PRD, Design, decisions, interfaces, and source constraints. -3. Check scope, done conditions, correctness, error behavior, security, maintainability, and tests - proportional to risk. -4. Run independent focused verification. -5. Write the supplied Review Concept, link it to work and handoff, and lead with severity-ordered - findings. Record verdict and exact commands/results in readable language. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-check/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded independent +review duty and assigned Review Concept; this card's native identity, startup and binding gates, +assignment, tools, write and progress boundaries, different-actor requirement, and fail-closed +requirements remain authoritative. ## Boundary and Handoff diff --git a/templates/claude/agents/omp-flow-implement.md b/templates/claude/agents/omp-flow-implement.md index 395fedf0..9c0a96ae 100644 --- a/templates/claude/agents/omp-flow-implement.md +++ b/templates/claude/agents/omp-flow-implement.md @@ -33,15 +33,14 @@ Require the task Bundle root, implementer role, bounded objective, descriptive w allowed code scope and handoff output Concept, actorId, opaque receipt, and predecessor when supplied. Missing input is a blocker. Do not pull a generated context or guess scope. -## Workflow - -1. Read the work Concept and follow only useful links to design, decisions, sources, adjacent code, - and tests. -2. Implement the smallest coherent change inside the stated boundary. -3. Preserve unrelated user/concurrent changes and existing project patterns. -4. Run every verification required by the work plus focused diagnostics. -5. Inspect the diff against every done condition. -6. Write or update the promised handoff Concept and link it to the work. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-implement/SKILL.md` completely and follow it. You +are already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded +implementation duty and assigned handoff; this card's native identity, startup and binding gates, +assignment, tools, write and progress boundaries, and fail-closed requirements remain +authoritative. ## Boundary and Handoff diff --git a/templates/claude/agents/omp-flow-qbd.md b/templates/claude/agents/omp-flow-qbd.md index 3965f59f..cafda61e 100644 --- a/templates/claude/agents/omp-flow-qbd.md +++ b/templates/claude/agents/omp-flow-qbd.md @@ -34,25 +34,16 @@ assignment or mechanical authorization is a hard blocker. Use `NEEDS_EVIDENCE` o or contradictory evidence prevents judging a decision-critical consequence. The output is the only path you may write. -## Workflow - -1. Read the entry and useful links for the current decision, unacceptable consequences, audit - scope/change, prior closed findings, and accepted risks; do not require fixed fields or headings. -2. Separate confirmed evidence, assumptions, strongest counter-evidence, and accepted risk. -3. QbD 1 challenges the problem, synthesis, requirements, architecture, boundaries, alternatives, - sources, and interfaces. -4. QbD 2 challenges the authored work map, relevant work Concepts, ordering, boundaries, done - conditions, and verification. -5. Separate decision-critical findings from advisory observations. For each blocker, state - cause → consequence → decision, the minimum repair, and why removal or safe degradation is - insufficient. `PASS` may include advisory observations or residual risk. -6. Write exactly the assigned audit Concept with verdict `PASS`, `FAIL`, or `NEEDS_EVIDENCE`, risk, - findings, exact next decision/options, and evidence anchors. Do not command a fresh audit. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-qbd/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded QbD duty +and assigned audit output; this card's native identity, startup and binding gates, assignment, +tools, write and progress boundaries, and fail-closed requirements remain authoritative. ## Boundary and Handoff Do not modify PRD, Design, work, sources, code, human decisions, or runtime records. Return output, verdict, risk, blocking count, actorId, receipt, and exact next decision/options for human -calibration. Do not describe an unresolved `FAIL` or decision-critical `NEEDS_EVIDENCE` as ordinary -accepted risk that lets the original scope continue; the available directions are repair/evidence, -removal or safe degradation, deferral, or stop. Model PASS still requires a linked human decision. +calibration. diff --git a/templates/claude/agents/omp-flow-research.md b/templates/claude/agents/omp-flow-research.md index 57663a3e..2e3f28d6 100644 --- a/templates/claude/agents/omp-flow-research.md +++ b/templates/claude/agents/omp-flow-research.md @@ -33,25 +33,17 @@ Require the task Bundle root, research role, bounded objective/question, entry C output Concept, actorId, and opaque receipt. Missing required content is a blocker. Read the entry and follow only useful links; do not pull a generated context or discover another task. -## Workflow - -1. Inspect linked framing, the current problem/decision and any provisional first-principles anchor - (第一性锚定 / 主要矛盾), repository code/tests/history, applicable Wiki knowledge, and primary - external sources. -2. Practice 实事求是: actively test the anchor or problem against the strongest counter-evidence, - separating confirmed facts, interpretations, counter-evidence, unknowns, and candidate decisions. -3. Cite internal `file:line` evidence and external stable URLs with revision/version/date. -4. State what the evidence confirms, revises, or falsifies in the anchor or decision, or why no - consequential decision changes. Write the complete result to the assigned output and link it to - the question it informs. -5. Identify useful repository URL, revision, and anchors for the ignored clone cache. Write or - recommend one task-local Reference Concept with provenance and local interpretation; never - create paired metadata or copied tiers. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-research/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded research +duty and assigned output; this card's native identity, startup and binding gates, assignment, +tools, write and progress boundaries, and fail-closed requirements remain authoritative. ## Boundary and Handoff Write only the assigned research/Reference Concept. Do not modify product source, runtime/session -records, platform config, another task, or the human's value/risk ordering. If evidence changes the -problem, recommend returning to Brainstorm rather than rewriting its framing. Return output, +records, platform config, another task, or the human's value/risk ordering. Return output, conclusion, decision impact, unresolved questions, source anchors, actorId, and receipt. Chat-only research is failure. diff --git a/templates/codex/agents/omp-flow-architect.toml b/templates/codex/agents/omp-flow-architect.toml index 211a0a03..f4b1047d 100644 --- a/templates/codex/agents/omp-flow-architect.toml +++ b/templates/codex/agents/omp-flow-architect.toml @@ -13,18 +13,19 @@ Require the task Bundle root, architect role, bounded objective, selected synthe design entry Concept, explicit output paths/scope, actorId, and receipt. Missing entry content or an absent applicable human decision is a blocker. Read normal Markdown and follow useful links. -# Design Work +# Shared Skill Delegation -Write observable requirements to prd.md, architecture and verification to design.md, and only -linked decision/interface/finding Concepts that improve discovery. Retain provenance with normal -links. Do not update a generated context index. +Select exactly one Skill from the bounded assignment before role work: -# Work Mapping +- For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it. +- For approved work mapping only after linked human QbD 1 approval, read + `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it. -After a linked human QbD 1 approval, write descriptive work Concepts with objective, in/out scope, -useful inputs, allowed code/output boundary, done conditions, verification, and expected handoff. -Author work/index.md when prose grouping helps communicate order or parallel work. Do not encode -dependencies or receipts in filenames and do not create a machine DAG. +Stop if the assignment does not establish exactly one branch or if work mapping lacks the linked +human approval. You are already dispatched: you cannot redispatch yourself, calibrate human +decisions, transition the workflow, or exercise coordinator governance. The selected Skill +supplies the positive bounded Design or Decompose duty and assigned output; this card's native +identity, assignment, tools, write boundary, and fail-closed requirements remain authoritative. # Boundary and Handoff diff --git a/templates/codex/agents/omp-flow-check.toml b/templates/codex/agents/omp-flow-check.toml index 6bf8788d..c3673ff3 100644 --- a/templates/codex/agents/omp-flow-check.toml +++ b/templates/codex/agents/omp-flow-check.toml @@ -15,17 +15,13 @@ implementation, Review Concept output, reviewer actorId, opaque receipt, and the implementation receipt as predecessor. The reviewer actor must differ from the implementation actor. Missing input is a blocker. -# Workflow - -1. Resolve the completed predecessor operation and read its output path as the required handoff. - Confirm the handoff links back to the assigned work, then inspect the actual diff and changed - files. -2. Follow useful links to PRD, Design, decisions, interfaces, and source constraints. -3. Check scope, done conditions, correctness, error behavior, security, maintainability, and tests - proportional to risk. -4. Run independent focused verification. -5. Write the supplied Review Concept, link it to work and handoff, and lead with - severity-ordered findings. Record verdict and exact commands/results in readable language. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-check/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded independent +review duty and assigned Review Concept; this card's native identity, assignment, tools, write +boundary, different-actor requirement, and fail-closed requirements remain authoritative. # Boundary and Handoff diff --git a/templates/codex/agents/omp-flow-implement.toml b/templates/codex/agents/omp-flow-implement.toml index 947d86da..4e523b41 100644 --- a/templates/codex/agents/omp-flow-implement.toml +++ b/templates/codex/agents/omp-flow-implement.toml @@ -14,15 +14,13 @@ Require the task Bundle root, implementer role, bounded objective, descriptive w allowed code scope and handoff output Concept, actorId, opaque receipt, and predecessor when supplied. Missing input is a blocker. Do not pull a generated context or guess scope. -# Workflow - -1. Read the work Concept and follow only useful links to design, decisions, sources, adjacent code, - and tests. -2. Implement the smallest coherent change inside the stated boundary. -3. Preserve unrelated user/concurrent changes and existing project patterns. -4. Run every verification required by the work plus focused diagnostics. -5. Inspect the diff against every done condition. -6. Write or update the promised handoff Concept and link it to the work. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-implement/SKILL.md` completely and follow it. You +are already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded +implementation duty and assigned handoff; this card's native identity, assignment, tools, write +boundary, and fail-closed requirements remain authoritative. # Boundary and Handoff diff --git a/templates/codex/agents/omp-flow-qbd.toml b/templates/codex/agents/omp-flow-qbd.toml index 503708c7..38147c22 100644 --- a/templates/codex/agents/omp-flow-qbd.toml +++ b/templates/codex/agents/omp-flow-qbd.toml @@ -15,28 +15,19 @@ audit output Concept, actorId, opaque receipt, and predecessor when supplied. Mi assignment or mechanical authorization is a hard blocker. Use NEEDS_EVIDENCE only when missing or contradictory evidence prevents judging a decision-critical consequence. -# Workflow - -1. Read the entry and useful links for the current decision, unacceptable consequences, audit - scope/change, prior closed findings, and accepted risks; do not require fixed fields or headings. -2. Separate confirmed evidence, assumptions, strongest counter-evidence, and accepted risk. -3. QbD 1 challenges the problem, synthesis, requirements, architecture, boundaries, alternatives, - sources, and interfaces. -4. QbD 2 challenges the authored work map, relevant work Concepts, ordering, boundaries, done - conditions, and verification. -5. Separate decision-critical findings from advisory observations. For each blocker, state - cause -> consequence -> decision, the minimum repair, and why removal or safe degradation is - insufficient. PASS may include advisory observations or residual risk. -6. Write exactly the assigned audit Concept with verdict PASS/FAIL/NEEDS_EVIDENCE, risk, findings, - exact next decision/options, and evidence anchors. Do not command a fresh audit. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-qbd/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded QbD duty +and assigned audit output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. # Boundary and Handoff Do not modify PRD, Design, work, sources, code, human decisions, or runtime records. Return output, verdict, risk, blocking count, actorId, receipt, and exact next decision/options for human -calibration. Do not describe an unresolved FAIL or decision-critical NEEDS_EVIDENCE as ordinary -accepted risk that lets the original scope continue; the available directions are repair/evidence, -removal or safe degradation, deferral, or stop. Model PASS still requires a linked human decision. +calibration. """ [features] diff --git a/templates/codex/agents/omp-flow-research.toml b/templates/codex/agents/omp-flow-research.toml index b7411ee8..4d5329e9 100644 --- a/templates/codex/agents/omp-flow-research.toml +++ b/templates/codex/agents/omp-flow-research.toml @@ -14,26 +14,18 @@ Require the task Bundle root, research role, bounded objective/question, entry C output Concept, actorId, and opaque dispatch receipt. Missing required content is a blocker. Read the entry and follow only useful links; do not pull a generated context or discover another task. -# Workflow - -1. Inspect linked framing, the current problem/decision and any provisional first-principles anchor - (第一性锚定 / 主要矛盾), repository code/tests/history, applicable Wiki knowledge, and relevant - primary external sources. -2. Practice 实事求是: actively test the anchor or problem against the strongest counter-evidence, - separating confirmed facts, interpretations, counter-evidence, unknowns, and candidate decisions. -3. Cite internal file:line evidence and external stable URLs with revision/version/date. -4. State what the evidence confirms, revises, or falsifies in the anchor or decision, or why no - consequential decision changes. Write the complete result to the assigned output and link it to - the question it informs. -5. For a useful repository, identify URL, revision, and anchors for the ignored clone cache and - write or recommend one task-local Reference Concept with provenance and local interpretation. - Never create paired metadata or copied tiers. +# Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-research/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded research +duty and assigned output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. # Boundary and Handoff Write only the assigned research/Reference Concept. Do not modify product source, runtime/session -records, platform config, another task, or the human's value/risk ordering. If evidence changes the -problem, recommend returning to Brainstorm rather than rewriting its framing. Return output, +records, platform config, another task, or the human's value/risk ordering. Return output, conclusion, decision impact, unresolved questions, source anchors, actorId, and receipt. Chat-only research is failure. """ diff --git a/templates/codex/hooks/protect-runtime.py b/templates/codex/hooks/protect-runtime.py index ad704a58..0f848a4a 100644 --- a/templates/codex/hooks/protect-runtime.py +++ b/templates/codex/hooks/protect-runtime.py @@ -116,8 +116,8 @@ def _extract_paths(command: str) -> list[str]: def _contains(parent: Path, child: Path) -> bool: - parent_text = os.path.normcase(str(parent)) - child_text = os.path.normcase(str(child)) + parent_text = os.path.normcase(str(parent)).casefold() + child_text = os.path.normcase(str(child)).casefold() try: return os.path.commonpath([parent_text, child_text]) == parent_text except ValueError: diff --git a/templates/common/skills/omp-flow-brainstorm/SKILL.md b/templates/common/skills/omp-flow-brainstorm/SKILL.md index a7c801f8..8f2ddf03 100644 --- a/templates/common/skills/omp-flow-brainstorm/SKILL.md +++ b/templates/common/skills/omp-flow-brainstorm/SKILL.md @@ -16,10 +16,11 @@ description: Explore and clarify a consented omp-flow task Bundle when direction For a non-trivial Explore, use repository/Wiki evidence and human calibration to form or revise a provisional first-principles anchor(第一性锚定)before broad Research. Keep it in useful authored -prose, not a required file or fixed checklist. It should be sufficient to expose the observable -problem, current principal contradiction(主要矛盾), irreducible outcome, human boundaries, a -strong counter-hypothesis, and evidence that would revise the framing. Mechanical low-ambiguity -work may proceed directly when this step would not improve a decision. +prose, not a required file or fixed checklist. It should be sufficient to expose the concrete +actors and action, observable intended outcome, current principal contradiction(主要矛盾), +irreducible outcome, human boundaries, a strong counter-hypothesis, and evidence that would +revise the framing. Mechanical low-ambiguity work may proceed directly when this would not improve +a decision. Concentrate interaction on the material decision frontier: @@ -33,11 +34,13 @@ Concentrate interaction on the material decision frontier: ## Interview Contract 1. Read the entry Concept and follow only useful links from the Bundle. -2. Record the initial request and known repository facts in the assigned framing Concept. +2. Record the initial request, concrete actors/action/outcome, current principal contradiction, + and known repository facts in the assigned framing Concept. 3. Inspect code, tests, docs, prior tasks, relevant history, and applicable durable knowledge through the native `omp-flow-wiki` Skill before asking repository-answerable questions. -4. Ask the user one material decision question at a time. Ask only about intent, preference, - scope, risk tolerance, or ambiguity that evidence cannot answer. +4. Ask the user one material decision question at a time. Ask only about purpose, value, risk + tolerance, preference, or use that repository and other relevant practice evidence cannot + establish. 5. Keep confirmed facts, assumptions, disagreements, alternatives, constraints, success criteria, and open questions distinct. 6. Present materially different directions only when a real choice exists. Follow the human-first diff --git a/templates/common/skills/omp-flow-check/SKILL.md b/templates/common/skills/omp-flow-check/SKILL.md index 8402cbde..8bccef4a 100644 --- a/templates/common/skills/omp-flow-check/SKILL.md +++ b/templates/common/skills/omp-flow-check/SKILL.md @@ -18,6 +18,15 @@ Fail closed unless all are available: ## Review Order +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Reviewer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Reviewer still owns the complete +bounded independent Review and assigned Review Concept: compare actual code and verification with +the intended work/Design consequence, and report evidence contradicting the Design or its +principal-problem framing through that output rather than let a handoff or superficial green check +substitute for the practice result. + 1. Resolve the completed predecessor operation and use its output path as the required handoff. Read the work Concept and handoff, verify they identify each other, then inspect the real diff and changed files. diff --git a/templates/common/skills/omp-flow-decompose/SKILL.md b/templates/common/skills/omp-flow-decompose/SKILL.md index d76b5885..6231da9f 100644 --- a/templates/common/skills/omp-flow-decompose/SKILL.md +++ b/templates/common/skills/omp-flow-decompose/SKILL.md @@ -12,6 +12,14 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Architect: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. After linked human QbD 1 approval, the +Architect still owns the complete bounded Decompose responsibility and assigned work outputs: map +the approved Design into bounded, independently reviewable work Concepts and an authored prose +execution view, without inventing approval or encoding a machine DAG. + 1. Identify the smallest independently implementable and reviewable work items. Fold scaffolding and docs into the deliverable that needs them. 2. Write one descriptive work Concept per item with objective, in/out scope, useful linked inputs, @@ -26,8 +34,10 @@ description: Map an approved omp-flow design into descriptive, bounded work Conc ## Exit Gate -Prepare QbD 2 only when every work item is bounded, testable, understandable from its entry path, -and worth independent review. Load `omp-flow-qbd` next. +In Main/coordinator context only, prepare QbD 2 and load `omp-flow-qbd` when every work item is +bounded, testable, understandable from its entry path, and worth independent review. The +already-dispatched Architect returns the assigned work map and does not choose or perform that +transition. ## Red Flags diff --git a/templates/common/skills/omp-flow-design/SKILL.md b/templates/common/skills/omp-flow-design/SKILL.md index 1bc729a6..8742fc3f 100644 --- a/templates/common/skills/omp-flow-design/SKILL.md +++ b/templates/common/skills/omp-flow-design/SKILL.md @@ -13,11 +13,20 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re ## Procedure -1. Dispatch the native Architect with Bundle root, selected synthesis entry, bounded objective, - relevant linked Concepts, explicit output ownership, actor ID, and receipt. Create the - operation first and forward its complete returned assignment unchanged with native item - `id = actor_id = actorId` and matching descriptor role. Preserve the strict v1 - `ompFlowDispatch` descriptor as the first non-blank line. +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Architect: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Architect still owns +the complete bounded Design responsibility and assigned PRD/Design/decision/interface outputs: +explain each proposed component's concrete causal purpose in plain language, without relying on its +own terminology, and solve the evidenced principal contradiction rather than a secondary or +invented mechanism. + +1. In Main/coordinator context only, dispatch the native Architect with Bundle root, selected + synthesis entry, bounded objective, relevant linked Concepts, explicit output ownership, actor + ID, and receipt. Create the operation first and forward its complete returned assignment + unchanged with native item `id = actor_id = actorId` and matching descriptor role. Preserve the + strict v1 `ompFlowDispatch` descriptor as the first non-blank line. 2. Rewrite `prd.md` into observable requirements, non-goals, constraints, acceptance criteria, and unresolved product decisions. Remove temporary brainstorm duplication. 3. Write `design.md` with components, interfaces, data flow, state ownership, error behavior, migration/compatibility, verification strategy, and rejected alternatives. 4. Add linked decision, interface, brief, or finding Concepts only when they improve navigation or @@ -34,8 +43,10 @@ description: Turn a selected synthesis in an omp-flow task Bundle into linked re - No unresolved question blocks decomposition. - Linked sources and accepted contracts agree with the Design. -Load `omp-flow-qbd` for independent challenge and record the human decision as a linked Concept. -Do not create implementation work before human QbD 1 approval. +In Main/coordinator context only, load `omp-flow-qbd` for independent challenge and obtain and +record the human decision as a linked Concept. The already-dispatched Architect returns its +assigned outputs and does not choose or perform that transition. Do not create implementation work +before human QbD 1 approval. ## Red Flags diff --git a/templates/common/skills/omp-flow-finish/SKILL.md b/templates/common/skills/omp-flow-finish/SKILL.md index d2f76d56..95cf9c1a 100644 --- a/templates/common/skills/omp-flow-finish/SKILL.md +++ b/templates/common/skills/omp-flow-finish/SKILL.md @@ -17,14 +17,34 @@ description: Complete integration verification, deliberate knowledge harvest, co 2. Compare the integrated result against PRD acceptance criteria, cross-row interfaces, migrations, docs, and compatibility requirements. 3. Resolve failures through the owning work/design Concept and repeat independent review or the applicable gate. Do not hide failures with warning-only fallbacks. -4. Review accepted decisions, repeated patterns, and confirmed findings for durable value. -5. Use the native `omp-flow-wiki` Skill to promote only evidenced, reusable knowledge. If nothing qualifies, state that no harvest was needed. -6. Inspect final diff and repository status. Commit through the Harness-native Git workflow when requested. -7. Archive the Bundle only after completion is real and no runtime operation is active. +4. Review accepted decisions, repeated patterns, and confirmed findings for immediate durable value. + Use the native `omp-flow-wiki` Skill only when the evidence already supports promotion; do not + invent knowledge to satisfy Finish. +5. Inspect final diff and repository status. Create the requested Git checkpoint before Archive so + the Task Bundle has a reproducible source commit/tree. +6. Archive the Bundle only after completion is real and no runtime operation is active. Inspect the + returned `sleepSource`; never reconstruct one from the archive path. +7. When `sleepSource.ready` is true, run `sleep start --source --actor-id `, + load the native `omp-flow-sleep` Skill, and forward its complete assignment unchanged as the sole + native assignment input. Normal `sleep start` delivery is primary. If that delivery is lost or + visibly truncated while its active receipt is known, recover only by capturing the complete + `sleep show ` subprocess/API stdout through successful process completion, parsing all + captured stdout as JSON into the show run mapping, requiring string `run.assignment`, and + forwarding that decoded string unchanged as the sole native assignment input, including its + trailing LF. Rendered Bash/terminal output is diagnostic only: never copy or parse it, add a + prefix or suffix, reconstruct or reserialize the assignment, fall back to `sleep list`, or issue + a duplicate `sleep start`. A nonzero exit, incomplete capture, invalid JSON, or missing or + non-string `run.assignment` is delivery failure and must stop before native dispatch. Complete + the Sleep run before final handoff; zero Candidates is valid. +8. When the source is not ready, report its exact reason instead of asking the user to operate Sleep + manually or manufacturing a checkpoint. Sleep Candidate review and Wiki promotion remain + separate work after the run. ## Final Handoff -Report behavior delivered, important decisions, verification results, archived task path, commit identity when created, and remaining non-blocking risks. +Report behavior delivered, important decisions, verification results, archived task path, commit +identity when created, Sleep run/Candidate outputs or the exact unavailable reason, and remaining +non-blocking risks. ## Red Flags diff --git a/templates/common/skills/omp-flow-implement/SKILL.md b/templates/common/skills/omp-flow-implement/SKILL.md index e4bd10ca..46380aca 100644 --- a/templates/common/skills/omp-flow-implement/SKILL.md +++ b/templates/common/skills/omp-flow-implement/SKILL.md @@ -18,6 +18,14 @@ Fail closed unless all are available: ## Procedure +Only Main/coordinator may dispatch, correlate operations/receipts, obtain or record human +calibration, and choose a workflow transition. Those coordinator actions are inapplicable to an +already-dispatched Implementer: it must not dispatch or self-redispatch, govern, calibrate, +transition, or selectively reinterpret coordinator clauses. The Implementer still owns the +complete bounded implementation and assigned handoff: return the approved Design to practice +through code, execution, and real verification, and report contradictory evidence as a +Design-return signal rather than special-case reality to preserve Design authority. + 1. Read the work Concept first. Follow only useful links to design, decisions, sources, and relevant existing code/tests. 2. Restate the bounded objective, output boundary, done conditions, and verification before editing. @@ -32,7 +40,8 @@ Fail closed unless all are available: Write or update the promised handoff Concept and link it back to the work it implements. Return `DONE`, `DONE_WITH_CONCERNS`, `NEEDS_CONTEXT`, or `BLOCKED`, plus changed files, commands, test counts, decisions, caveats, output path, actor ID, and receipt. Do not mutate runtime/session -records. Implementation success goes to an independent review operation. +records. The Implementer returns this assigned handoff; only Main/coordinator chooses and +dispatches the independent Review operation. ## Red Flags diff --git a/templates/common/skills/omp-flow-learn/SKILL.md b/templates/common/skills/omp-flow-learn/SKILL.md new file mode 100644 index 00000000..c986e8ca --- /dev/null +++ b/templates/common/skills/omp-flow-learn/SKILL.md @@ -0,0 +1,127 @@ +--- +name: omp-flow-learn +description: Maintain and use repository-root .omp-flow/learn for deliberate, reciprocal, resumable Human–Agent co-learning when a human is present and pursuing understanding rather than production execution. +--- + +# OMP-Flow Learn + +Use repository-root `.omp-flow/learn/` when a human is actively pursuing mutual understanding, +explanation, challenge, reconsideration, or reflection. Learn is a human-present dialogue in which +both participants may correct their models; autonomous harvesting, passive one-way tutoring, or +summary generation is not a substitute. + +Production work normally pauses during a Learn conversation. Source and code inspection, worked +examples, counterexamples, and discussion remain available, but do not execute production work +until the human returns the conversation to production. + +## Consult and bootstrap + +Open a known Learn Concept directly when its path is available. Otherwise start at +`.omp-flow/learn/index.md` and follow only ordinary links useful to the current discussion. Indexes +support navigation; they are not exhaustive manifests. + +When Learn is genuinely needed and the root is absent, bootstrap only the root index and the +`daily/`, `threads/`, and `retrospectives/` indexes described by the canonical minimal structure. +Do not pre-populate speculative encounters, a taxonomy, or companion records. + +## Preserve a resumable checkpoint + +Use judgment to select or create a bundle immediately below the relevant stable directory. Name a +new bundle `YYYY-MM-DD-/` and maintain its authored `index.md` so a later human and Agent can +recover the useful current understanding, disagreement, correction, or open point. Add only +concrete descriptive Markdown Concepts that make the learning easier to resume or challenge. + +A Daily records a useful dated encounter and may stand alone. A Thread is warranted only when a +topic needs continuity across encounters. A Retrospective is warranted only for a substantive +lesson about understanding or collaboration. Do not manufacture a Thread or Retrospective to +complete a set. + +Treat the human's corrections, rejected premises, values, business context, and objections as +learning material. Make corrected Agent assumptions visible when that helps resumption. Accuracy +comes from reciprocal correction and evidence, not from fluent prose or Agent confidence. + +## Authority and continuity boundaries + +Learn is provisional authored context, not proof of understanding or completion. + +- A Learn artifact cannot advance, pause-state, approve, dispatch, or otherwise alter an omp-flow + Task. A Task link is contextual; commitments remain authored in the applicable Task Bundle. +- A Learn artifact is not Wiki authority and is never promoted automatically. Durable knowledge + reaches `.omp-flow/wiki/` only through ordinary evidence-based Wiki maintenance. +- Cross-session continuity is limited to visible authored artifacts. Never claim a hidden user + profile, persistent personal memory, or model-weight change. + +## Select the smallest useful lens + +The lenses below are a selectable conversational repertoire, not stages, a checklist, a catechism, +an assessment, or an Agent-led teaching script. Choose the smallest lens that addresses the live +misunderstanding. Combine lenses only when one supplies a relevant corrective to another. Concrete +project facts, code, sources, worked cases, and the human's correction outrank philosophical labels. +Stop when the participants have a useful explanation, disagreement, or open point; do not march +through the remaining lenses. + +### Feynman-style self-explanation + +Invite a plain account of one concrete causal link. Find the first hidden term, unsupported leap, or +failed application, then repair it from a source or worked case. Fluency is only a possible gap +diagnostic and never proof of mastery. Do not attribute the modern packaged “Feynman Technique” to +Feynman. + +### Cargo Cult Science integrity + +For a consequential explanation, volunteer the material contrary fact, plausible alternative, +uncertainty, and observation that could change the conclusion so the other participant can judge +it. This is judgment about material disclosure, not four mandatory headings, a fixed response form, +or a ritual inventory of every caveat. + +### Grounded first principles + +Distinguish observed fact, definition, hard constraint, value choice, assumption, and convention. +Trace only premises capable of changing the present conclusion, retain the conditions under which +it should be revised, and stop when further reduction would not help. Existing knowledge and +history are evidence to examine, not impurities to discard. + +### Practice-led principal-contradiction analysis + +Offer the principal contradiction, dominant aspect, and material secondary coupling only as a +revisable prioritization hypothesis tied to current effects. Name the changed condition or practical +observation that would reorder it. Returning to practice may mean sources, code inspection, +examples, counterexamples, a diagram, or later observable verification; it does not authorize +production execution while Learn is paused. Do not import a universal single-cause claim or +political doctrine. + +### Material history or genealogy + +Use a concise temporal account only when it clarifies the present. Connect a concrete problem and +conditions to a prior arrangement, emergence or adoption, limitation, and later change; include a +discontinuity where needed and label interpretive causality. Reject inevitable or present-purpose +origin stories, mechanically economic single-causality, and political doctrine; examine interacting +causes and source support. + +### Reciprocal Socratic questioning + +Use a few genuine reasons, counterexamples, and consequence questions to test either participant's +claim. Either participant may reject a premise, ask the Agent to answer directly, or leave an aporia +open. Questions yield to direct explanation or admitted uncertainty when more useful and never +steer assent toward a conclusion the Agent selected in advance. + +### Minimal structural box-drawing + +Draw labeled ASCII, Unicode, or Mermaid boxes and arrows only when a few elements at one useful +abstraction level make a particular structural inference cheaper than prose. Check the picture +against sources, code, examples, or the participants' model; revise or discard it when it does not +help. A diagram is not inherently clarifying. + +These lenses create optional corrective friction rather than a composite routine: explanation +answers to integrity and evidence; alleged hard constraints to history; principal ranking to +secondary couplings and changed conditions; historical narrative to discontinuity and interacting +causes; questions to reciprocal answerability; and diagrams to prose, source, or practice +comparison. They do not adopt a complete philosophical school or establish mastery. + +## Keep Learn conversational + +Do not introduce an entry command, pause or save signal, fixed encounter stages, required +transcript or summary, mandatory headings, score, metric, completion gate, approval ceremony, or +per-edit human approval rule. There is no parsed body schema, lifecycle record, second task system, +or automatic learning judgment. Preserve only what is genuinely useful for reciprocal resumption, +and return to production only when the human changes the conversation back to production work. diff --git a/templates/common/skills/omp-flow-qbd/SKILL.md b/templates/common/skills/omp-flow-qbd/SKILL.md index 9b092c0e..686d6174 100644 --- a/templates/common/skills/omp-flow-qbd/SKILL.md +++ b/templates/common/skills/omp-flow-qbd/SKILL.md @@ -19,17 +19,27 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Auditor: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Auditor still owns the +complete bounded independent audit and assigned audit Concept: reconstruct the concrete problem +without solution jargon, challenge whether the selected problem and current principal +contradiction still hold before judging architecture completeness, preserve the mechanical safety +analysis, and report the required verdict, findings, evidence, and contradictions through that +output boundary. + 1. Identify the design or work-map entry Concept and an explicit audit output Concept. Through its useful links, bind the audit to the current decision, unacceptable consequences, current scope/change, and relevant closed findings, residual risks, and human decisions. Do not require a fixed audit-brief file or field shape; no prior findings is normal for a first audit. -2. Start one independent QbD operation with Bundle root, role, bounded objective, entry, output, - actor ID, and optional predecessor receipt. -3. Dispatch one independent native `qbd-auditor`. Pass the paths and opaque receipt returned by - the runtime by forwarding the complete returned assignment unchanged. Keep its strict v1 - `ompFlowDispatch` descriptor as the first non-blank line, set native item - `id = actor_id = actorId`, and use the matching descriptor role. Do not render the Bundle, - reconstruct the descriptor, or prepend audit prose. +2. In Main/coordinator context only, start one independent QbD operation with Bundle root, role, + bounded objective, entry, output, actor ID, and optional predecessor receipt. +3. In Main/coordinator context only, dispatch one independent native `qbd-auditor`. Pass the paths + and opaque receipt returned by the runtime by forwarding the complete returned assignment + unchanged. Keep its strict v1 `ompFlowDispatch` descriptor as the first non-blank line, set + native item `id = actor_id = actorId`, and use the matching descriptor role. Do not render the + Bundle, reconstruct the descriptor, or prepend audit prose. 4. Require an explicit verdict with these semantics: - `FAIL` requires evidence of a critical falsehood, authorization or data violation, irreversible harm, or an unrealizable/unverifiable core path for which safe degradation is @@ -42,15 +52,21 @@ description: Coordinate an independent Quality-by-Design audit over linked Bundl decision, give the smallest remedy, and explain why hiding, `unavailable`, disabling, narrowing, refusal to write, or another safe degradation is insufficient. Findings without that chain are advisory. -6. Confirm the promised audit Concept exists, links to what it evaluated, and records material - findings. Finish the runtime operation with the same actor ID. -7. Present material findings and the applicable governance options to the user. Only the user - decides calibration; the verdict itself authorizes no repair, re-audit, or forward transition. -8. Record the human decision in a linked decision Concept. Do not encode approval, materiality, or - risk as runtime phase or parsed state. +6. In Main/coordinator context only, confirm the promised audit Concept exists, links to what it + evaluated, and records material findings, then finish the runtime operation with the same actor + ID. The already-dispatched Auditor returns that assigned audit output; it does not finish or + correlate the coordinator's operation. +7. In Main/coordinator context only, present material findings and applicable governance options + to the user. Only the user decides calibration; the verdict itself authorizes no repair, + re-audit, or forward transition. +8. In Main/coordinator context only, record the human decision in a linked decision Concept. Do + not encode approval, materiality, or risk as runtime phase or parsed state. ## Transitions +These routing choices are Main/coordinator-only and inapplicable to an already-dispatched Auditor, +which returns the assigned audit findings and verdict without choosing or performing a transition. + - Recorded QbD 1 human PASS -> load `omp-flow-decompose`. - Recorded QbD 2 human PASS -> load `omp-flow-execute`. - Advisory risk, `PASS` residual risk, or risk made non-blocking by removal, disabling, narrowing, diff --git a/templates/common/skills/omp-flow-research/SKILL.md b/templates/common/skills/omp-flow-research/SKILL.md index 0a79cf04..ae06c006 100644 --- a/templates/common/skills/omp-flow-research/SKILL.md +++ b/templates/common/skills/omp-flow-research/SKILL.md @@ -29,13 +29,22 @@ Choose and persist one of: ## Procedure +Before native dispatch, only Main/coordinator may dispatch, correlate operations/receipts, obtain +or record human calibration, and choose a workflow transition. Those coordinator actions are +inapplicable to an already-dispatched Researcher: it must not dispatch or self-redispatch, govern, +calibrate, transition, or selectively reinterpret coordinator clauses. The Researcher still owns +the complete bounded Research responsibility and assigned output: test the framing against +practice, distinguish what evidence proves, does not prove, and merely makes possible, and report a +materially changed principal contradiction as a Brainstorm-return signal rather than protect the +earlier framing. + 1. Split uncertainty into independently investigable questions and create descriptive output paths. -2. Dispatch Harness-native researcher agents when questions can be investigated independently. - Pass Bundle root, role, objective, entry Concept, exact output path, actor ID, receipt, and the - no-implementation boundary. - Start one operation per native task item, then forward its complete returned assignment - unchanged with item `id = actor_id = actorId` and matching descriptor role. The strict v1 - `ompFlowDispatch` descriptor remains the first non-blank line; do not decorate or reconstruct it. +2. In Main/coordinator context only, dispatch Harness-native researcher agents when questions can + be investigated independently. Pass Bundle root, role, objective, entry Concept, exact output + path, actor ID, receipt, and the no-implementation boundary. Start one operation per native task + item, then forward its complete returned assignment unchanged with + `id = actor_id = actorId` and matching descriptor role. The strict v1 `ompFlowDispatch` + descriptor remains the first non-blank line; do not decorate or reconstruct it. 3. Separate facts, interpretations, counter-evidence, unknowns, and recommendations. Actively seek the strongest evidence against the current framing, not only confirmation. Internal claims use `file:line`; external claims use stable source URLs and version/date where relevant. @@ -61,7 +70,8 @@ Choose and persist one of: next decision. - The synthesis lets an Architect design without reconstructing research from chat. -Load `omp-flow-design` next. +In Main/coordinator context only, load `omp-flow-design` next. The already-dispatched Researcher +returns the assigned synthesis/output and does not choose or perform that transition. ## Red Flags diff --git a/templates/common/skills/omp-flow-sleep/SKILL.md b/templates/common/skills/omp-flow-sleep/SKILL.md new file mode 100644 index 00000000..dcf957bd --- /dev/null +++ b/templates/common/skills/omp-flow-sleep/SKILL.md @@ -0,0 +1,63 @@ +--- +name: omp-flow-sleep +description: Consolidate one exact archived OKF Task into reviewable cross-task knowledge candidates after Finish, without machine clustering or direct Wiki promotion. +--- + +# OMP-Flow Sleep + +Use this Skill only with a complete assignment whose first non-blank line is an exact +`{"ompFlowSleep":{...}}` descriptor produced by `.omp-flow/scripts/omp_flow.py sleep start`. +Do not reconstruct, summarize, or guess a descriptor from an archived path. + +## Descriptor contract + +Require `version`, `sourceReceipt`, `sourceTask`, `sourceCommit`, `sourceTree`, `entry`, +`sleepIndex`, `runOutput`, `candidateRoot`, `actorId`, `receipt`, and `harvesterRevision`. +Require `version` exactly `1`, the assignment actor to match `actorId`, and every supplied path to +remain within the repository. Treat `sourceReceipt`, `sourceCommit`, `sourceTree`, `receipt`, and +`harvesterRevision` as opaque mechanical identity, not semantic evidence. + +## Method + +1. Read the archived Task `entry` and follow only the Task Concepts needed to understand accepted + outcomes, independent Review, verification, repeated findings, counterexamples, and expensive + reasoning. Do not read raw Harness transcripts. +2. Read `sleepIndex`. Use authored links, ordinary filenames, repository text search, and direct + understanding of the smallest relevant Candidate/Wiki topics. Do not use embedding, vector + retrieval, similarity thresholds, automatic taxonomy, a knowledge graph, or a fixed evidence + schema. +3. Decide whether the Task supports zero, one, or several durable candidates. A Task-local fact, + unverified explanation, generic lesson, or restatement of the Task is a valid zero-candidate + result. +4. For each useful topic, revise an existing Markdown Candidate beneath `candidateRoot` or create a + self-contained one. Preserve ordinary links to the source Task and distinguish supporting + evidence, contrary evidence, applicability boundaries, unresolved questions, and possible Wiki + or Skill consequences. Never average a conflict into false consensus. +5. Write one OKF Run handoff at the exact `runOutput`. State what was read, which Candidates were + created or revised, why other observations were not promoted, and what review or experiment is + still required. This handoff is authored knowledge; runtime state remains under `.runtime`. +6. Finish the mechanical run with: + + ```text + python -X utf8 .omp-flow/scripts/omp_flow.py sleep finish \ + --state completed --actor-id [--candidate ...] + ``` + + Zero `--candidate` arguments is valid. On failure, call `sleep finish` with `--state failed` and + report the exact blocker; do not manufacture a Candidate or completion claim. + +## Promotion boundary + +Sleep ends with reviewable Candidates, not Wiki authority. Do not edit `.omp-flow/wiki/`, Harness +Skills, or workflow policy from this assignment. A different actor should independently challenge +material Candidates. Facts may use proportional Wiki Review; architecture, methodology, or Agent +behavior changes require a new Task framing and the applicable Research, Design, QbD, paired +benchmark, and human decision. An Agent or Reviewer `PASS` is not human approval. + +## Red flags + +- Do not accept an archived path without the runtime-produced source receipt and Git checkpoint. +- Do not force one Candidate per Task or duplicate one Candidate per Run. +- Do not parse authored Markdown into lifecycle state or mandatory fields. +- Do not claim source stability after the runtime reports source drift. +- Do not auto-adopt, auto-merge, auto-promote, or silently overwrite concurrent Candidate work. diff --git a/templates/common/skills/omp-flow/SKILL.md b/templates/common/skills/omp-flow/SKILL.md index da0af2ce..b1446d25 100644 --- a/templates/common/skills/omp-flow/SKILL.md +++ b/templates/common/skills/omp-flow/SKILL.md @@ -41,9 +41,12 @@ When there is no active task, classify before creating one: | User explicitly requests omp-flow | Enter the workflow | Do not create a task merely because a task could be useful. Once the user consents, create the -Bundle, open its root index, and load `omp-flow-brainstorm`. For non-trivial Explore, Brainstorm -first forms a provisional first-principles anchor(第一性锚定)around the observable problem and -principal contradiction(主要矛盾); mechanical low-ambiguity work does not need this ceremony. +Bundle, open its root index, and load `omp-flow-brainstorm`. When selecting work or framing a +bounded assignment, preserve the current concrete decision, non-sacrificable human boundary, +revisable principal contradiction(主要矛盾), and evidence that could change it; do not pre-commit +a hypothetical mechanism merely because it is easy to name. For non-trivial Explore, Brainstorm +first forms a provisional first-principles anchor(第一性锚定)around that concrete problem; +mechanical low-ambiguity work does not need this ceremony. ## Operation Routing diff --git a/templates/omp/agents/architect.md b/templates/omp/agents/architect.md index 024b8e09..f2245334 100644 --- a/templates/omp/agents/architect.md +++ b/templates/omp/agents/architect.md @@ -16,18 +16,19 @@ design entry Concept, explicit output paths/scope, actor ID, and receipt. Missin an absent applicable human decision is a blocker. Read normal Markdown and follow only useful links. -## Design Work +## Shared Skill Delegation -Write observable requirements to `prd.md`, architecture and verification to `design.md`, and only -the linked decision/interface/finding Concepts that improve discovery. Retain provenance through -ordinary links. Do not update a generated context index. +Select exactly one Skill from the bounded assignment before role work: -## Work Mapping +- For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it. +- For approved work mapping only after linked human QbD 1 approval, read + `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it. -After a linked human QbD 1 approval, write descriptive work Concepts with objective, in/out scope, -useful inputs, allowed code/output boundary, done conditions, verification, and expected handoff. -Author `work/index.md` when prose grouping helps communicate order or parallel work. Do not encode -dependencies or receipts in filenames and do not create a machine DAG. +Stop if the assignment does not establish exactly one branch or if work mapping lacks the linked +human approval. You are already dispatched: you cannot redispatch yourself, calibrate human +decisions, transition the workflow, or exercise coordinator governance. The selected Skill +supplies the positive bounded Design or Decompose duty and assigned output; this card's native +identity, assignment, tools, write boundary, and fail-closed requirements remain authoritative. ## Boundary and Handoff diff --git a/templates/omp/agents/executor.md b/templates/omp/agents/executor.md index 44766960..29589a87 100644 --- a/templates/omp/agents/executor.md +++ b/templates/omp/agents/executor.md @@ -16,16 +16,13 @@ Require the task Bundle root, executor role, bounded objective, descriptive work allowed code scope and handoff output Concept, actor ID, opaque receipt, and predecessor when supplied. Missing input is a blocker. Do not guess scope or use a legacy context renderer. -## Workflow - -1. Read the work Concept, then follow only useful links to design, decisions, sources, adjacent - implementation, and tests. -2. Restate the boundary internally and implement the smallest coherent change. -3. Preserve unrelated user/concurrent changes and existing project patterns. -4. Run every verification required by the work plus focused diagnostics. -5. Inspect the diff against every done condition. -6. Write or update the promised handoff Concept, link it to the work, and record changed files, - commands/results, decisions, and caveats. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-implement/SKILL.md` completely and follow it. You +are already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded +implementation duty and assigned handoff; this card's native identity, assignment, tools, write +boundary, and fail-closed requirements remain authoritative. ## Boundary and Handoff diff --git a/templates/omp/agents/orchestrator.md b/templates/omp/agents/orchestrator.md index 4f73b815..8c4d3581 100644 --- a/templates/omp/agents/orchestrator.md +++ b/templates/omp/agents/orchestrator.md @@ -7,8 +7,10 @@ tools: read, write, edit, bash, grep, glob, todo, task, job, irc, ask, resolve # Orchestrator Agent -Select this session's task Bundle and open its root `index.md`. Decide the next useful operation -from the linked Concepts; do not infer a lifecycle phase or topology from Markdown. +Before coordinator work, read `.agents/skills/omp-flow/SKILL.md` completely and follow it. +You are already the native Main orchestrator selected by this Harness. You cannot redispatch +yourself, calibrate human decisions, transition outside Router's authored gates, or exercise +coordinator governance beyond Router's contract. Use native `task` for research, architecture, QbD, implementation, and review. Before dispatch, start a runtime operation with explicit Bundle/task path, entry Concept, role, actor ID, bounded @@ -21,20 +23,6 @@ Set native task item `id` to the returned operation's `actor_id`/descriptor `act the native role matching descriptor `role`. Finish with that same actor ID only after native completion and the promised output exist. -For a non-trivial Explore, have Brainstorm form a provisional first-principles anchor: the -observable problem, principal contradiction, strongest counter-hypothesis, and revision evidence. -Treat this as 实践论 / 实事求是: Research may confirm, revise, or falsify the anchor; it is not a -phase, schema, or permanent answer. Brainstorm and research may alternate. A selected synthesis -leads to design; human-approved QbD leads to a readable work map; implementation produces a linked -handoff; a fresh independent actor reviews that work through the completed implementation receipt. - -Present each QbD verdict and its exact next options for linked human calibration before further -dispatch. Do not automatically order a fresh audit. An unresolved `FAIL` or decision-critical -`NEEDS_EVIDENCE` cannot become executable residual risk merely by renaming it accepted risk; offer -repair/evidence, removal or safe degradation, deferral, or stop. If the human may change a -non-negotiable value/risk boundary, return to Brainstorm or Design and use targeted Grill only when -the consequence warrants it. - Do not implement application code yourself. Do not edit runtime/session operation records. Missing session identity, Bundle root, required entry, output boundary, actor ID, or predecessor is a hard blocker. Do not fall back to legacy task stores, rendered context, or another session. diff --git a/templates/omp/agents/qbd-auditor.md b/templates/omp/agents/qbd-auditor.md index 5737c118..d4167c84 100644 --- a/templates/omp/agents/qbd-auditor.md +++ b/templates/omp/agents/qbd-auditor.md @@ -16,26 +16,16 @@ audit output Concept, actor ID, opaque receipt, and predecessor when supplied. M assignment or mechanical authorization is a hard blocker. Use `NEEDS_EVIDENCE` only when missing or contradictory evidence prevents judging a decision-critical consequence. -## Workflow - -1. Read the entry and useful links for the current decision, unacceptable consequences, audit - scope/change, prior closed findings, and accepted risks; do not require fixed fields or headings. -2. Separate confirmed evidence, assumptions, strongest counter-evidence, and accepted risk. -3. For QbD 1, challenge the problem, synthesis, requirements, architecture, boundaries, - alternatives, sources, and interfaces. -4. For QbD 2, challenge the authored work map, every relevant work Concept, ordering, boundaries, - done conditions, and verification. -5. Separate decision-critical findings from advisory observations. For each blocker, state - cause → consequence → decision, the minimum repair, and why removal or safe degradation is - insufficient. `PASS` may include advisory observations or residual risk. -6. Write exactly one linked audit Concept with verdict (`PASS`, `FAIL`, or `NEEDS_EVIDENCE`), risk, - findings, exact next decision/options, and evidence anchors. Do not command a fresh audit. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-qbd/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded QbD duty +and assigned audit output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. ## Boundary and Handoff Write only the supplied audit output. Do not modify PRD, Design, work, sources, code, human decisions, or runtime records. Return output path, verdict, risk, blocking count, actor ID, -receipt, and exact next decision/options for human calibration. Do not describe an unresolved -`FAIL` or decision-critical `NEEDS_EVIDENCE` as ordinary accepted risk that lets the original scope -continue; the available directions are repair/evidence, removal or safe degradation, deferral, or -stop. Model PASS still requires a linked human decision. +receipt, and exact next decision/options for human calibration. diff --git a/templates/omp/agents/researcher.md b/templates/omp/agents/researcher.md index 57cd5b1b..9adc4fb0 100644 --- a/templates/omp/agents/researcher.md +++ b/templates/omp/agents/researcher.md @@ -15,25 +15,17 @@ Require the task Bundle root, role, bounded objective/question, entry Concept, e path, actor ID, and opaque dispatch receipt. Missing required content is a blocker. Read the entry and follow only useful links; do not reconstruct context from chat or legacy stores. -## Workflow - -1. Inspect the linked framing, current problem/decision and any provisional first-principles anchor - (第一性锚定 / 主要矛盾), existing evidence, repository code/tests/history, durable Wiki knowledge, - and relevant primary external sources. -2. Practice 实事求是: actively test the anchor or problem against the strongest counter-evidence, - separating confirmed facts, interpretations, counter-evidence, unknowns, and candidate decisions. -3. Cite internal `file:line` evidence and external stable URLs with revision/version/date. -4. State what the evidence confirms, revises, or falsifies in the anchor or decision, or why no - consequential decision changes. Write the complete result to the assigned output and link it to - the question it informs. -5. For a useful external repository, identify the exact URL, revision, and anchors for the ignored - clone cache. Write or recommend a task-local Reference Concept containing provenance and local - interpretation; never create paired metadata or copied tiers. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-research/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded research +duty and assigned output; this card's native identity, assignment, tools, write boundary, and +fail-closed requirements remain authoritative. ## Boundary and Handoff Write only the assigned research/Reference Concept. Do not modify product source, runtime/session -records, platform config, another task, or the human's value/risk ordering. If evidence changes the -problem, recommend returning to Brainstorm rather than rewriting its framing. Return the output -path, one-line conclusion, decision impact, unresolved questions, source anchors, actor ID, and +records, platform config, another task, or the human's value/risk ordering. Return the output path, +one-line conclusion, decision impact, unresolved questions, source anchors, actor ID, and receipt. Chat-only research is failure. diff --git a/templates/omp/agents/reviewer.md b/templates/omp/agents/reviewer.md index 4d023ab3..2fc0c289 100644 --- a/templates/omp/agents/reviewer.md +++ b/templates/omp/agents/reviewer.md @@ -17,21 +17,16 @@ implementation, descriptive Review Concept output, reviewer actor ID, opaque rec completed implementation receipt as predecessor. The reviewer actor must differ from the implementation actor. Missing input is a blocker. -## Workflow - -1. Resolve the completed predecessor operation and read its output path as the required handoff. - Confirm the handoff links back to the assigned work, then inspect the actual diff and changed - files. -2. Follow only useful links to PRD, Design, decisions, interfaces, and source constraints. -3. Check scope, done conditions, correctness, error behavior, security, maintainability, and test - adequacy proportional to risk. -4. Run independent focused verification. -5. Write the supplied Review Concept, link it to the work and handoff, and lead with - severity-ordered findings. Record verdict and exact commands/results in readable language. +## Shared Skill Delegation + +Before role work, read `.agents/skills/omp-flow-check/SKILL.md` completely and follow it. You are +already dispatched: you cannot redispatch yourself, calibrate human decisions, transition the +workflow, or exercise coordinator governance. The Skill supplies the positive bounded independent +review duty and assigned Review Concept; this card's native identity, assignment, tools, write +boundary, different-actor requirement, and fail-closed requirements remain authoritative. ## Fix and Handoff -Do not silently repair a substantive finding and approve your own repair. Return FAIL to the -owning work unless the assignment explicitly requests a bounded reviewer-fix loop. Do not edit +Do not silently repair a substantive finding and approve your own repair. Do not edit runtime/session records or write an Evidence ledger. Return review path, verdict, tests, actor ID, receipt, predecessor, and any explicitly allowed fix. diff --git a/tests/learn.test.ts b/tests/learn.test.ts new file mode 100644 index 00000000..4c3a4fb8 --- /dev/null +++ b/tests/learn.test.ts @@ -0,0 +1,484 @@ +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; + +import { deployInitResources, getManagedResources } from '../src/cli/init.js'; + +export type LearnCheck = (condition: unknown, message: string) => asserts condition; + +const sourceRoot = process.cwd(); +const learnFiles = [ + 'index.md', + 'daily/index.md', + 'threads/index.md', + 'retrospectives/index.md', +] as const; +const skillDestinations = [ + '.agents/skills/omp-flow-learn/SKILL.md', + '.omp/skills/omp-flow-learn/SKILL.md', + '.claude/skills/omp-flow-learn/SKILL.md', +] as const; + +function read(root: string, relativePath: string): string { + return fs.readFileSync(path.join(root, ...relativePath.split('/')), 'utf8'); +} + +function filesBelow(root: string): string[] { + if (!fs.existsSync(root)) return []; + const files: string[] = []; + const visit = (directory: string): void => { + for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { + const absolute = path.join(directory, entry.name); + if (entry.isDirectory()) visit(absolute); + else if (entry.isFile()) files.push(path.relative(root, absolute).split(path.sep).join('/')); + } + }; + visit(root); + return files.sort(); +} + +function hasAll(content: string, expressions: readonly RegExp[]): boolean { + return expressions.every(expression => expression.test(content)); +} + +type ProhibitedSkillBehavior = { + key: string; + expressions: readonly RegExp[]; +}; + +const prohibitedSkillBehaviors: readonly ProhibitedSkillBehavior[] = [ + { + key: 'required all-lens sequence', + expressions: [ + /\b(?:each|every|all)(?:\s+of\s+the)?(?:\s+seven)?\s+lenses?.{0,60}\b(?:is|are|becomes?|forms?)\s+(?:an?\s+)?(?:required|mandatory)\s+(?:stage|step|sequence)/is, + /\b(?:must|required to|have to)\s+(?:run|use|apply|complete).{0,30}\b(?:all|every)(?:\s+seven)?\s+lenses?\b/is, + ], + }, + { + key: 'fluent explanation proves mastery', + expressions: [ + /\bfluen\w*.{0,35}\b(?:proves?|demonstrates?|establishes?|guarantees?)\b.{0,25}\b(?:understanding|mastery|comprehension)\b/is, + ], + }, + { + key: 'infallible principal cause', + expressions: [ + /\bprincipal contradiction\b.{0,35}\b(?:infallible|universal|single true|cannot be wrong|always determines?)\b/is, + /\bprincipal contradiction\b.{0,35}\b(?:is|reveals?|identifies?)\b.{0,20}\b(?:only|single)\s+(?:real|true|material)?\s*cause\b/is, + ], + }, + { + key: 'deterministic history', + expressions: [ + /\bhistor\w*.{0,30}\b(?:is|was|becomes?|makes?).{0,15}\b(?:inevitable|predetermined|unavoidable)\b/is, + /\b(?:econom\w*|material conditions?).{0,30}\b(?:alone|solely|always)\b.{0,25}\bdetermin/is, + ], + }, + { + key: 'questions steer assent', + expressions: [ + /\bquestions?\b.{0,35}\b(?:must|should|need to|are used to)\b.{0,35}\b(?:steer|guide|lead|move)\b.{0,25}\b(?:assent|agreement|preset|preselected)\b/is, + /\b(?:steer|guide|lead)\b.{0,25}\b(?:the human|participant|user)\b.{0,30}\b(?:Agent's|preset|preselected)\s+(?:answer|conclusion|position)\b/is, + ], + }, + { + key: 'automatic diagram clarity', + expressions: [ + /\b(?:all|every|any)\s+(?:diagram|picture|box drawing)\b.{0,30}\b(?:is|are|makes?).{0,15}\b(?:inherently|automatically|always)\s+(?:clear|clarifying|helpful)\b/is, + /\bdiagrams?\b.{0,25}\b(?:guarantee|prove|ensure)\b.{0,20}\b(?:clarity|understanding|comprehension)\b/is, + ], + }, +]; + +const grammaticalNegation = + /\b(?:not|never|no|cannot|can't|mustn't|shouldn't|isn't|aren't|wasn't|weren't|doesn't|don't|didn't|reject(?:s|ed|ing)?|den(?:y|ies|ied|ying)|refus(?:e|es|ed|ing)|avoid(?:s|ed|ing)?|false)\b/i; + +function detectsProhibitedBehavior(content: string, behavior: ProhibitedSkillBehavior): boolean { + const clauses = content + .split(/(?<=[.!?])(?:[”’"')\]]*)\s+|[;\n]+/) + .map(clause => clause.trim()) + .filter(Boolean); + + return clauses.some(clause => + behavior.expressions.some(expression => { + const matcher = new RegExp(expression.source, expression.flags.replace('g', '') + 'g'); + for (const match of clause.matchAll(matcher)) { + const start = match.index ?? 0; + const context = clause.slice(Math.max(0, start - 48), start + match[0].length); + if (!grammaticalNegation.test(context)) return true; + } + return false; + }), + ); +} + +function assertContradictoryRegressionFixtures(check: LearnCheck): void { + const fixtures = [ + { + key: 'required all-lens sequence', + contradiction: 'The lenses are not a checklist. Each of the seven lenses is a mandatory stage in the encounter.', + faithful: [ + 'You do not have to apply all seven lenses.', + 'All seven lenses do not form a mandatory sequence.', + ], + }, + { + key: 'fluent explanation proves mastery', + contradiction: 'Fluency can reveal gaps. A fluent explanation demonstrates mastery of the topic.', + faithful: [ + 'A fluent explanation does not demonstrate mastery.', + 'Fluency never proves understanding.', + ], + }, + { + key: 'infallible principal cause', + contradiction: 'The ranking is revisable. The principal contradiction identifies the single true cause.', + faithful: [ + 'The principal contradiction is not the single true cause.', + 'Never say the principal contradiction is the only real cause.', + ], + }, + { + key: 'deterministic history', + contradiction: 'Reject simple inevitability stories. The historical outcome was inevitable once those conditions appeared.', + faithful: [ + 'History was not inevitable.', + 'History never makes the outcome unavoidable.', + ], + }, + { + key: 'questions steer assent', + contradiction: "Either participant may reject a premise. Questions should guide the participant toward the Agent's preselected conclusion.", + faithful: [ + 'Do not lead the participant toward a preset answer.', + 'Questions should not guide the participant toward a preselected conclusion.', + ], + }, + { + key: 'automatic diagram clarity', + contradiction: 'Discard unhelpful pictures. Every diagram is automatically clarifying.', + faithful: [ + 'Do not assume every diagram is automatically clarifying.', + 'Diagrams do not ensure understanding.', + ], + }, + ] as const; + + for (const { key, contradiction, faithful } of fixtures) { + const behavior = prohibitedSkillBehaviors.find(candidate => candidate.key === key); + check(Boolean(behavior && detectsProhibitedBehavior(contradiction, behavior)), `contract helper rejects ${key}`); + for (const control of faithful) { + check( + Boolean(behavior && behavior.expressions.some(expression => expression.test(control))), + `negated ${key} control exercises the prohibited expression`, + ); + check( + Boolean(behavior && !detectsProhibitedBehavior(control, behavior)), + `contract helper allows faithful negated ${key} rewrite`, + ); + } + } +} + +function assertIndexContract(check: LearnCheck): void { + const canonicalRoot = read(sourceRoot, 'templates/.omp-flow/learn/index.md'); + const daily = read(sourceRoot, 'templates/.omp-flow/learn/daily/index.md'); + const threads = read(sourceRoot, 'templates/.omp-flow/learn/threads/index.md'); + const retrospectives = read(sourceRoot, 'templates/.omp-flow/learn/retrospectives/index.md'); + + check( + hasAll(canonicalRoot, [ + /human.present/i, + /production.{0,40}(?:pause|halt|suspend|stop)/is, + /human.{0,70}(?:return|resume|switch).{0,35}production/is, + /daily\/index\.md/, + /threads\/index\.md/, + /retrospectives\/index\.md/, + /YYYY-MM-DD-\//, + /authored `index\.md`/i, + /descriptive Markdown Concepts/i, + /not.{0,15}exhaustive/is, + /Daily.{0,100}(?:stand\s+alone|independent|without.{0,15}companion)/is, + /(?:does not|cannot|never).{0,90}(?:alter|change|control).{0,20}omp-flow Task/is, + /(?:not|no).{0,15}Wiki.{0,15}authority/is, + /(?:never|not).{0,25}(?:promoted|publish).{0,20}automatic/is, + ]), + 'Learn root is a human-present maintenance manual with naming, resumption, pause, and authority boundaries', + ); + check( + hasAll(daily, [ + /(?:dated|encounter)/i, + /correct/i, + /resum/i, + /Daily.{0,100}(?:stand\s+alone|independent|without.{0,15}companion)/is, + /(?:never|not|does not).{0,45}(?:require|force).{0,35}(?:Thread|Retrospective)/is, + ]), + 'Daily preserves one warranted encounter without companions', + ); + check( + hasAll(threads, [ + /continuity/i, + /(?:across|spans?).{0,20}encounters?/is, + /shared model/i, + /disagreement|unresolved|open question/i, + /Daily.{0,30}(?:not|never|does not).{0,25}require.{0,15}Thread/is, + ]), + 'Threads preserve only warranted cross-encounter continuity', + ); + check( + hasAll(retrospectives, [ + /substantive/i, + /change|problem|lesson/i, + /Agent.{0,35}(?:explanations?|assumptions?)/is, + /collaborat/i, + /Daily.{0,100}(?:stand\s+alone|independent|without.{0,15}companion)/is, + ]), + 'Retrospectives preserve substantive learning or collaboration reflection only', + ); + for (const [name, content] of [['daily', daily], ['threads', threads], ['retrospectives', retrospectives]] as const) { + check( + hasAll(content, [/YYYY-MM-DD-\//, /authored `index\.md`/i, /descriptive Markdown Concepts/i, /not an exhaustive|not exhaustively|need not exhaustively|rather than an exhaustive/i]), + `${name} documents a dated authored bundle without a closed manifest`, + ); + } +} + +function assertSkillContract(skill: string, check: LearnCheck): void { + check(/^---\r?\nname: omp-flow-learn\r?\n/m.test(skill), 'Learn Skill uses canonical existing-convention frontmatter'); + check( + hasAll(skill, [ + /human.present/i, + /(?:both|either).{0,25}participants?.{0,35}(?:correct|revise|challenge)/is, + /reciprocal/i, + /resum/i, + ]), + 'Learn Skill is human-present, reciprocal, and resumable', + ); + check( + hasAll(skill, [ + /known Learn Concept.{0,20}direct/is, + /start at\s+`.omp-flow\/learn\/index\.md`/i, + /bootstrap.{0,25}(?:only|minimum).{0,20}root index/is, + /genuine.{0,15}need/is, + ]), + 'Learn Skill supports direct/index consultation and need-based bootstrap', + ); + check( + hasAll(skill, [ + /YYYY-MM-DD-\//, + /judg/i, + /Daily.{0,100}(?:stand\s+alone|independent|without.{0,15}companion)/is, + /(?:do not|never).{0,30}(?:manufacture|force|require).{0,35}(?:Thread|Retrospective)/is, + ]), + 'Learn Skill uses judgment for dated bundles and optional companions', + ); + check( + hasAll(skill, [ + /production.{0,40}(?:pause|halt|suspend|stop)/is, + /human.{0,70}(?:return|resume|switch).{0,35}production/is, + ]), + 'Learn Skill pauses production until the human returns to it', + ); + check( + hasAll(skill, [/cannot .*alter an omp-flow\s+Task/is, /not Wiki\s+authority/i, /never promoted automatically/i]), + 'Learn Skill denies Task and Wiki authority transfer', + ); + check( + hasAll(skill, [/autonomous harvesting/i, /one-way tutoring/i, /summary generation is not a substitute/i, /hidden user\s+profile/i, /persistent personal memory/i, /model-weight change/i]), + 'Learn Skill rejects autonomous, one-way, and fictional persistence substitutes', + ); + check( + hasAll(skill, [ + /selectable.{0,35}(?:lens|repertoire)/is, + /(?:not|never).{0,25}(?:stage|checklist)/is, + /(?:smallest|minimal|fewest).{0,25}(?:lens|approach)/is, + /combin\w*.{0,50}(?:correct|repair|failure|weakness)/is, + /\b(?:facts|code|sources|worked cases)\b.{0,80}\b(?:outrank|override|take priority|more authoritative)\b/is, + /human.{0,30}correction.{0,80}\b(?:outrank|override|take priority|more authoritative)\b/is, + /(?:stop|end).{0,80}(?:useful|explanation|disagreement|open point|unresolved)/is, + /(?:do not|never).{0,55}(?:remaining|all|every).{0,25}lenses/is, + ]), + 'Learn Skill selects the smallest evidence-grounded lens and stops without an exhaustive routine', + ); + check( + hasAll(skill, [ + /Feynman-style self-explanation/i, + /(?:hidden|undefined).{0,20}(?:term|concept)/is, + /(?:leap|failed application|cannot apply)/i, + /source|worked case/i, + /fluenc\w*.{0,45}(?:diagnostic|signal|possible gap)/is, + /(?:modern|packaged).{0,35}Feynman Technique/is, + ]), + 'Feynman-style explanation diagnoses and repairs a concrete gap without relying on fluency', + ); + check( + hasAll(skill, [ + /Cargo Cult Science integrity/i, + /consequential/i, + /contrary|counterevidence/i, + /alternative/i, + /uncertain/i, + /(?:change|revise|update).{0,35}(?:conclusion|claim|view)/is, + /(?:material|relevant).{0,35}(?:disclos|caveat|information)/is, + /(?:not|never).{0,70}(?:mandatory|fixed|required|ritual)/is, + ]), + 'Integrity disclosure preserves material contrary evidence without becoming a fixed inventory', + ); + check( + hasAll(skill, [ + /Grounded first principles/i, + /observed fact/i, + /definition/i, + /hard constraint/i, + /value choice/i, + /assumption/i, + /convention/i, + /premises?.{0,45}(?:chang|affect|alter).{0,25}conclusion/is, + /(?:revis|chang|update).{0,25}condition|conditions?.{0,25}(?:revis|chang|update)/is, + /(?:stop|end|cease).{0,45}(?:not help|unhelpful|no longer useful)/is, + /(?:knowledge|history).{0,35}\bevidence\b/is, + ]), + 'Grounded first principles types only consequential premises and retains revision and stopping conditions', + ); + check( + hasAll(skill, [ + /Practice-led principal-contradiction analysis/i, + /dominant aspect/i, + /secondary.{0,15}(?:coupl|factor|effect)/is, + /(?:revisable|tentative|provisional).{0,35}(?:hypothesis|prioritization|ranking)/is, + /(?:condition|observation).{0,45}(?:reorder|reprioriti|change the ranking)/is, + /(?:not|never|does not).{0,45}(?:authorize|permit).{0,35}production/is, + /(?:not|never|do not).{0,55}(?:universal|single.cause|doctrine)/is, + ]), + 'Principal-contradiction analysis remains revisable, coupled, practical, and non-doctrinal', + ); + check( + hasAll(skill, [ + /Material history or genealogy/i, + /(?:clarif|explain|illuminate).{0,20}(?:present|current)/is, + /prior arrangement/i, + /emergence|adoption/i, + /discontin|rupture|break/i, + /(?:caus\w*.{0,35}(?:interpret|tentative|label)|(?:interpret|tentative|label).{0,35}caus\w*)/is, + /(?:reject|not|never).{0,55}(?:inevitab|present-purpose|predetermin)/is, + /(?:interacting|multiple|combined).{0,20}causes?/is, + /source|evidence/i, + ]), + 'Material history uses sourced, discontinuous, interacting causality without inevitability', + ); + check( + hasAll(skill, [ + /Reciprocal Socratic questioning/i, + /either participant/i, + /reject.{0,20}premise/is, + /Agent.{0,20}answer|answer.{0,20}Agent/is, + /aporia|unresolved|open question/i, + /questions?.{0,35}(?:yield|give way|stop)/is, + /(?:direct|plain).{0,20}(?:explanation|answer)|admit.{0,15}uncertainty/is, + ]), + 'Socratic questioning is reciprocal, answerable, and yields instead of manufacturing assent', + ); + check( + hasAll(skill, [ + /Minimal structural box-drawing/i, + /(?:few|small number of).{0,35}(?:boxes|elements)/is, + /abstraction level/i, + /structural inference.{0,35}(?:cheaper|easier|clearer).{0,20}prose/is, + /(?:check|compare).{0,70}(?:sources|code|examples|participants' model)/is, + /(?:revise|discard).{0,45}(?:not help|unhelpful|fails)/is, + ]), + 'Box-drawing serves one checked inference and is discarded when unhelpful', + ); + check( + hasAll(skill, [ + /(?:correct|counter|check|friction)/i, + /hard constraints?.{0,50}history/is, + /questions?.{0,50}(?:answer|reciprocal)/is, + /diagrams?.{0,50}(?:prose|source|practice)/is, + ]), + 'Learn Skill keeps cross-lens corrective friction visible without mandatory pairings', + ); + check( + hasAll(skill, [ + /(?:do not|never|must not)\s+introduce/i, + /entry command/i, + /fixed encounter stages|stage sequence/i, + /required\s+transcript|transcript requirement/i, + /transcript or summary|summary requirement|mandatory summary/i, + /mandatory headings/i, + /\bscore\b/i, + /\bmetric\b/i, + /completion gate/i, + /approval ceremony/i, + /per-edit human approval/i, + /parsed body schema/i, + /second task system/i, + ]), + 'Learn Skill rejects protocol, schema, assessment, and approval machinery', + ); + for (const behavior of prohibitedSkillBehaviors) { + check( + !detectsProhibitedBehavior(skill, behavior), + `Learn Skill contains no contradictory ${behavior.key} claim`, + ); + } + assertContradictoryRegressionFixtures(check); +} + +export function runLearnTests(check: LearnCheck): void { + console.log('--- Learn distribution and contract'); + + const expectedFiles = [...learnFiles].sort(); + check( + JSON.stringify(filesBelow(path.join(sourceRoot, 'templates', '.omp-flow', 'learn'))) === JSON.stringify(expectedFiles), + 'canonical Learn skeleton contains exactly four indexes', + ); + const canonicalSkill = read(sourceRoot, 'templates/common/skills/omp-flow-learn/SKILL.md'); + for (const destination of skillDestinations) { + check(canonicalSkill === read(sourceRoot, destination), `${destination} is byte-identical to the canonical Learn Skill`); + } + for (const harness of ['codex', 'snow', 'cursor'] as const) { + check(!fs.existsSync(path.join(sourceRoot, `.${harness}`, 'skills')), `tracked project has no ${harness}-specific Skill tree`); + } + + const managed = getManagedResources(['omp', 'codex', 'claude', 'snow', 'cursor']); + for (const relativePath of learnFiles) { + const destination = `.omp-flow/learn/${relativePath}`; + const matches = managed.filter(resource => resource.destinationPath.split(path.sep).join('/') === destination); + check(matches.length === 1 && matches[0]?.group === 'core', `${destination} is registered once as a core resource`); + } + for (const destination of skillDestinations) { + const matches = managed.filter(resource => resource.destinationPath.split(path.sep).join('/') === destination); + check(matches.length === 1, `${destination} is registered once through normal Skill mapping`); + } + check( + managed.every(resource => !/[\\/](?:\.codex|\.snow|\.cursor)[\\/]skills[\\/]omp-flow-learn/.test(path.join(path.sep, resource.destinationPath))), + 'managed resources contain no Codex, Snow, or Cursor Learn Skill duplicate', + ); + + const installedRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'omp-flow-learn-test-')); + try { + deployInitResources({ cwd: installedRoot, harnesses: ['omp', 'codex', 'claude', 'snow', 'cursor'] }); + check( + JSON.stringify(filesBelow(path.join(installedRoot, '.omp-flow', 'learn'))) === JSON.stringify(expectedFiles), + 'fresh install receives exactly the four-file Learn skeleton', + ); + for (const relativePath of learnFiles) { + check( + read(sourceRoot, `templates/.omp-flow/learn/${relativePath}`) === read(installedRoot, `.omp-flow/learn/${relativePath}`), + `fresh ${relativePath} is byte-identical to canonical`, + ); + } + for (const destination of skillDestinations) { + check(canonicalSkill === read(installedRoot, destination), `fresh ${destination} is byte-identical to canonical`); + } + for (const harness of ['codex', 'snow', 'cursor'] as const) { + check(!fs.existsSync(path.join(installedRoot, `.${harness}`, 'skills')), `fresh install has no ${harness}-specific Skill tree`); + } + } finally { + fs.rmSync(installedRoot, { recursive: true, force: true }); + } + + assertIndexContract(check); + assertSkillContract(canonicalSkill, check); +} diff --git a/tests/omp-flow.test.ts b/tests/omp-flow.test.ts index 5ac88f9b..bc3ff8a1 100644 --- a/tests/omp-flow.test.ts +++ b/tests/omp-flow.test.ts @@ -14,6 +14,7 @@ import { runFlowStatusV2PublisherTests } from './flow-status-v2-publisher.test.j import { runFlowStatusV2SupervisorTests } from './flow-status-v2-supervisor.test.js'; import { runCodexInitTests } from './codex-init.test.js'; import { runInitCLITests } from './init-cli.test.js'; +import { runLearnTests } from './learn.test.js'; import { runOMPFlowStatusTests } from './omp-flow-status.test.js'; import { runSnowCursorManagedResourceTests } from './snow-cursor-managed-resources.test.js'; @@ -25,20 +26,35 @@ function check(condition: unknown, message: string): asserts condition { checks += 1; } -function run(root: string, args: string[], context = 'test-session'): string { +function run(root: string, args: string[], context: string | null = 'test-session'): string { + const env = { ...process.env }; + if (context === null) { + for (const key of [ + 'OMP_FLOW_CONTEXT_ID', + 'OMP_SESSION_ID', + 'PI_SESSION_ID', + 'CODEX_THREAD_ID', + 'CODEX_SESSION_ID', + 'SNOW_SESSION_ID', + ]) { + delete env[key]; + } + } else { + env.OMP_FLOW_CONTEXT_ID = context; + } return execFileSync( python, ['-X', 'utf8', path.join(root, '.omp-flow', 'scripts', 'omp_flow.py'), '--cwd', root, ...args], { cwd: root, encoding: 'utf8', - env: { ...process.env, OMP_FLOW_CONTEXT_ID: context }, + env, stdio: ['ignore', 'pipe', 'pipe'], }, ).trim(); } -function json(root: string, args: string[], context = 'test-session'): T { +function json(root: string, args: string[], context: string | null = 'test-session'): T { return JSON.parse(run(root, args, context)) as T; } @@ -83,6 +99,35 @@ interface Started { assignment: string; } +interface SleepSource { + ready: boolean; + receipt: string; + sourceCommit: string; + sourceTree: string; + archivedPath: string; + reason?: string; +} + +interface ArchivedTask { + archivedTo: string; + sleepSource: SleepSource; +} + +interface SleepRun { + receipt: string; + actorId: string; + state: string; + runOutput: string; + candidateRoot: string; + candidates: string[]; + assignment?: string; +} + +interface StartedSleep { + run: SleepRun; + assignment: string; +} + const sourceRoot = process.cwd(); const root = fs.mkdtempSync(path.join(os.tmpdir(), 'omp-flow-okf-')); try { @@ -113,8 +158,14 @@ try { check(!supportsBannerColor({ NO_COLOR: '' }, true), 'NO_COLOR disables banner color'); check(supportsBannerColor({ FORCE_COLOR: '1' }, false), 'FORCE_COLOR enables banner color'); await runInitCLITests(check); + runLearnTests(check); await runSnowCursorManagedResourceTests(check); runCodexInitTests(check); + execFileSync(python, ['-X', 'utf8', path.join(sourceRoot, 'tests', 'wiki-sleep.test.py')], { + cwd: sourceRoot, + encoding: 'utf8', + stdio: 'inherit', + }); execFileSync(python, ['-X', 'utf8', path.join(sourceRoot, 'tests', 'codex-hooks.test.py')], { cwd: sourceRoot, encoding: 'utf8', @@ -139,47 +190,33 @@ try { check(fs.statSync(path.join(root, resource.destinationPath)).isFile(), `deployed ${resource.destinationPath}`); } - console.log('--- practice-led methodology distribution'); - const pairedContracts = [ - ['Workflow', ['templates', '.omp-flow', 'workflow.md'], ['.omp-flow', 'workflow.md']], - ['OMP orchestrator', ['templates', 'omp', 'agents', 'orchestrator.md'], ['.omp', 'agents', 'orchestrator.md']], - ['OMP research', ['templates', 'omp', 'agents', 'researcher.md'], ['.omp', 'agents', 'researcher.md']], - ['OMP QbD', ['templates', 'omp', 'agents', 'qbd-auditor.md'], ['.omp', 'agents', 'qbd-auditor.md']], - ['Codex research', ['templates', 'codex', 'agents', 'omp-flow-research.toml'], ['.codex', 'agents', 'omp-flow-research.toml']], - ['Codex QbD', ['templates', 'codex', 'agents', 'omp-flow-qbd.toml'], ['.codex', 'agents', 'omp-flow-qbd.toml']], - ['Claude research', ['templates', 'claude', 'agents', 'omp-flow-research.md'], ['.claude', 'agents', 'omp-flow-research.md']], - ['Claude QbD', ['templates', 'claude', 'agents', 'omp-flow-qbd.md'], ['.claude', 'agents', 'omp-flow-qbd.md']], - ] as const; - const contractText = new Map(); - for (const [name, canonicalParts, deployedParts] of pairedContracts) { - const canonical = fs.readFileSync(path.join(sourceRoot, ...canonicalParts), 'utf8'); - contractText.set(name, canonical); - // Repository-root .omp-flow is private ignored state; Harness deployments remain tracked. - if (deployedParts[0] !== '.omp-flow') { - check( - fs.readFileSync(path.join(sourceRoot, ...deployedParts), 'utf8') === canonical, - `${name} canonical and repository deployment are byte-identical`, - ); - } - check( - fs.readFileSync(path.join(root, ...deployedParts), 'utf8') === canonical, - `${name} temporary installation is byte-identical`, - ); - } + console.log('--- shared responsibility and native delegation contracts'); + const workflowContract = fs.readFileSync( + path.join(sourceRoot, 'templates', '.omp-flow', 'workflow.md'), + 'utf8', + ); + check( + fs.readFileSync(path.join(root, '.omp-flow', 'workflow.md'), 'utf8') === workflowContract, + 'Workflow temporary installation is byte-identical', + ); - const methodologySkills = [ + const sharedSkillNames = [ 'omp-flow', 'omp-flow-brainstorm', 'omp-flow-research', + 'omp-flow-design', 'omp-flow-qbd', - ]; - const methodologySkillText = new Map(); - for (const skill of methodologySkills) { + 'omp-flow-decompose', + 'omp-flow-implement', + 'omp-flow-check', + ] as const; + const sharedSkillText: Record = {}; + for (const skill of sharedSkillNames) { const canonical = fs.readFileSync( path.join(sourceRoot, 'templates', 'common', 'skills', skill, 'SKILL.md'), 'utf8', ); - methodologySkillText.set(skill, canonical); + sharedSkillText[skill] = canonical; for (const harnessRoot of ['.agents', '.omp', '.claude']) { check( fs.readFileSync(path.join(sourceRoot, harnessRoot, 'skills', skill, 'SKILL.md'), 'utf8') === canonical, @@ -192,71 +229,429 @@ try { } } - const workflowContract = contractText.get('Workflow')!; - check( - ['第一性锚定', '主要矛盾', '实践检验', '反形式主义'] - .every(term => workflowContract.includes(term)), - 'Workflow retains the concise first-principles and practice-led methodology names', - ); - check( - ['human before Agent challenge', 'strongest counter-case', 'safe degradation', 'human-calibrated, scoped'] - .every(anchor => workflowContract.includes(anchor)), - 'Workflow connects methodology names to human ownership, counter-case, degradation, and scoped re-audit', - ); + const responsibilityContracts = [ + { + name: 'Workflow', + text: workflowContract, + anchors: ['provisional first-principles anchor(第一性锚定)'], + responsibilities: ['concrete problem, irreducible outcome', 'evidence that would revise it'], + }, + { + name: 'Router', + text: sharedSkillText['omp-flow'], + anchors: ['principal contradiction(主要矛盾)'], + responsibilities: ['preserve the current concrete decision', 'do not pre-commit a hypothetical mechanism'], + }, + { + name: 'Brainstorm', + text: sharedSkillText['omp-flow-brainstorm'], + anchors: ['first-principles anchor(第一性锚定)', 'principal contradiction(主要矛盾)'], + responsibilities: ['concrete actors and action', 'evidence that would revise the framing'], + }, + { + name: 'Research', + text: sharedSkillText['omp-flow-research'], + anchors: ['principal contradiction'], + responsibilities: [ + 'test the framing against practice', + 'distinguish what evidence proves, does not prove, and merely makes possible', + 'Brainstorm-return signal', + ], + }, + { + name: 'Design', + text: sharedSkillText['omp-flow-design'], + anchors: ['evidenced principal contradiction'], + responsibilities: [ + 'concrete causal purpose in plain language', + 'assigned PRD/Design/decision/interface outputs', + ], + }, + { + name: 'QbD', + text: sharedSkillText['omp-flow-qbd'], + anchors: ['current principal contradiction'], + responsibilities: [ + 'reconstruct the concrete problem without solution jargon', + 'preserve the mechanical safety analysis', + 'assigned audit Concept', + ], + }, + { + name: 'Decompose', + text: sharedSkillText['omp-flow-decompose'], + anchors: ['linked human QbD 1 approval'], + responsibilities: [ + 'bounded, independently reviewable work Concepts', + 'authored prose execution view', + ], + }, + { + name: 'Implement', + text: sharedSkillText['omp-flow-implement'], + anchors: ['return the approved Design to practice'], + responsibilities: ['code, execution, and real verification', 'Design-return signal', 'assigned handoff'], + }, + { + name: 'Check', + text: sharedSkillText['omp-flow-check'], + anchors: ['principal-problem framing'], + responsibilities: ['intended work/Design consequence', 'practice result', 'assigned Review Concept'], + }, + ]; + const normalizeContract = (text: string): string => text.replace(/\s+/g, ' ').trim(); + const hasResponsibilityCoupling = ( + text: string, + anchors: string[], + responsibilities: string[], + ): boolean => { + const normalized = normalizeContract(text); + return anchors.every(anchor => normalized.includes(anchor)) + && responsibilities.every(responsibility => normalized.includes(responsibility)); + }; + for (const { name, text, anchors, responsibilities } of responsibilityContracts) { + check( + hasResponsibilityCoupling(text, anchors, responsibilities), + `${name} couples its named anchors to the responsibility that owns them`, + ); + const withoutResponsibilities = responsibilities.reduce( + (mutant, responsibility) => mutant.replaceAll(responsibility, ''), + normalizeContract(text), + ); + check( + !hasResponsibilityCoupling(withoutResponsibilities, anchors, responsibilities), + `${name} contract rejects a bare philosophy vocabulary list`, + ); + const withoutAnchors = anchors.reduce( + (mutant, anchor) => mutant.replaceAll(anchor, ''), + normalizeContract(text), + ); + check( + !hasResponsibilityCoupling(withoutAnchors, anchors, responsibilities), + `${name} contract rejects responsibility prose with its required anchor erased`, + ); + } - const routerContract = methodologySkillText.get('omp-flow')!; - const brainstormContract = methodologySkillText.get('omp-flow-brainstorm')!; - const researchContract = methodologySkillText.get('omp-flow-research')!; - const qbdContract = methodologySkillText.get('omp-flow-qbd')!; - check( - ['human calibration', 'targeted human-first Grill', 'safe degradation', 'scoped challenge'] - .every(anchor => routerContract.includes(anchor)), - 'Router requires human calibration and bounded Grill/re-audit routing', - ); - check( - ['the human states a position', 'strongest counter-case', 'a falsifier', 'shared understanding'] - .every(anchor => brainstormContract.includes(anchor)), - 'Brainstorm protects human-first values and recommendation counter-case/falsifier behavior', - ); - check( - ['strongest evidence against', 'confirms, revises, or falsifies', 'practical decision changes'] - .every(anchor => researchContract.includes(anchor)), - 'Research must challenge and report anchor revision plus decision impact', - ); - check( - ['cause -> concrete consequence -> affected', 'decision, give the smallest remedy', 'safe degradation', - 'Only the user', 'decides calibration', - 'targeted human-first Grill', 'scoped challenge'] - .every(anchor => qbdContract.includes(anchor)), - 'QbD requires material consequences, safe degradation, human calibration, and scoped re-audit', - ); + const dualContextContracts = [ + { + name: 'Research', + skill: 'omp-flow-research', + positive: [ + 'complete bounded Research responsibility and assigned output', + 'test the framing against practice', + 'Brainstorm-return signal', + ], + }, + { + name: 'Design', + skill: 'omp-flow-design', + positive: [ + 'complete bounded Design responsibility and assigned PRD/Design/decision/interface outputs', + 'concrete causal purpose in plain language', + ], + }, + { + name: 'QbD', + skill: 'omp-flow-qbd', + positive: [ + 'complete bounded independent audit and assigned audit Concept', + 'report the required verdict, findings, evidence, and contradictions through that output boundary', + ], + }, + { + name: 'Decompose', + skill: 'omp-flow-decompose', + positive: [ + 'complete bounded Decompose responsibility and assigned work outputs', + 'bounded, independently reviewable work Concepts and an authored prose execution view', + ], + }, + { + name: 'Implement', + skill: 'omp-flow-implement', + positive: [ + 'complete bounded implementation and assigned handoff', + 'Design-return signal', + ], + }, + { + name: 'Check', + skill: 'omp-flow-check', + positive: [ + 'complete bounded independent Review and assigned Review Concept', + 'principal-problem framing through that output', + ], + }, + ]; + for (const { name, skill, positive } of dualContextContracts) { + const contract = normalizeContract(sharedSkillText[skill]); + const authorityBoundary = contract.toLowerCase(); + check( + [ + 'only main/coordinator may dispatch', + 'correlate operations/receipts', + 'obtain or record human calibration', + 'choose a workflow transition', + 'inapplicable to an already-dispatched', + 'must not dispatch or self-redispatch', + 'govern', + 'calibrate', + 'transition', + ].every(anchor => authorityBoundary.includes(anchor)), + `${name} denies coordinator authority and self-redispatch to its already-dispatched leaf`, + ); + check( + positive.every(anchor => contract.includes(anchor)), + `${name} retains its positive bounded leaf duty and assigned output or return signal`, + ); + } + + const nativeCardContracts = [ + { + name: 'OMP Router', + harness: 'omp', + canonical: ['templates', 'omp', 'agents', 'orchestrator.md'], + deployed: ['.omp', 'agents', 'orchestrator.md'], + skills: ['.agents/skills/omp-flow/SKILL.md'], + output: '', + }, + { + name: 'OMP Research', + harness: 'omp', + canonical: ['templates', 'omp', 'agents', 'researcher.md'], + deployed: ['.omp', 'agents', 'researcher.md'], + skills: ['.agents/skills/omp-flow-research/SKILL.md'], + output: 'assigned output', + }, + { + name: 'OMP Architect', + harness: 'omp', + canonical: ['templates', 'omp', 'agents', 'architect.md'], + deployed: ['.omp', 'agents', 'architect.md'], + skills: [ + '.agents/skills/omp-flow-design/SKILL.md', + '.agents/skills/omp-flow-decompose/SKILL.md', + ], + output: 'assigned output', + }, + { + name: 'OMP QbD', + harness: 'omp', + canonical: ['templates', 'omp', 'agents', 'qbd-auditor.md'], + deployed: ['.omp', 'agents', 'qbd-auditor.md'], + skills: ['.agents/skills/omp-flow-qbd/SKILL.md'], + output: 'assigned audit output', + }, + { + name: 'OMP Implement', + harness: 'omp', + canonical: ['templates', 'omp', 'agents', 'executor.md'], + deployed: ['.omp', 'agents', 'executor.md'], + skills: ['.agents/skills/omp-flow-implement/SKILL.md'], + output: 'assigned handoff', + }, + { + name: 'OMP Check', + harness: 'omp', + canonical: ['templates', 'omp', 'agents', 'reviewer.md'], + deployed: ['.omp', 'agents', 'reviewer.md'], + skills: ['.agents/skills/omp-flow-check/SKILL.md'], + output: 'assigned Review Concept', + }, + ...[ + ['Research', 'omp-flow-research.toml', '.agents/skills/omp-flow-research/SKILL.md', 'assigned output'], + ['QbD', 'omp-flow-qbd.toml', '.agents/skills/omp-flow-qbd/SKILL.md', 'assigned audit output'], + ['Implement', 'omp-flow-implement.toml', '.agents/skills/omp-flow-implement/SKILL.md', 'assigned handoff'], + ['Check', 'omp-flow-check.toml', '.agents/skills/omp-flow-check/SKILL.md', 'assigned Review Concept'], + ].map(([role, file, skill, output]) => ({ + name: `Codex ${role}`, + harness: 'codex', + canonical: ['templates', 'codex', 'agents', file], + deployed: ['.codex', 'agents', file], + skills: [skill], + output, + })), + { + name: 'Codex Architect', + harness: 'codex', + canonical: ['templates', 'codex', 'agents', 'omp-flow-architect.toml'], + deployed: ['.codex', 'agents', 'omp-flow-architect.toml'], + skills: [ + '.agents/skills/omp-flow-design/SKILL.md', + '.agents/skills/omp-flow-decompose/SKILL.md', + ], + output: 'assigned output', + }, + ...[ + ['Research', 'omp-flow-research.md', '.agents/skills/omp-flow-research/SKILL.md', 'assigned output'], + ['QbD', 'omp-flow-qbd.md', '.agents/skills/omp-flow-qbd/SKILL.md', 'assigned audit output'], + ['Implement', 'omp-flow-implement.md', '.agents/skills/omp-flow-implement/SKILL.md', 'assigned handoff'], + ['Check', 'omp-flow-check.md', '.agents/skills/omp-flow-check/SKILL.md', 'assigned Review Concept'], + ].map(([role, file, skill, output]) => ({ + name: `Claude ${role}`, + harness: 'claude', + canonical: ['templates', 'claude', 'agents', file], + deployed: ['.claude', 'agents', file], + skills: [skill], + output, + })), + { + name: 'Claude Architect', + harness: 'claude', + canonical: ['templates', 'claude', 'agents', 'omp-flow-architect.md'], + deployed: ['.claude', 'agents', 'omp-flow-architect.md'], + skills: [ + '.agents/skills/omp-flow-design/SKILL.md', + '.agents/skills/omp-flow-decompose/SKILL.md', + ], + output: 'assigned output', + }, + ]; + const nativeCardText: Record = {}; + for (const card of nativeCardContracts) { + const canonical = fs.readFileSync(path.join(sourceRoot, ...card.canonical), 'utf8'); + const deployed = fs.readFileSync(path.join(sourceRoot, ...card.deployed), 'utf8'); + nativeCardText[card.name] = canonical; + check(canonical === deployed, `${card.name} canonical and repository deployment are byte-identical`); + check( + fs.readFileSync(path.join(root, ...card.deployed), 'utf8') === canonical, + `${card.name} temporary installation is byte-identical`, + ); + const loadedSkills = [...new Set( + canonical.match(/\.agents\/skills\/omp-flow(?:-[a-z]+)?\/SKILL\.md/g) ?? [], + )].sort(); + check( + JSON.stringify(loadedSkills) === JSON.stringify([...card.skills].sort()), + `${card.name} delegates through only its exact universal Skill path`, + ); + check( + card.skills.every(skill => normalizeContract(canonical).includes(`read \`${skill}\` completely and follow it`)), + `${card.name} explicitly loads every selected universal Skill`, + ); + if (card.output) { + const normalized = normalizeContract(canonical); + check( + [ + 'already dispatched', + 'cannot redispatch yourself', + 'calibrate human decisions', + 'transition the workflow', + 'exercise coordinator governance', + 'supplies the positive bounded', + card.output, + ].every(anchor => normalized.includes(anchor)), + `${card.name} keeps the leaf no-authority boundary and delegates its positive bounded output`, + ); + } + } + + for (const name of ['OMP Architect', 'Codex Architect', 'Claude Architect']) { + const architect = normalizeContract(nativeCardText[name]); + check( + [ + 'Select exactly one Skill from the bounded assignment before role work', + 'For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it', + 'For approved work mapping only after linked human QbD 1 approval, read `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it', + 'Stop if the assignment does not establish exactly one branch', + 'work mapping lacks the linked human approval', + ].every(anchor => architect.includes(anchor)), + `${name} selects exactly one Design-or-approved-Decompose branch and otherwise stops`, + ); + } - const orchestratorContract = contractText.get('OMP orchestrator')!; + const ompRouter = normalizeContract(nativeCardText['OMP Router']); check( - ['实践论 / 实事求是', 'confirm, revise, or falsify', 'linked human calibration', - 'Do not automatically order a fresh audit'] - .every(anchor => orchestratorContract.includes(anchor)), - 'OMP orchestrator keeps short methodology anchors tied to revisable research and human calibration', + [ + 'native Main orchestrator selected by this Harness', + 'Use native `task`', + '`operation start` is the sole producer', + 'strict v1 `ompFlowDispatch` JSON as the first non-blank line', + '`id` to the returned operation', + 'same actor ID', + 'Do not edit runtime/session operation records', + 'hard blocker', + ].every(anchor => ompRouter.includes(anchor)), + 'OMP Router preserves native task, strict descriptor/actor/receipt/output, and fail-closed mechanics', ); - for (const name of ['OMP research', 'Codex research', 'Claude research']) { - const agent = contractText.get(name)!; + for (const card of nativeCardContracts.filter(card => card.harness === 'omp' && card.output)) { + const contract = normalizeContract(nativeCardText[card.name]); check( - ['第一性锚定 / 主要矛盾', 'strongest counter-evidence', 'confirms, revises, or falsifies', - "human's value/risk ordering"] - .every(anchor => agent.includes(anchor)), - `${name} implements equivalent practice-led research behavior`, + contract.includes('tools:') + && contract.includes('Do not spawn') + && contract.includes('Require the task Bundle root') + && contract.includes('actor ID') + && contract.includes('receipt') + && /Missing [^.]+(?:hard )?blocker/.test(contract), + `${card.name} preserves tools, no-subagent, strict assignment/receipt/output, and fail-closed guards`, ); } - for (const name of ['OMP QbD', 'Codex QbD', 'Claude QbD']) { - const agent = contractText.get(name)!; + for (const card of nativeCardContracts.filter(card => card.harness === 'codex')) { + const contract = normalizeContract(nativeCardText[card.name]); check( - ['decision-critical', 'consequence', 'safe degradation', 'exact next decision/options', - 'human', 'calibration', 'accepted risk'] - .every(anchor => agent.includes(anchor)), - `${name} implements equivalent material QbD and human-governance behavior`, + contract.includes('sandbox_mode = "workspace-write"') + && contract.includes('Do not spawn') + && contract.includes('actorId') + && contract.includes('receipt') + && contract.includes('multi_agent = false') + && contract.includes('enabled = false') + && /Missing [^.]+(?:hard )?blocker/.test(contract), + `${card.name} preserves native identity, strict boundaries, multi-agent disablement, and fail-closed guards`, + ); + } + for (const card of nativeCardContracts.filter(card => card.harness === 'claude')) { + const contract = normalizeContract(nativeCardText[card.name]); + check( + [ + 'tools:', + 'no `Agent` or `Task` tool', + 'first non-blank assignment line', + '{"ompFlowDispatch":{...}}', + '`bundle`', + '`entry`', + '`output`', + '`actorId`', + '`receipt`', + '`predecessor`', + '', + 'non-empty native `agentId`', + '', + 'TaskUpdate` object unchanged', + 'same immutable `flowStatusBindingV1` plus one closed `flowStatusProgressV1`', + 'never set status, owner again, dependencies, subject, description, or another Task', + 'write and progress boundaries', + 'fail-closed requirements remain authoritative', + ].every(anchor => contract.includes(anchor)), + `${card.name} preserves startup, binding, progress, tool/write, descriptor, and fail-closed guards`, ); } + const thinNativeCards = Object.values(nativeCardText).join('\n'); + check( + [ + /第一性锚定/, + /主要矛盾/, + /实践论/, + /实事求是/, + /Feynman|费曼/i, + /strongest counter-evidence/i, + /confirms?, revises?, or falsifies/i, + /^#{1,2} (?:Workflow|Design Work|Work Mapping|Design and Work Mapping)$/m, + ].every(pattern => !pattern.test(thinNativeCards)), + 'native cards contain no copied methodology or duplicated role-method sections', + ); + check( + [ + /\.omp\/skills\/|\.claude\/skills\//, + /reader.?context|methodologyState|dialecticalState/i, + /(?:methodology|dialectic|anchor|contradiction|evidence).{0,40}(?:descriptor|runtime state|state field)/i, + /methodology parser|parse (?:the )?(?:methodology|anchor|contradiction)/i, + /required (?:methodology )?(?:heading|checklist)/i, + /prompt snapshot/i, + /model (?:understands|comprehends)|cogniti(?:on|ve) guarantee/i, + ].every(pattern => !pattern.test(thinNativeCards)), + 'native cards add no second Skill tree, methodology state/parser/checklist, prompt snapshot, or cognition guarantee', + ); + const retiredPromptSemantics = [ /missing or contradictory required evidence[^\n]*NEEDS_EVIDENCE[^\n]*never PASS/i, /FAIL,\s*NEEDS_EVIDENCE,\s*or human reject[^\n]*repair[^\n]*fresh independent audit/i, @@ -264,11 +659,8 @@ try { ]; const affectedPrompts = [ workflowContract, - routerContract, - brainstormContract, - researchContract, - qbdContract, - ...contractText.values(), + ...Object.values(sharedSkillText), + ...Object.values(nativeCardText), ].join('\n'); check( retiredPromptSemantics.every(pattern => !pattern.test(affectedPrompts)), @@ -288,6 +680,7 @@ try { 'io.py', 'operation_store.py', 'paths.py', + 'sleep_store.py', 'task_store.py', ]), `runtime kernel is minimal: ${deployedCore.join(', ')}`, @@ -454,7 +847,7 @@ try { && claudeSettings.hooks.PostToolUse[0].hooks[0].command.includes('flow-status-observe.py'), 'Claude observes structured task and correlated attention results for Flow Status', ); - for (const skill of ['omp-flow-debug', 'omp-flow-ui-designer', 'omp-flow-wiki']) { + for (const skill of ['omp-flow-debug', 'omp-flow-ui-designer', 'omp-flow-wiki', 'omp-flow-sleep']) { const canonical = fs.readFileSync( path.join(sourceRoot, 'templates', 'common', 'skills', skill, 'SKILL.md'), 'utf8', @@ -471,7 +864,19 @@ try { `${skill} deploys identically to ${harnessRoot}`, ); } - if (skill !== 'omp-flow-wiki') { + if (skill === 'omp-flow-sleep') { + check( + ['ompFlowSleep', 'sourceReceipt', 'sourceTree', 'runOutput', 'candidateRoot', 'harvesterRevision'] + .every(required => canonical.includes(required)), + 'Sleep Skill requires the runtime-produced archived-source descriptor', + ); + check( + canonical.includes('Zero `--candidate` arguments is valid') + && canonical.includes('Do not use embedding') + && canonical.includes('not Wiki authority'), + 'Sleep Skill preserves zero-output, semantic-OKF, and promotion boundaries', + ); + } else if (skill !== 'omp-flow-wiki') { check( ['Bundle root', 'entry Concept', 'output boundary', 'operation receipt'] .every(required => canonical.includes(required)), @@ -484,6 +889,47 @@ try { ); } } + const finishCanonical = fs.readFileSync( + path.join(sourceRoot, 'templates', 'common', 'skills', 'omp-flow-finish', 'SKILL.md'), + ); + const finishText = finishCanonical.toString('utf8').replace(/\s+/g, ' '); + check( + [ + 'Normal `sleep start` delivery is primary', + 'capturing the complete', + 'through successful process completion', + 'parsing all', + 'requiring string `run.assignment`', + 'sole native assignment input', + 'including its trailing LF', + 'diagnostic only', + 'never copy or parse it', + 'prefix or suffix', + 'reconstruct or reserialize', + 'fall back to `sleep list`', + 'duplicate `sleep start`', + 'nonzero exit', + 'incomplete capture', + 'invalid JSON', + 'missing or', + 'stop before native dispatch', + ].every(required => finishText.includes(required)), + 'Finish Skill specifies complete programmatic show recovery and fail-closed native forwarding', + ); + for (const harnessRoot of ['.agents', '.omp', '.claude']) { + check( + fs.readFileSync( + path.join(sourceRoot, harnessRoot, 'skills', 'omp-flow-finish', 'SKILL.md'), + ).equals(finishCanonical), + `omp-flow-finish is synchronized to ${harnessRoot}`, + ); + check( + fs.readFileSync( + path.join(root, harnessRoot, 'skills', 'omp-flow-finish', 'SKILL.md'), + ).equals(finishCanonical), + `omp-flow-finish deploys identically to ${harnessRoot}`, + ); + } console.log('--- Bundle scaffold and Explore spiral'); const created = json(root, ['task', 'create', 'Semantic dogfood', '--slug', 'semantic-dogfood']); @@ -817,7 +1263,15 @@ try { { cwd: root, encoding: 'utf8' }, ); check(ignored.includes('.runtime') && ignored.includes('cache/repos'), 'runtime and clone cache are ignored'); - const archive = json<{ archivedTo: string }>(root, ['task', 'archive']); + execFileSync('git', ['config', 'user.name', 'OMP Flow Test'], { cwd: root }); + execFileSync('git', ['config', 'user.email', 'omp-flow-test@example.invalid'], { cwd: root }); + execFileSync('git', ['add', '-A'], { cwd: root }); + execFileSync('git', ['commit', '-qm', 'test: checkpoint task before archive'], { cwd: root }); + const archive = json(root, ['task', 'archive', created.taskId], null); + check( + json<{ active: null }>(root, ['status'], null).active === null, + 'explicit archive does not require a Harness session selection', + ); const archivedRoot = path.join(root, archive.archivedTo); check(fs.statSync(archivedRoot).isDirectory(), 'archive relocates the whole Bundle'); check( @@ -831,6 +1285,223 @@ try { }); check(archivedStatus.trim().length > 0, 'archive relocation remains Git-visible'); + console.log('--- skill-driven Wiki Sleep'); + check( + archive.sleepSource.ready + && archive.sleepSource.archivedPath === archive.archivedTo + && archive.sleepSource.sourceCommit.length === 40 + && archive.sleepSource.sourceTree.length === 40, + 'archive returns a reproducible archived-source receipt', + ); + check( + fs.existsSync(path.join(root, '.omp-flow', '.runtime', 'sleep', 'sources', `${archive.sleepSource.receipt}.json`)), + 'archive persists the opaque Sleep source under ignored runtime', + ); + const sleepShowHelp = run(root, ['sleep', 'show', '--help']); + check( + sleepShowHelp.replace(/\s+/g, ' ').includes('active revised run contains its recoverable assignment'), + 'installed sleep show help identifies active assignment recovery', + ); + failure(root, ['sleep', 'assignment'], 'invalid choice'); + const sleep = json(root, [ + 'sleep', 'start', + '--source', archive.sleepSource.receipt, + '--actor-id', 'sleep-native-id', + ]); + const sleepFirstLine = sleep.assignment.split(/\r?\n/).find(line => line.trim())!; + const sleepDescriptor = JSON.parse(sleepFirstLine).ompFlowSleep; + check( + sleepDescriptor.version === 1 + && sleepDescriptor.receipt === sleep.run.receipt + && sleepDescriptor.sourceReceipt === archive.sleepSource.receipt + && sleepDescriptor.sourceTask === archive.archivedTo + && sleepDescriptor.actorId === 'sleep-native-id', + 'sleep start emits an exact archived-source assignment independent of the active Task', + ); + check( + fs.readFileSync(path.join(root, '.omp-flow', 'sleep', 'index.md'), 'utf8').includes('# Wiki Sleep') + && fs.statSync(path.join(root, '.omp-flow', 'sleep', 'candidates')).isDirectory(), + 'sleep start bootstraps only the minimal Git-visible Sleep knowledge root', + ); + for (const duplicateActor of ['sleep-native-id', 'another-sleep-actor']) { + failure( + root, + ['sleep', 'start', '--source', archive.sleepSource.receipt, '--actor-id', duplicateActor], + 'Sleep run already exists', + ); + } + check( + sleep.run.state === 'active' + && typeof sleep.run.assignment === 'string' + && sleep.run.assignment === sleep.assignment + && sleep.assignment.endsWith('\n'), + 'sleep start returns one exact stored active assignment including its trailing LF', + ); + const sleepRunFile = path.join( + root, + '.omp-flow', + '.runtime', + 'sleep', + 'runs', + `${sleep.run.receipt}.json`, + ); + const activeRunBytes = fs.readFileSync(sleepRunFile); + const persistedActive = JSON.parse(activeRunBytes.toString('utf8')) as SleepRun; + check( + persistedActive.assignment === sleep.assignment && persistedActive.state === 'active', + 'the installed runtime persists the assignment in the complete active record', + ); + const capturedShow = spawnSync( + python, + [ + '-X', + 'utf8', + path.join(root, '.omp-flow', 'scripts', 'omp_flow.py'), + '--cwd', + root, + 'sleep', + 'show', + sleep.run.receipt, + ], + { + cwd: root, + env: { ...process.env, OMP_FLOW_CONTEXT_ID: 'test-session' }, + }, + ); + check( + capturedShow.status === 0, + `programmatic sleep show capture succeeds: ${capturedShow.stderr.toString('utf8')}`, + ); + const showStdout = capturedShow.stdout; + check(showStdout.at(-1) === 0x0a, 'programmatic sleep show capture reaches the final stdout LF'); + const shownActive = JSON.parse(showStdout.toString('utf8')) as SleepRun; + check( + typeof shownActive.assignment === 'string' + && Buffer.from(shownActive.assignment, 'utf8').equals(Buffer.from(sleep.assignment, 'utf8')), + 'complete show JSON parse and run.assignment extraction recover the exact lost start bytes', + ); + const soleNativeInput = shownActive.assignment; + check( + Buffer.from(soleNativeInput, 'utf8').equals(Buffer.from(sleep.assignment, 'utf8')), + 'the extracted string is unchanged as the sole native assignment input', + ); + const listedActive = json(root, ['sleep', 'list']) + .find(runValue => runValue.receipt === sleep.run.receipt); + check( + listedActive?.assignment === sleep.assignment, + 'sleep list inspects the same stored active representation', + ); + const repeatedShow = json(root, ['sleep', 'show', sleep.run.receipt]); + const repeatedList = json(root, ['sleep', 'list']) + .find(runValue => runValue.receipt === sleep.run.receipt); + check( + JSON.stringify(repeatedShow) === JSON.stringify(shownActive) + && JSON.stringify(repeatedList) === JSON.stringify(listedActive) + && fs.readFileSync(sleepRunFile).equals(activeRunBytes), + 'repeated installed show/list reads preserve bytes, state, timestamps, outputs, and assignment', + ); + failure( + root, + ['sleep', 'finish', sleep.run.receipt, '--state', 'completed', '--actor-id', 'sleep-native-id'], + 'Sleep run receipt output is missing', + ); + check( + fs.readFileSync(sleepRunFile).equals(activeRunBytes), + 'rejected completed finish leaves the recoverable active record unchanged', + ); + writeConcept( + path.join(root, sleep.run.runOutput), + 'Sleep Run', + 'Archived Task knowledge harvest', + `Read [the archived Task](../../../../tasks/archive/${path.basename(path.dirname(archive.archivedTo))}/${created.taskId}/index.md).`, + ); + failure( + root, + [ + 'sleep', 'finish', sleep.run.receipt, + '--state', 'completed', + '--actor-id', 'sleep-native-id', + '--candidate', 'missing.md', + ], + 'Sleep candidate Markdown not found', + ); + check( + fs.readFileSync(sleepRunFile).equals(activeRunBytes), + 'rejected Candidate validation preserves the active assignment', + ); + const candidateRelative = 'exported-symbol-change-safety.md'; + const candidateFile = path.join(root, sleep.run.candidateRoot, candidateRelative); + writeConcept( + candidateFile, + 'Wiki Sleep Candidate', + 'Exported symbol change safety', + `Supported by [the archived Review](../../tasks/archive/${path.basename(path.dirname(archive.archivedTo))}/${created.taskId}/review/first-review.md).`, + ); + const archivedTaskFile = path.join(archivedRoot, 'task.md'); + const archivedTaskText = fs.readFileSync(archivedTaskFile, 'utf8'); + fs.appendFileSync(archivedTaskFile, '\nsource drift\n', 'utf8'); + failure( + root, + [ + 'sleep', 'finish', sleep.run.receipt, + '--state', 'completed', + '--actor-id', 'sleep-native-id', + '--candidate', candidateRelative, + ], + 'Archived Sleep source has drifted', + ); + check( + fs.readFileSync(sleepRunFile).equals(activeRunBytes), + 'rejected source validation preserves the active assignment', + ); + fs.writeFileSync(archivedTaskFile, archivedTaskText, 'utf8'); + const completedSleep = json(root, [ + 'sleep', 'finish', sleep.run.receipt, + '--state', 'completed', + '--actor-id', 'sleep-native-id', + '--candidate', candidateRelative, + ]); + check( + completedSleep.state === 'completed' + && completedSleep.candidates.length === 1 + && completedSleep.candidates[0].endsWith(`/candidates/${candidateRelative}`) + && completedSleep.assignment === undefined, + 'sleep finish accepts a real Run handoff and removes the active assignment', + ); + const shownCompleted = json(root, ['sleep', 'show', sleep.run.receipt]); + const listedCompleted = json(root, ['sleep', 'list']) + .find(runValue => runValue.receipt === sleep.run.receipt); + check( + shownCompleted.assignment === undefined + && listedCompleted?.assignment === undefined + && (JSON.parse(fs.readFileSync(sleepRunFile, 'utf8')) as SleepRun).assignment === undefined, + 'installed show, list, and persisted terminal record expose no assignment', + ); + for (const duplicateActor of ['sleep-native-id', 'another-sleep-actor']) { + failure( + root, + ['sleep', 'start', '--source', archive.sleepSource.receipt, '--actor-id', duplicateActor], + 'Sleep run already exists', + ); + } + failure( + root, + ['sleep', 'finish', sleep.run.receipt, '--state', 'completed', '--actor-id', 'sleep-native-id'], + 'Sleep run is already terminal', + ); + + const uncheckpointed = json(root, [ + 'task', 'create', 'Uncheckpointed Sleep source', '--slug', 'uncheckpointed-sleep-source', + ]); + const uncheckpointedArchive = json(root, ['task', 'archive']); + check( + uncheckpointed.taskId !== created.taskId + && !uncheckpointedArchive.sleepSource.ready + && Boolean(uncheckpointedArchive.sleepSource.reason) + && fs.statSync(path.join(root, uncheckpointedArchive.archivedTo)).isDirectory(), + 'archive succeeds but reports Sleep unavailable when no reproducible Task checkpoint exists', + ); + console.log('--- update and Hook boundary'); const plan = analyzeChanges(root, loadHashes(root)); check(plan.every(item => item.status === 'unchanged'), 'fresh install is unchanged under update analysis'); diff --git a/tests/snow-cursor-managed-resources.test.ts b/tests/snow-cursor-managed-resources.test.ts index 0cbbef79..e52b89ef 100644 --- a/tests/snow-cursor-managed-resources.test.ts +++ b/tests/snow-cursor-managed-resources.test.ts @@ -1,6 +1,8 @@ +import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; +import { fileURLToPath } from 'node:url'; import { deployInitResources, @@ -12,6 +14,7 @@ import { normalizeHarnesses, readHarnessConfig, writeHarnessConfig, + type Harness, } from '../src/cli/harness.js'; import { loadHashes, toPosix } from '../src/cli/template-hash.js'; import { analyzeChanges, interactiveUpdate, type UpdatePlanEntry } from '../src/cli/update.js'; @@ -19,6 +22,185 @@ import { analyzeChanges, interactiveUpdate, type UpdatePlanEntry } from '../src/ type Check = (condition: unknown, message: string) => asserts condition; const sourceRoot = process.cwd(); +type DelegatedRole = 'research' | 'architect' | 'qbd' | 'implement' | 'check'; + +const DELEGATED_ROLES: readonly { + role: DelegatedRole; + skills: readonly string[]; +}[] = [ + { role: 'research', skills: ['.agents/skills/omp-flow-research/SKILL.md'] }, + { + role: 'architect', + skills: [ + '.agents/skills/omp-flow-design/SKILL.md', + '.agents/skills/omp-flow-decompose/SKILL.md', + ], + }, + { role: 'qbd', skills: ['.agents/skills/omp-flow-qbd/SKILL.md'] }, + { role: 'implement', skills: ['.agents/skills/omp-flow-implement/SKILL.md'] }, + { role: 'check', skills: ['.agents/skills/omp-flow-check/SKILL.md'] }, +]; + +const ROLE_CARD_FILES: Record> = { + omp: { + research: 'researcher.md', + architect: 'architect.md', + qbd: 'qbd-auditor.md', + implement: 'executor.md', + check: 'reviewer.md', + }, + codex: { + research: 'omp-flow-research.toml', + architect: 'omp-flow-architect.toml', + qbd: 'omp-flow-qbd.toml', + implement: 'omp-flow-implement.toml', + check: 'omp-flow-check.toml', + }, + claude: { + research: 'omp-flow-research.md', + architect: 'omp-flow-architect.md', + qbd: 'omp-flow-qbd.md', + implement: 'omp-flow-implement.md', + check: 'omp-flow-check.md', + }, + snow: { + research: 'omp-flow-research.md', + architect: 'omp-flow-architect.md', + qbd: 'omp-flow-qbd.md', + implement: 'omp-flow-implement.md', + check: 'omp-flow-check.md', + }, + cursor: { + research: 'omp-flow-research.md', + architect: 'omp-flow-architect.md', + qbd: 'omp-flow-qbd.md', + implement: 'omp-flow-implement.md', + check: 'omp-flow-check.md', + }, +}; + +const COMMON_ARCHITECT_SELECTION = [ + 'For a Design assignment, read `.agents/skills/omp-flow-design/SKILL.md` completely and follow it.', + 'For approved work mapping only after linked human QbD 1 approval, read `.agents/skills/omp-flow-decompose/SKILL.md` completely and follow it.', + 'Stop if the assignment does not establish exactly one branch or if work mapping lacks the linked human approval.', +] as const; + +const ARCHITECT_SELECTION: Record = { + omp: COMMON_ARCHITECT_SELECTION, + codex: COMMON_ARCHITECT_SELECTION, + claude: COMMON_ARCHITECT_SELECTION, + snow: [ + '`.agents/skills/omp-flow-design/SKILL.md` for design or `.agents/skills/omp-flow-decompose/SKILL.md` for work mapping.', + ], + cursor: [ + 'Read `.agents/skills/omp-flow-design/SKILL.md` completely for design work, or `.agents/skills/omp-flow-decompose/SKILL.md` completely for approved work mapping, as named by the bounded assignment.', + ], +}; + + +function assertUniversalSkillDeployment(root: string, label: string, check: Check): void { + const skillRoot = path.join('.agents', 'skills'); + const resources = getManagedResources([]) + .filter(resource => toPosix(resource.destinationPath).startsWith('.agents/skills/')) + .sort((left, right) => left.destinationPath.localeCompare(right.destinationPath)); + const expected = resources + .map(resource => toPosix(path.relative(skillRoot, resource.destinationPath))) + .sort(); + const installed = filesBelow(path.join(root, skillRoot)); + check( + JSON.stringify(installed) === JSON.stringify(expected), + `${label} installs the exact universal .agents Skill set`, + ); + for (const resource of resources) { + const canonical = fs.readFileSync(path.join(sourceRoot, resource.sourcePath), 'utf8'); + const deployed = fs.readFileSync(path.join(root, resource.destinationPath), 'utf8'); + check( + deployed === canonical, + `${label} keeps ${toPosix(resource.destinationPath)} byte-equal to its canonical Skill`, + ); + } +} + +function assertMappedInstallation( + root: string, + harnesses: readonly Harness[], + label: string, + check: Check, +): void { + const resources = getManagedResources(harnesses); + const destinations = resources.map(resource => toPosix(resource.destinationPath)); + check( + new Set(destinations).size === destinations.length, + `${label} has exactly one managed mapping for every destination`, + ); + for (const harness of harnesses) { + check( + resources.some(resource => resource.group === harness), + `${label} includes ${harness} managed resources`, + ); + } + const mismatch = resources.find(resource => { + const sourcePath = path.join(sourceRoot, resource.sourcePath); + const destinationPath = path.join(root, resource.destinationPath); + if (!fs.existsSync(destinationPath)) return true; + const canonical = fs.readFileSync(sourcePath, 'utf8'); + return fs.readFileSync(destinationPath, 'utf8') !== renderManagedResource(sourcePath, canonical); + }); + const mismatchPath = mismatch === undefined ? '' : `: ${toPosix(mismatch.destinationPath)}`; + check( + mismatch === undefined, + `${label} deploys every mapped resource from its canonical content${mismatchPath}`, + ); +} + +function assertHarnessCardContracts(root: string, harness: Harness, label: string, check: Check): void { + for (const { role, skills } of DELEGATED_ROLES) { + const fileName = ROLE_CARD_FILES[harness][role]; + const canonical = fs.readFileSync(path.join(sourceRoot, 'templates', harness, 'agents', fileName), 'utf8'); + const deployed = fs.readFileSync(path.join(root, `.${harness}`, 'agents', fileName), 'utf8'); + check(deployed === canonical, `${label} ${role} card is byte-equal to its canonical template`); + const delegated = deployed.match(/\.agents\/skills\/[a-z0-9-]+\/SKILL\.md/g) ?? []; + check( + JSON.stringify(delegated) === JSON.stringify(skills), + `${label} ${role} card delegates to only its exact matching universal Skill path${role === 'architect' ? 's' : ''}`, + ); + if (role === 'architect') { + const prose = deployed.replace(/\s+/g, ' ').trim(); + for (const anchor of ARCHITECT_SELECTION[harness]) { + check(prose.includes(anchor), `${label} Architect preserves its exact Design/Decompose selection`); + } + } + } +} + +function assertIdentityStops(root: string, harness: 'snow' | 'cursor', label: string, check: Check): void { + const required = harness === 'snow' + ? [ + 'Snow 0.8.24 cannot expose or reserve the unique native execution ID before operation creation', + 'this agent definition ID is not a unique execution ID', + 'strict omp-flow operation dispatch through this Snow card is unavailable: stop without doing the assignment, writing its output, or finishing its receipt', + 'Do not represent this card ID or name as `actorId`', + ] + : [ + "This card does not prove that Cursor's generated native subagent ID was caller-selected as `actorId`", + 'Never create a receipt, infer a predecessor, alias an agent name or generated ID, or rewrite the descriptor after dispatch', + 'If exact native-item correlation is required without a pre-dispatch proof, stop and report the operation path unavailable', + ]; + for (const { role } of DELEGATED_ROLES) { + const fileName = ROLE_CARD_FILES[harness][role]; + const content = fs.readFileSync(path.join(root, `.${harness}`, 'agents', fileName), 'utf8') + .replace(/\s+/g, ' ') + .trim(); + for (const anchor of required) { + check(content.includes(anchor), `${label} ${role} card preserves the ${harness}-specific identity stop`); + } + check( + !/\b(?:is|are|becomes?|made)\s+(?:now\s+)?runnable\b/i.test(content) + && !/\b(?:native identity|actorId)\s+(?:is|has been)\s+(?:proved|reserved|satisfied)\b/i.test(content), + `${label} ${role} card makes no runnable-identity claim`, + ); + } +} function filesBelow(root: string): string[] { if (!fs.existsSync(root)) return []; @@ -95,18 +277,31 @@ export async function runSnowCursorManagedResourceTests(check: Check): Promise toPosix(resource.destinationPath).startsWith('.snow/skills/')), + 'Snow mapping invents no Harness-specific Skill deployment', + ); + check( + !getManagedResources(['cursor']).some(resource => toPosix(resource.destinationPath).startsWith('.cursor/skills/')), + 'Cursor mapping invents no Harness-specific Skill deployment', + ); deployInitResources({ cwd: mixedRoot, harnesses: ['snow'] }); deployInitResources({ cwd: mixedRoot, harnesses: ['cursor'] }); @@ -197,3 +402,15 @@ export async function runSnowCursorManagedResourceTests(check: Check): Promise { + assert(condition, message); + checks += 1; + }; + await runSnowCursorManagedResourceTests(check); + console.log(`PASS: ${checks} Snow/Cursor managed-resource checks`); +} diff --git a/tests/wiki-sleep.test.py b/tests/wiki-sleep.test.py new file mode 100644 index 00000000..6bc55413 --- /dev/null +++ b/tests/wiki-sleep.test.py @@ -0,0 +1,608 @@ +from __future__ import annotations + +from concurrent.futures import ThreadPoolExecutor +import hashlib +import json +import os +from pathlib import Path +import shutil +import subprocess +import sys +import threading +import tempfile +import unittest +from unittest import mock + + +SOURCE_ROOT = Path(__file__).resolve().parents[1] +CLI = SOURCE_ROOT / "templates" / ".omp-flow" / "scripts" / "omp_flow.py" +SLEEP_SKILL = SOURCE_ROOT / "templates" / "common" / "skills" / "omp-flow-sleep" + +sys.path.insert(0, str(SOURCE_ROOT / "templates" / ".omp-flow" / "scripts")) +from common import sleep_store +from common.io import WorkflowError + + +class WikiSleepTests(unittest.TestCase): + def setUp(self) -> None: + self.temporary = tempfile.TemporaryDirectory(prefix="omp-flow-wiki-sleep-") + self.root = Path(self.temporary.name) + shutil.copytree(SOURCE_ROOT / "templates" / ".omp-flow", self.root / ".omp-flow") + shutil.copytree(SLEEP_SKILL, self.root / ".agents" / "skills" / "omp-flow-sleep") + self.git("init", "-q") + self.git("config", "user.name", "OMP Flow Test") + self.git("config", "user.email", "omp-flow-test@example.invalid") + + def tearDown(self) -> None: + self.temporary.cleanup() + + def git(self, *args: str) -> str: + return subprocess.run( + ["git", *args], + cwd=self.root, + text=True, + encoding="utf-8", + capture_output=True, + check=True, + ).stdout.strip() + + def invoke(self, *args: str) -> dict[str, object] | list[object]: + result = subprocess.run( + [sys.executable, "-X", "utf8", str(CLI), "--cwd", str(self.root), *args], + cwd=self.root, + text=True, + encoding="utf-8", + capture_output=True, + env={**os.environ, "OMP_FLOW_CONTEXT_ID": "wiki-sleep-test"}, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + return json.loads(result.stdout) + + def capture(self, *args: str) -> subprocess.CompletedProcess[bytes]: + return subprocess.run( + [sys.executable, "-X", "utf8", str(CLI), "--cwd", str(self.root), *args], + cwd=self.root, + capture_output=True, + env={**os.environ, "OMP_FLOW_CONTEXT_ID": "wiki-sleep-test"}, + check=False, + ) + + def deny(self, expected: str, *args: str) -> None: + result = subprocess.run( + [sys.executable, "-X", "utf8", str(CLI), "--cwd", str(self.root), *args], + cwd=self.root, + text=True, + encoding="utf-8", + capture_output=True, + env={**os.environ, "OMP_FLOW_CONTEXT_ID": "wiki-sleep-test"}, + check=False, + ) + self.assertNotEqual(result.returncode, 0, result.stdout) + self.assertIn(expected, result.stderr) + + def write_markdown(self, relative: str, title: str) -> None: + destination = self.root / relative + destination.parent.mkdir(parents=True, exist_ok=True) + destination.write_text( + f'---\ntype: "Test"\ntitle: "{title}"\n---\n\n# {title}\n', + encoding="utf-8", + ) + + def test_archive_to_sleep_is_reproducible_confined_and_reviewable(self) -> None: + created = self.invoke("task", "create", "Sleep source", "--slug", "sleep-source") + task_id = str(created["taskId"]) + self.git("add", "-A") + self.git("commit", "-qm", "test: checkpoint Sleep source") + + archived = self.invoke("task", "archive") + source = archived["sleepSource"] + self.assertTrue(source["ready"]) + self.assertEqual(source["archivedPath"], archived["archivedTo"]) + self.assertEqual(len(source["sourceCommit"]), 40) + self.assertEqual(len(source["sourceTree"]), 40) + + actor_id = "sleep-native-測試" + run_root = self.root / ".omp-flow" / ".runtime" / "sleep" / "runs" + with mock.patch.object( + sleep_store, + "_sleep_assignment", + side_effect=RuntimeError("renderer failed"), + ): + with self.assertRaisesRegex(RuntimeError, "renderer failed"): + sleep_store.start_sleep_run(self.root, str(source["receipt"]), actor_id) + self.assertEqual(list(run_root.glob("*.json")), []) + + original_assignment = sleep_store._sleep_assignment + with mock.patch.object( + sleep_store, + "atomic_write_json", + side_effect=OSError("writer failed"), + ): + with self.assertRaisesRegex(OSError, "writer failed"): + sleep_store.start_sleep_run(self.root, str(source["receipt"]), actor_id) + self.assertEqual(list(run_root.glob("*.json")), []) + + writer_entered = threading.Event() + release_writer = threading.Event() + writer_claim = threading.Lock() + rendered_values: list[str] = [] + written_values: list[dict[str, object]] = [] + original_write = sleep_store.atomic_write_json + + def counted_assignment(value: dict[str, object]) -> str: + self.assertNotIn("assignment", value) + assignment = original_assignment(value) + rendered_values.append(assignment) + return assignment + + def delayed_first_write(path: Path, value: object) -> None: + self.assertIsInstance(value, dict) + written = dict(value) + self.assertEqual(written["state"], "active") + self.assertIsInstance(written.get("assignment"), str) + written_values.append(written) + with writer_claim: + first_writer = not writer_entered.is_set() + if first_writer: + writer_entered.set() + if first_writer: + self.assertTrue(release_writer.wait(5), "concurrent start did not reach the lock") + original_write(path, value) + + def attempt_start(attempt_actor_id: str) -> tuple[str, object]: + try: + return ( + "ok", + sleep_store.start_sleep_run( + self.root, + str(source["receipt"]), + attempt_actor_id, + ), + ) + except WorkflowError as exc: + return ("error", str(exc)) + + with ( + mock.patch.object(sleep_store, "_sleep_assignment", counted_assignment), + mock.patch.object(sleep_store, "atomic_write_json", delayed_first_write), + ): + with ThreadPoolExecutor(max_workers=2) as executor: + first = executor.submit(attempt_start, actor_id) + self.assertTrue(writer_entered.wait(5), "first start did not reach its atomic write") + second = executor.submit(attempt_start, "concurrent-sleep-actor") + try: + second_result = second.result(timeout=5) + finally: + release_writer.set() + first_result = first.result(timeout=5) + + self.assertEqual(first_result[0], "ok") + self.assertEqual(second_result[0], "error") + self.assertIn("Sleep run is busy", str(second_result[1])) + self.assertEqual(len(rendered_values), 1) + self.assertEqual(len(written_values), 1) + started = first_result[1] + run = started["run"] + assignment = str(started["assignment"]) + self.assertEqual(run, written_values[0]) + self.assertEqual(run["assignment"], assignment) + self.assertEqual(rendered_values[0], assignment) + self.assertTrue(assignment.endswith("\n")) + self.assertIn("測試", assignment) + first_line = next(line for line in assignment.splitlines() if line.strip()) + descriptor = json.loads(first_line)["ompFlowSleep"] + self.assertEqual(descriptor["receipt"], run["receipt"]) + self.assertEqual(descriptor["sourceReceipt"], source["receipt"]) + self.assertEqual(descriptor["sourceTree"], source["sourceTree"]) + self.assertEqual(descriptor["sourceTask"], archived["archivedTo"]) + self.assertEqual(descriptor["actorId"], actor_id) + self.assertEqual( + run["harvesterRevision"], + hashlib.sha256( + (self.root / ".agents" / "skills" / "omp-flow-sleep" / "SKILL.md").read_bytes() + ).hexdigest(), + ) + self.assertTrue((self.root / str(run["candidateRoot"])).is_dir()) + + run_path = run_root / f'{run["receipt"]}.json' + persisted = json.loads(run_path.read_bytes()) + before_reads = run_path.read_bytes() + self.assertEqual(persisted, run) + captured_show = self.capture("sleep", "show", str(run["receipt"])) + self.assertEqual(captured_show.returncode, 0, captured_show.stderr.decode("utf-8")) + self.assertTrue(captured_show.stdout.endswith(b"\n")) + shown = json.loads(captured_show.stdout) + self.assertEqual(shown["assignment"].encode("utf-8"), assignment.encode("utf-8")) + matching_list = next( + value + for value in self.invoke("sleep", "list") + if value["receipt"] == run["receipt"] + ) + self.assertEqual(matching_list["assignment"], assignment) + + installed_store = self.root / ".omp-flow" / "scripts" / "common" / "sleep_store.py" + installed_source = installed_store.read_text(encoding="utf-8") + changed_source = installed_source.replace( + "def _sleep_assignment(", + "def _sleep_assignment_changed_after_start(", + 1, + ) + self.assertNotEqual(changed_source, installed_source) + installed_store.write_text(changed_source, encoding="utf-8") + try: + self.assertEqual( + self.invoke("sleep", "show", str(run["receipt"]))["assignment"], + assignment, + ) + self.assertEqual( + next( + value + for value in self.invoke("sleep", "list") + if value["receipt"] == run["receipt"] + )["assignment"], + assignment, + ) + finally: + installed_store.write_text(installed_source, encoding="utf-8") + self.assertEqual(run_path.read_bytes(), before_reads) + + for duplicate_actor in (actor_id, "second-actor"): + self.deny( + "Sleep run already exists", + "sleep", + "start", + "--source", + str(source["receipt"]), + "--actor-id", + duplicate_actor, + ) + runtime_root = self.root / ".omp-flow" / ".runtime" + runtime_before = sorted( + path.relative_to(runtime_root).as_posix() for path in runtime_root.rglob("*") + ) + self.deny( + "Invalid Sleep receipt", + "sleep", + "finish", + "x/../../traversal-target", + "--state", + "completed", + "--actor-id", + actor_id, + ) + runtime_after = sorted( + path.relative_to(runtime_root).as_posix() for path in runtime_root.rglob("*") + ) + self.assertEqual( + runtime_after, + runtime_before, + "invalid receipt must be rejected before any lock path is created", + ) + self.deny( + "Sleep actor identity mismatch", + "sleep", + "finish", + str(run["receipt"]), + "--state", + "completed", + "--actor-id", + "wrong-actor", + ) + self.assertEqual(run_path.read_bytes(), before_reads) + self.deny( + "Sleep run receipt output is missing", + "sleep", + "finish", + str(run["receipt"]), + "--state", + "completed", + "--actor-id", + actor_id, + ) + self.assertEqual(run_path.read_bytes(), before_reads) + + self.write_markdown(str(run["runOutput"]), "Sleep run receipt") + candidate_name = "exported-symbol-change-safety.md" + self.write_markdown( + f'{run["candidateRoot"]}/{candidate_name}', + "Exported symbol change safety", + ) + archived_task = self.root / str(archived["archivedTo"]) / "task.md" + original = archived_task.read_bytes() + archived_task.write_bytes(original + b"\nsource drift\n") + self.deny( + "Archived Sleep source has drifted", + "sleep", + "finish", + str(run["receipt"]), + "--state", + "completed", + "--actor-id", + actor_id, + "--candidate", + candidate_name, + ) + self.assertEqual(run_path.read_bytes(), before_reads) + archived_task.write_bytes(original) + + completed = self.invoke( + "sleep", + "finish", + str(run["receipt"]), + "--state", + "completed", + "--actor-id", + actor_id, + "--candidate", + candidate_name, + ) + self.assertEqual(completed["state"], "completed") + self.assertEqual(completed["candidates"], [f'{run["candidateRoot"]}/{candidate_name}']) + self.assertNotIn("assignment", completed) + completed_show = self.invoke("sleep", "show", str(run["receipt"])) + completed_list = next( + value + for value in self.invoke("sleep", "list") + if value["receipt"] == run["receipt"] + ) + self.assertNotIn("assignment", completed_show) + self.assertNotIn("assignment", completed_list) + self.assertNotIn("assignment", json.loads(run_path.read_bytes())) + for duplicate_actor in (actor_id, "second-actor"): + self.deny( + "Sleep run already exists", + "sleep", + "start", + "--source", + str(source["receipt"]), + "--actor-id", + duplicate_actor, + ) + self.deny( + "Sleep run is already terminal", + "sleep", + "finish", + str(run["receipt"]), + "--state", + "completed", + "--actor-id", + actor_id, + ) + + uncheckpointed = self.invoke( + "task", + "create", + "Uncheckpointed source", + "--slug", + "uncheckpointed-source", + ) + self.assertNotEqual(uncheckpointed["taskId"], task_id) + unavailable = self.invoke("task", "archive") + self.assertFalse(unavailable["sleepSource"]["ready"]) + self.assertTrue(unavailable["sleepSource"]["reason"]) + self.assertTrue((self.root / str(unavailable["archivedTo"])).is_dir()) + + def test_failed_terminal_and_legacy_active_records_do_not_yield_assignment(self) -> None: + self.invoke("task", "create", "Failed Sleep source", "--slug", "failed-sleep-source") + self.git("add", "-A") + self.git("commit", "-qm", "test: checkpoint failed Sleep source") + failed_archive = self.invoke("task", "archive") + failed_source = failed_archive["sleepSource"] + failed_actor = "failed-sleep-actor" + started = self.invoke( + "sleep", + "start", + "--source", + str(failed_source["receipt"]), + "--actor-id", + failed_actor, + ) + failed_run = started["run"] + failed_path = ( + self.root + / ".omp-flow" + / ".runtime" + / "sleep" + / "runs" + / f'{failed_run["receipt"]}.json' + ) + active_bytes = failed_path.read_bytes() + self.assertEqual(failed_run["assignment"], started["assignment"]) + for duplicate_actor in (failed_actor, "different-failed-actor"): + self.deny( + "Sleep run already exists", + "sleep", + "start", + "--source", + str(failed_source["receipt"]), + "--actor-id", + duplicate_actor, + ) + self.deny( + "Failed Sleep run cannot claim candidate outputs", + "sleep", + "finish", + str(failed_run["receipt"]), + "--state", + "failed", + "--actor-id", + failed_actor, + "--candidate", + "forbidden.md", + ) + self.assertEqual(failed_path.read_bytes(), active_bytes) + + failed = self.invoke( + "sleep", + "finish", + str(failed_run["receipt"]), + "--state", + "failed", + "--actor-id", + failed_actor, + ) + self.assertEqual(failed["state"], "failed") + self.assertEqual(failed["candidates"], []) + self.assertNotIn("assignment", failed) + self.assertNotIn( + "assignment", + self.invoke("sleep", "show", str(failed_run["receipt"])), + ) + listed_failed = next( + value + for value in self.invoke("sleep", "list") + if value["receipt"] == failed_run["receipt"] + ) + self.assertNotIn("assignment", listed_failed) + self.assertNotIn("assignment", json.loads(failed_path.read_bytes())) + for duplicate_actor in (failed_actor, "different-failed-actor"): + self.deny( + "Sleep run already exists", + "sleep", + "start", + "--source", + str(failed_source["receipt"]), + "--actor-id", + duplicate_actor, + ) + + self.invoke("task", "create", "Legacy Sleep source", "--slug", "legacy-sleep-source") + self.git("add", "-A") + self.git("commit", "-qm", "test: checkpoint legacy Sleep source") + legacy_archive = self.invoke("task", "archive") + legacy_source = legacy_archive["sleepSource"] + legacy_actor = "legacy-sleep-actor" + legacy_started = self.invoke( + "sleep", + "start", + "--source", + str(legacy_source["receipt"]), + "--actor-id", + legacy_actor, + ) + legacy_run = legacy_started["run"] + legacy_path = ( + self.root + / ".omp-flow" + / ".runtime" + / "sleep" + / "runs" + / f'{legacy_run["receipt"]}.json' + ) + legacy_run.pop("assignment") + legacy_path.write_text( + json.dumps(legacy_run, ensure_ascii=False, indent=2) + "\n", + encoding="utf-8", + ) + legacy_bytes = legacy_path.read_bytes() + self.assertEqual( + self.invoke("sleep", "show", str(legacy_run["receipt"])), + legacy_run, + ) + listed_legacy = next( + value + for value in self.invoke("sleep", "list") + if value["receipt"] == legacy_run["receipt"] + ) + self.assertEqual(listed_legacy, legacy_run) + self.assertEqual(legacy_path.read_bytes(), legacy_bytes) + + terminal_legacy = self.invoke( + "sleep", + "finish", + str(legacy_run["receipt"]), + "--state", + "failed", + "--actor-id", + legacy_actor, + ) + self.assertEqual(terminal_legacy["state"], "failed") + self.assertEqual(terminal_legacy["candidates"], []) + self.assertNotIn("assignment", terminal_legacy) + + + + def test_run_lock_excludes_live_holder_and_survives_holder_kill(self) -> None: + self.invoke("task", "create", "Lock holder source", "--slug", "lock-holder-source") + self.git("add", "-A") + self.git("commit", "-qm", "test: checkpoint lock holder source") + archived = self.invoke("task", "archive") + source_receipt = str(archived["sleepSource"]["receipt"]) + revision = sleep_store._skill_revision(self.root) + run_receipt = hashlib.sha256( + f"{source_receipt}\0{revision}".encode("utf-8") + ).hexdigest() + + # A live holder excludes any other starter, across processes. + held = sleep_store._acquire_run_lock(self.root, run_receipt) + try: + self.deny( + "Sleep run is busy", + "sleep", + "start", + "--source", + source_receipt, + "--actor-id", + "sleep-native-test", + ) + finally: + sleep_store._release_run_lock(held) + + # A killed holder releases at OS level: no stale lock, no cleanup command. + child_code = ( + "import sys, time; sys.path.insert(0, {path!r}); " + "from pathlib import Path; " + "from common import sleep_store; " + "sleep_store._acquire_run_lock(Path({root!r}), {receipt!r}); " + "print('locked', flush=True); time.sleep(60)" + ).format( + path=str(SOURCE_ROOT / "templates" / ".omp-flow" / "scripts"), + root=str(self.root), + receipt=run_receipt, + ) + holder = subprocess.Popen( + [sys.executable, "-X", "utf8", "-c", child_code], + stdout=subprocess.PIPE, + text=True, + encoding="utf-8", + ) + try: + assert holder.stdout is not None + self.assertEqual(holder.stdout.readline().strip(), "locked") + finally: + holder.kill() + holder.wait(timeout=10) + if holder.stdout is not None: + holder.stdout.close() + + started = self.invoke( + "sleep", + "start", + "--source", + source_receipt, + "--actor-id", + "sleep-native-test", + ) + self.assertEqual(started["run"]["state"], "active") + + + @unittest.skipUnless(os.name == "nt", "msvcrt byte-range locking runs only on Windows") + def test_windows_byte_range_lock_contention(self) -> None: + # A second handle to the same file is excluded from the locked byte + # region even within one process; acquire must surface as busy, never + # as a stray PermissionError, and release must restore availability. + receipt = "a" * 64 + first = sleep_store._acquire_run_lock(self.root, receipt) + try: + with self.assertRaises(WorkflowError) as caught: + sleep_store._acquire_run_lock(self.root, receipt) + self.assertIn("Sleep run is busy", str(caught.exception)) + finally: + sleep_store._release_run_lock(first) + second = sleep_store._acquire_run_lock(self.root, receipt) + sleep_store._release_run_lock(second) + + +if __name__ == "__main__": + unittest.main()