diff --git a/.claude/skills/EXAMPLE-REPORT.md b/.claude/skills/EXAMPLE-REPORT.md new file mode 100644 index 0000000..ec62b06 --- /dev/null +++ b/.claude/skills/EXAMPLE-REPORT.md @@ -0,0 +1,160 @@ +# Reporting Example + +An illustrative report showing the two-layer format used by both skills. The numbers, +issue references, and SHAs below are **fictional** — this file demonstrates *format and +evidence discipline*, nothing more. It is not a record of real work. + +For the rules themselves see `batch-skill/SKILL.md` and `merge-skill/SKILL.md`. + +--- + +# Human Report + +## v1.0 Phase 1 — Batch Execution + +**Result**: 4 of 4 issues completed and merged +**Execution**: serial (parallel safety not CONFIRMED for any pair) + +| Issue | Title | PR | Result | +|---|---|---|---| +| #7 | Diagnostic SSOT | #121 | Merged | +| #8 | Regression Tests | #122 | Merged | +| #9 | RT Semantics | #123 | Merged | +| #10 | Interprocedural Analysis | #124 | Merged | + +**Changes**: 12 files, +1,247 / −89 lines, 3 new test files +**Verification**: build passed, 234/234 tests passed, CI passed for each PR HEAD +**Approvals**: 1 effective human approval per PR, each bound to that PR's final HEAD + +**Notes for the reader** + +- Issues #7–#10 form a dependency chain, so they ran serially. Parallelism was never + eligible here. +- Each merge was executed only after an explicit human approval of that specific HEAD. + +**Next**: Phase 2 (#11–#13). Their independence is not yet CONFIRMED, so plan for serial +execution until it is. + +--- + +# AI Report + +## Verification SHA binding + +Every item below is bound to the SHA named beside it. Evidence gathered for a different +SHA is not reused. + +| PR | Verification SHA | +|---|---| +| #121 | `abc1234` | +| #122 | `bcd2345` | +| #123 | `cde3456` | +| #124 | `def4567` | + +## CONFIRMED + +Observed from a trusted source during this run. + +**Git state** (per issue, at its verification SHA) +- Branch, base commit, and result commit identified for each of #7–#10 +- Working tree clean at each verification point — no uncommitted or untracked files +- Each feature branch ancestry to the base branch established + +**Build and test** +- Build succeeded for each verification SHA +- 234/234 tests passed; 0 failed, 0 skipped +- Analyzer suites: RT 24 passed, LVP 18 passed, FIF 12 passed + +**CI** +- CI concluded successfully for each PR +- CI HEAD == PR HEAD confirmed for each PR (see the SHA table above) +- No required check left pending, queued, or in progress +- Stale runs at superseded commits were identified and excluded + +**Reviews** +- Required approvals: 1 (source: `.kiro/merge.config.json` → `requiredApprovals`) +- Effective human approvals: 1 per PR, each submitted against that PR's final HEAD +- Stale approvals ignored: 0 +- Bot reviews excluded: 4 — automated review tooling, not counted as human approval +- Outstanding `CHANGES_REQUESTED`: none + +**Mergeability** +- No conflicts with the base branch for any PR +- Host-reported merge state clean for each PR + +**File conflict analysis** — read from the actual branch diffs, not inferred from issue +descriptions, because the batch conflict gate requires CONFIRMED evidence: +- #7 touches `Analyzer.cs`, `DiagnosticCatalog.cs`, localization files +- #8 touches `Tests/`, `TestData/`, `TestBase.cs` — no overlap with #7 +- #9 touches `ReferentialTransparencyAnalyzer.cs`, `SemanticAnalyzer.cs` — no overlap with #7, #8 +- #10 touches `InterproceduralAnalyzer.cs`, `CallGraphBuilder.cs` — no overlap with #7–#9 +- Shared mutable configuration touched by more than one issue: none +- Shared public contract touched by more than one issue: none + +**Human approval** +- Explicit human approval recorded per PR, naming the PR and its SHA, before execution + +**Post-merge** +- Each PR state `MERGED`; merge commit identified for each +- Base branch contains the expected result; base branch HEAD verified after each merge +- Post-merge CI on the base branch concluded successfully + +## INFERRED + +Reasonable conclusions from the confirmed facts. **None of these opened a gate.** They +are recorded for context, and where they bore on execution they pushed toward the safe +side. + +- **Dependency chain satisfied** — inferred from execution order: #7 completed first, + then #8, #9, #10, each after its blocker merged. +- **Phase 2 (#11–#13) may be independent** — inferred from the analyzers they are + scoped to. This did **not** authorise parallelism. Independence must be CONFIRMED on + every dimension before #11–#13 run in parallel; until then they run serially. + +## UNVERIFIED + +Not established. Each would block any gate that depended on it. + +- Long-term performance impact of the #10 interprocedural changes — not measured +- Downstream consumer compatibility beyond the repository's own test suite — not exercised + +Neither is a gate item for this batch, so neither blocked it. They are reported rather +than omitted so the reader can see the edge of what was checked. + +## Gate results + +Batch gate, per issue: all items CONFIRMED → each PR a merge candidate. + +Merge gate, per PR: + +```text +Layer 1 — technical gates: all CONFIRMED → MERGE CANDIDATE +Layer 2 — human approval: EXPLICIT HUMAN APPROVAL recorded +Verdict: MERGED, post-merge verification passed +``` + +Passing layer 1 produced a candidate only. Every merge required the layer 2 approval. + +--- + +## What a blocked report looks like + +The same structure, with the verdict and the blocking reason stated plainly. Blocked is +a normal, correct outcome — not a failure of the report. + +```text +PR: #125 +Verification SHA: ef56789 +CI: success, CI HEAD == PR HEAD (ef56789) +Mergeability: clean, no conflicts +Required approvals: 1 +Effective human approvals: 0 +Bot reviews excluded: 1 + +Verdict: MERGE BLOCKED + - Requires 1 effective human approval on ef56789, has 0 +``` + +Note what this report does **not** do: it does not describe the PR as ready, safe, or +merely awaiting a formality. Zero human approvals means blocked, and the passing CI does +not soften that. diff --git a/.claude/skills/README.md b/.claude/skills/README.md new file mode 100644 index 0000000..08bcfb8 --- /dev/null +++ b/.claude/skills/README.md @@ -0,0 +1,119 @@ +# PureSharp Batch & Merge Skills + +Two skills coordinate multi-issue development and safe integration for the PureSharp +v1.0.0 roadmap. + +| Skill | Specification | Responsibility | +|---|---|---| +| **Batch Skill** | `batch-skill/SKILL.md` | Orchestrate multiple issues: dependencies, parallel safety, execution graph, aggregation | +| **Merge Skill** | `merge-skill/SKILL.md` | Verify a PR against merge gates, enforce the human approval boundary, verify after merge | + +## Scriptless by design + +Each `SKILL.md` is an **executable specification and the single source of truth** for its +skill. There are no helper scripts, and none may be added as a requirement. + +This is deliberate. The skills define **which facts must be established**, not **which +commands to run** — so they carry no dependency on PowerShell version, shell dialect, +path separator, file encoding, exit-code convention, or any one CLI being installed. + +They run unchanged on Windows, Linux, macOS, and WSL. No PowerShell, Bash, Python, or +Node runtime is required. + +Establish each fact with whichever trusted source the environment offers — a GitHub +connector, `gh`, the GitHub API, `git` for local facts, or the repository's own build and +test tooling. If **no** available source can establish a required fact, the result is +**UNVERIFIED**, and UNVERIFIED blocks. Skipping a check because a tool is missing is +never acceptable. + +Porting the removed helper scripts into another language would reintroduce exactly the +coupling this design removes, and is not a valid change. + +## Using the skills + +Invoke a skill and follow its specification. The Merge Skill's default mode is +verification only: it reads state, changes nothing, and is safe to run at any time. + +```text +Batch Skill → analyse issues, decide execution order, run, aggregate, report +Merge Skill → verify a PR against the gates, report MERGE CANDIDATE or MERGE BLOCKED +``` + +Neither skill merges anything on its own. See `WORKFLOW.md` for the end-to-end flow. + +## Safety principles + +These are fixed policy. No configuration, flag, or argument relaxes them. + +1. **Fail closed.** Any error, ambiguity, or missing evidence blocks. +2. **Explicit human approval before every merge.** Technical verification success is not + permission to merge. The approval comes from one of exactly two sources — a + third-party GitHub `APPROVED` review, or, for a self-authored PR in a repository that + requires no third-party review, an explicit out-of-band approval bound to the exact + HEAD SHA. **Repository policy always wins**: where the repository requires approving + reviews, nothing here bypasses it. A self-authored PR is never recorded as carrying + its author's GitHub approval. +3. **Evidence is bound to an exact commit.** Stale evidence never satisfies a gate; a new + push invalidates all prior evidence, approvals included. +4. **UNVERIFIED blocks. INFERRED never opens a gate.** +5. **Parallel execution requires proof of safety**, not merely the absence of known + danger. Serial is the safe default. +6. **Auto-merge is never enabled**; the base branch is never force-pushed or pushed to + directly. + +## Evidence classification + +Both skills use these three labels and no others. + +| Label | Meaning | May open a gate? | +|---|---|---| +| **CONFIRMED** | Actually observed from a trusted source this run | Yes | +| **INFERRED** | Reasonable conclusion from confirmed facts, not itself observed | No — may only support a decision that fails safe | +| **UNVERIFIED** | Not established, including "the tool was unavailable" | No — blocks | + +**Golden rule**: never claim success for something you have not verified. + +## Configuration + +Both configuration files carry **data only**. Behaviour lives in the `SKILL.md` files. + +| File | Keys | +|---|---| +| `.kiro/merge.config.json` | `requiredApprovals`, `mergeMethod`, `deleteBranchAfterMerge` | +| `.kiro/batch.config.json` | `maxParallelTasks` | + +A missing file, malformed JSON, an unknown key, or a value out of range is a **CONFIG +ERROR** and blocks. Safety policy is deliberately absent from both schemas so it cannot +be switched off, and configuration can only make a gate stricter, never weaker. + +## Files + +```text +.claude/skills/ +├── README.md (this file — overview, invocation, safety principles) +├── WORKFLOW.md (end-to-end workflow: batch → PR → review → merge) +├── EXAMPLE-REPORT.md (reporting example) +├── batch-skill/ +│ └── SKILL.md (batch specification — SSOT) +└── merge-skill/ + └── SKILL.md (merge specification — SSOT) + +.kiro/ +├── batch.config.json +└── merge.config.json +``` + +## Project context + +The skills support the PureSharp v1.0.0 roadmap tracked in **Issue #6**. The roadmap's +phases, issue membership, and target dates live in the GitHub issues — deliberately not +duplicated here, where a second copy would silently go stale. + +## See also + +- `WORKFLOW.md` — end-to-end workflow +- `EXAMPLE-REPORT.md` — reporting example +- `batch-skill/SKILL.md`, `merge-skill/SKILL.md` — the specifications themselves +- Issue #18 — Batch and Merge Skills +- Issue #6 — PureSharp v1.0.0 roadmap +- `.kiro/steering/` — project guidance documents diff --git a/.claude/skills/WORKFLOW.md b/.claude/skills/WORKFLOW.md new file mode 100644 index 0000000..3733dcc --- /dev/null +++ b/.claude/skills/WORKFLOW.md @@ -0,0 +1,148 @@ +# PureSharp Batch & Merge Workflow + +End-to-end flow from issue selection to a merged, verified PR. + +This document describes **how the phases fit together**. It does not restate the gates, +the evidence requirements, or the failure behaviour — those live in the specifications: + +- `batch-skill/SKILL.md` — batch orchestration and parallel safety +- `merge-skill/SKILL.md` — merge gates, approval semantics, human approval boundary + +Where this document and a `SKILL.md` disagree, the `SKILL.md` wins. + +## Overview + +```text +Issue selection + ↓ +Batch analysis (Batch Skill) dependencies, parallel safety, execution graph + ↓ +Implementation (per issue) spec-driven work on a feature branch + ↓ +Pull request (per issue) + ↓ +Merge verification (Merge Skill) gates → MERGE CANDIDATE or MERGE BLOCKED + ↓ +Human review + explicit human approval + ↓ +Merge execution (Merge Skill) + ↓ +Post-merge verification + ↓ +Batch report +``` + +No step in this workflow requires a particular shell, runtime, or CLI. Each phase +establishes facts from whichever trusted source the environment offers. + +## Phase 1 — Batch analysis + +Invoke the Batch Skill with the issues under consideration. + +It retrieves live issue state, reads requirements, establishes dependencies, investigates +affected areas, classifies every finding, and decides parallel safety pairwise. The +output is an execution graph: ordered layers, with parallel groups only where safety is +CONFIRMED on every dimension. + +Expect serial execution to be the common answer. Two issues touching disjoint files can +still conflict through shared configuration, a shared public contract, architectural +coupling, or a required order — so file non-overlap alone never justifies parallelism. A +batch that runs serially because independence could not be proven is a correct outcome. + +## Phase 2 — Implementation + +For each issue, in the order the execution graph gives: + +1. Create a feature branch for the issue +2. Implement against the issue's requirements +3. Build and test locally +4. Open a pull request +5. Let CI run + +Use the repository's existing spec-driven workflow for the implementation itself. The +Batch Skill governs *ordering and concurrency*, not how any one issue is implemented. + +## Phase 3 — Merge verification and integration + +The full boundary, in order. Every step is mandatory: + +```text +VERIFY PR IDENTITY + ↓ +VERIFY CURRENT HEAD + ↓ +VERIFY GIT STATE + ↓ +VERIFY BUILD / TEST + ↓ +VERIFY CI FOR EXACT HEAD + ↓ +VERIFY EFFECTIVE HUMAN REVIEWS + ↓ +VERIFY MERGEABILITY + ↓ +PRODUCE MERGE CANDIDATE REPORT + ↓ +HUMAN REVIEW + ↓ +EXPLICIT HUMAN APPROVAL ← required; no automated substitute + ↓ +MERGE EXECUTION + ↓ +POST-MERGE VERIFICATION +``` + +**Technical verification success is not permission to merge.** Passing every gate through +VERIFY MERGEABILITY produces a **MERGE CANDIDATE** — a candidate, not a decision. Only an +explicit human approval moves it to MERGE EXECUTION. + +At the human review step, read the verification report and confirm that every gate item +is CONFIRMED, and that no gate item is INFERRED or UNVERIFIED. If the report says MERGE +BLOCKED, fix the cause and re-verify from the top; a blocked PR is never merged. + +Immediately before executing the merge, the Merge Skill re-confirms that nothing moved — +HEAD, CI, approvals, mergeability, and the human approval itself. Any of these failing +re-confirmation blocks the merge and sends the PR back to VERIFY. + +## Phase 4 — Reporting + +After the batch completes, produce both layers: + +- **Human report** — what ran, success and failure breakdown, blockers, next steps +- **AI report** — per-finding evidence classification, per-issue state, verification + results, and the parallel-safety decision with the evidence behind it + +See `EXAMPLE-REPORT.md`. + +## Failure handling + +Every failure below is handled the same way: **fix the cause, then re-verify from the +top.** Verification evidence is bound to a commit, so any new push invalidates all prior +evidence — including approvals already given. + +| Failure | Action | +|---|---| +| Build failed | Fix on the feature branch, push, wait for CI, re-verify | +| Tests failed | Investigate the failures, fix code or test, push, re-verify | +| CI pending or in progress | Wait for completion, then re-verify. Pending is not a pass | +| CI failed | Fix the cause, push, re-verify | +| CI belongs to an older commit | Stale — wait for CI on the current HEAD, then re-verify | +| Merge conflict | Rebase the feature branch on the base branch, resolve, test, push, re-verify | +| Base branch moved | Re-verify; rebase if the move invalidates the verification | +| Approvals insufficient | Request review. Never substitute an automated verdict for a human approval | +| Repository requires reviews, none present | Obtain the required third-party reviews. Out-of-band approval cannot substitute | +| Self-authored PR, no third-party reviewer available | Use the out-of-band approval path in `merge-skill/SKILL.md`, bound to the exact HEAD SHA. Never record a self-approval as a GitHub review | +| `mergeMethod` not enabled in the repository | CONFIG ERROR. Fix the configuration; never silently merge by another method | +| Changes requested | Address the review, push, obtain a fresh approval on the new HEAD | +| PR HEAD changed mid-verification | Restart verification from the top | +| Required evidence unobtainable | UNVERIFIED → BLOCKED. Find another trusted source; do not skip the check | + +Nothing in this table is merged around, waived, or configured away. + +## See also + +- `README.md` — overview, invocation, safety principles +- `batch-skill/SKILL.md`, `merge-skill/SKILL.md` — the specifications +- `EXAMPLE-REPORT.md` — reporting example +- Issue #18 — Batch and Merge Skills +- Issue #6 — PureSharp v1.0.0 roadmap diff --git a/.claude/skills/batch-skill/SKILL.md b/.claude/skills/batch-skill/SKILL.md new file mode 100644 index 0000000..1a6509b --- /dev/null +++ b/.claude/skills/batch-skill/SKILL.md @@ -0,0 +1,193 @@ +--- +name: batch-skill +description: Orchestrates multiple PureSharp GitHub issues as a batch. Defines dependency analysis, the CONFIRMED-only evidence bar for parallel execution, execution graph construction, result aggregation, and batch reporting. Use when planning or running work across several issues. +--- + +# Batch Skill for PureSharp Issue Orchestration + +## Status of this document + +**This document is the executable specification and the single source of truth (SSOT) +for batch orchestration in this repository.** There is no helper script. Behaviour is +defined here, not in any `.ps1`, `.sh`, `.py`, or `.js` file, and none may be introduced +as a requirement of this skill. + +The skill defines **which facts must be established**, not **which commands to run**. + +## Design Principles + +1. **SKILL.md is the SSOT.** +2. **No required environment-dependent script.** Porting logic from one scripting + language to another is not a valid response to this rule. +3. **Facts, not commands.** +4. **Any trusted source is acceptable** — see the Merge Skill's "Selecting a trusted + source", which applies identically here. +5. **Unavailable evidence is UNVERIFIED.** Never skip a check because a tool is missing. +6. **Parallel execution requires proof of safety, not absence of evidence of danger.** +7. **Serial execution is the safe default.** When in doubt, run serially. + +## Fixed Safety Policy (not configurable) + +- Parallel execution requires CONFIRMED evidence on every safety dimension. +- INFERRED safety → serial execution. +- UNVERIFIED safety → serial execution, or BLOCKED where the unknown affects correctness. +- A batch never merges anything. Merging is the Merge Skill's responsibility and always + requires explicit human approval. +- Fail closed: any error, ambiguity, or missing evidence degrades toward serial or blocked. + +## Evidence Classification + +Identical to the Merge Skill. + +| Label | Meaning | +|---|---| +| **CONFIRMED** | Actually observed from a trusted source during this run. | +| **INFERRED** | A reasonable conclusion from CONFIRMED facts, not itself observed. | +| **UNVERIFIED** | Not established, including "the tool was unavailable". | + +- Gate items require **CONFIRMED**. +- **INFERRED** may support a decision that fails safe — choosing serial execution is such + a decision. It may never open a gate or authorise parallelism. +- **UNVERIFIED** must be reported, never omitted. + +## Batch Workflow + +1. **Retrieve the issues.** Obtain the batch's issues from a trusted GitHub source. +2. **Confirm current state.** For each issue: open or closed, assignee, labels, linked + PRs. Work from live state, never from a cached or remembered list. +3. **Read the requirements.** Read each issue body and its acceptance criteria. +4. **Identify dependencies.** Establish blocking / blocked-by relationships from issue + metadata and issue content — not from issue-number ordering. +5. **Investigate affected areas.** For each issue, determine the code, configuration, + and public contracts it will touch. +6. **Classify the evidence.** Label every dependency and affected-area finding + CONFIRMED, INFERRED, or UNVERIFIED. +7. **Decide parallel safety.** Apply the checklist below, pairwise. +8. **Build the execution graph.** Resolve the dependency DAG into ordered layers, with + parallel groups only where safety is CONFIRMED. +9. **Execute the batch**, honouring the graph. +10. **Aggregate results** per issue. +11. **Report**, in the two-layer format. + +## Parallel Safety + +Two issues may run in parallel **only when every dimension below is CONFIRMED for that +specific pair**: + +- [ ] Dependency graph resolved — every edge between them determined, none assumed +- [ ] No execution-order dependency +- [ ] No shared mutable configuration +- [ ] No shared public contract change +- [ ] No architectural coupling that requires ordering +- [ ] No conflicting change area +- [ ] No release or version coordination conflict + +**File non-overlap alone is never sufficient.** Two issues touching disjoint files can +still conflict through shared configuration, a shared public contract, architectural +coupling, or a required execution order. "Different analyzers" and "different files" are +starting observations, not conclusions. + +Decision table: + +| Evidence level on any dimension | Execution | +|---|---| +| All dimensions CONFIRMED | **PARALLEL permitted** | +| Any dimension INFERRED | **SERIAL** | +| Any dimension UNVERIFIED | **SERIAL**, or **BLOCKED** if the unknown affects correctness | + +**If safety cannot be proven, do not choose parallel execution.** The absence of a known +conflict is not evidence of independence. Never promote INFERRED to CONFIRMED because a +conflict seems unlikely. + +Configuration may lower the parallel limit but can never lower this evidence bar. + +## Result Collection + +Track, per issue: + +- Branch and the commits produced +- Build result +- Test result +- PR identity and state +- CI result, bound to the PR HEAD + +Classify each issue's outcome as exactly one of: + +| Status | Meaning | +|---|---| +| **Success** | All required checks CONFIRMED passing | +| **Blocked** | A dependency did not complete, or a gate blocked it | +| **Failed** | Implementation or verification failed | +| **Pending** | Awaiting human approval or an external result | +| **Unexecuted** | Skipped — conflict risk, or an unresolved dependency | + +## Batch Gate + +A batch may advance to the merge phase only when, for **every** issue: + +- [ ] Branch exists and its working tree is clean (CONFIRMED) +- [ ] Base commit identified (CONFIRMED) +- [ ] Result commit identified (CONFIRMED) +- [ ] Build succeeded (CONFIRMED) +- [ ] Relevant tests passed (CONFIRMED) +- [ ] CI passed for the PR HEAD (CONFIRMED) +- [ ] PR exists and is mergeable (CONFIRMED) +- [ ] No file conflicts with other issues in the batch (CONFIRMED) + +Conflict evidence bar: + +| Conflict evidence | Batch gate | +|---|---| +| CONFIRMED | may pass | +| INFERRED | **BATCH GATE BLOCKED** | +| UNVERIFIED | **BATCH GATE BLOCKED** | + +Passing the batch gate makes each PR a **merge candidate** and nothing more. Every merge +still runs through the Merge Skill, including its explicit human approval step. The batch +gate never authorises a merge. + +## Reporting + +Two layers, both required. + +**Human report** — what was executed, success and failure breakdown, critical blockers, +recommended next steps. + +**AI report** — evidence classification per finding, per-issue git state, verification +results, dependency resolution status, and the parallel-safety decision with the evidence +that drove it. + +Report the parallel-safety decision explicitly, including which dimensions were +CONFIRMED and which forced serial execution. A batch that ran serially because safety +could not be proven is a correct outcome and should be reported as such, not as a +shortfall. + +See `../EXAMPLE-REPORT.md`. + +## Configuration + +`.kiro/batch.config.json` carries **data only**. All behaviour is defined here. + +| Key | Type | Meaning | +|---|---|---| +| `maxParallelTasks` | integer ≥ 1 | Upper bound on concurrent tasks. `1` forces fully serial execution. | + +Rules: + +- Missing file, malformed JSON, an unknown key, a key of the wrong type, or + `maxParallelTasks < 1` → **CONFIG ERROR → BATCH BLOCKED**. +- `maxParallelTasks` is a **ceiling, not a licence**. It never authorises parallelism the + evidence bar has not already permitted. Raising it cannot make an INFERRED or + UNVERIFIED pair parallel-eligible. +- Safety policy is deliberately absent from the schema so it cannot be switched off. +- The v1.0 roadmap, its phases, and its target dates live in the GitHub issues + (Issue #6), not in this configuration. Do not duplicate them here — a second copy + silently goes stale. + +## Related + +- `../merge-skill/SKILL.md` — merge gates, approval semantics, human approval boundary +- `../WORKFLOW.md` — end-to-end workflow +- `../EXAMPLE-REPORT.md` — reporting example +- Issue #18 — Batch and Merge Skills +- Issue #6 — PureSharp v1.0.0 roadmap diff --git a/.claude/skills/merge-skill/SKILL.md b/.claude/skills/merge-skill/SKILL.md new file mode 100644 index 0000000..72458d4 --- /dev/null +++ b/.claude/skills/merge-skill/SKILL.md @@ -0,0 +1,422 @@ +--- +name: merge-skill +description: Safe integration of a PureSharp pull request into the base branch. Defines the evidence that must be CONFIRMED before a PR becomes a merge candidate, the human approval boundary, and the post-merge verification contract. Use when verifying, approving, or executing a merge. +--- + +# Merge Skill for PureSharp Safe Integration + +## Status of this document + +**This document is the executable specification and the single source of truth (SSOT) +for merge safety in this repository.** There is no helper script. Behaviour is defined +here, not in any `.ps1`, `.sh`, `.py`, or `.js` file, and none may be introduced as a +requirement of this skill. + +The skill defines **which facts must be established**, not **which commands to run**. +Any trusted tool available in the execution environment may be used to establish them. + +## Design Principles + +1. **SKILL.md is the SSOT.** If this document and any other artifact disagree, this + document wins. +2. **No required environment-dependent script.** No PowerShell, shell, Python, or Node + helper is required, and none may be added to satisfy this skill. Migrating the logic + from one scripting language to another is not a valid response to this rule. +3. **Facts, not commands.** Each gate names the fact to establish and the acceptance + criterion, never a fixed command line. +4. **Any trusted source is acceptable.** See "Selecting a trusted source". +5. **Unavailable evidence is UNVERIFIED, and UNVERIFIED blocks.** Never skip a check + because a tool is missing. +6. **Never infer a gate open.** Gates require CONFIRMED evidence. +7. **Human approval is required before every merge.** Technical success is not + permission. + +## Fixed Safety Policy (not configurable) + +These hold in every environment and cannot be relaxed by configuration. If a +configuration file appears to weaken any of them, the configuration is wrong and the +merge is BLOCKED. + +- Fail closed: any error, ambiguity, or missing evidence blocks the merge. +- Explicit human approval is required before merge execution. +- Repository policy takes precedence over this skill. Where the repository requires + approving reviews, that requirement cannot be bypassed by any means described here. +- A self-authored PR is never recorded as carrying its author's GitHub approval. +- Auto-merge is never enabled by this skill. +- Verification is bound to an exact commit SHA; stale evidence never satisfies a gate. +- UNVERIFIED blocks. INFERRED does not satisfy a gate. +- This skill never force-pushes and never pushes directly to the base branch. +- Working tree must be clean at the point of any local verification. + +## Evidence Classification + +Shared with the Batch Skill. Use these three labels and no others. + +| Label | Meaning | +|---|---| +| **CONFIRMED** | Actually observed from a trusted source during this verification run. | +| **INFERRED** | A reasonable conclusion drawn from CONFIRMED facts, but not itself observed. | +| **UNVERIFIED** | Not established — including "the tool was unavailable" and "the answer was ambiguous". | + +Rules: + +- Every gate item in this document requires **CONFIRMED**. +- **INFERRED** may be reported for context and may support a decision that fails safe + (for example, choosing serial execution), but never opens a gate. +- **UNVERIFIED** blocks. Report it as UNVERIFIED; do not silently omit it. +- Evidence is bound to the SHA it was observed for. Re-using evidence gathered for a + different SHA makes it UNVERIFIED, not CONFIRMED. + +## Selecting a Trusted Source + +Establish each fact from whichever trusted source the environment actually offers. +No single mechanism is mandatory. In rough order of preference: + +1. A first-party GitHub connector or integration, where the host designates it as such. +2. The GitHub CLI (`gh`), including its GraphQL access. +3. The GitHub REST/GraphQL API through an authenticated client. +4. `git` itself, for purely local facts (branch, commit, ancestry, working tree). +5. Repository-native build and test tooling, for build and test facts. + +Rules: + +- Prefer the source that reports the fact **directly**. Do not derive a PR's HEAD from a + local branch when the PR itself can be asked. +- Local `git` alone cannot establish PR state, CI results, reviews, or mergeability. +- If **no** available source can establish a required fact: record it **UNVERIFIED** and + report **MERGE BLOCKED**. "The tool was not available, so the check was skipped" is + never acceptable. + +## Required Evidence + +Each item below must be CONFIRMED, bound to the verification SHA, before the PR can be +reported a merge candidate. + +### A. PR identity + +- PR number +- PR state (must be OPEN) +- Base branch +- **PR HEAD SHA** — this is the *verification SHA*; every other item is bound to it + +### B. Git state + +- Current working branch +- The HEAD under verification, and that it equals the PR HEAD SHA +- Working tree state (clean: no uncommitted changes, no untracked files, no merge or + rebase in progress) +- Relationship to the base branch (ancestry known; whether the base has moved since the + PR branch diverged) + +### C. Build and test + +- Required build completed and succeeded, for the verification SHA +- Required test run completed with zero failures, for the verification SHA +- Any repository-specific validation required for the changed area + +Build and test evidence may come from CI (item D) rather than a local run, provided it +is bound to the verification SHA. A local run at a different SHA does not satisfy this. + +### D. CI + +- The CI result that belongs to the **exact** verification SHA +- **CI HEAD SHA == PR HEAD SHA** — CONFIRMED, not assumed +- All required checks completed (none pending, queued, or in progress) +- All required checks concluded successfully + +A CI result for any other commit is stale. Stale CI is UNVERIFIED and blocks. + +### E. Reviews + +- Effective third-party approvals, computed per "Approval Semantics" below +- The required approval count in force +- No blocking review state outstanding + +### F. Mergeability and repository policy + +- No merge conflicts with the base branch +- Repository merge state reported by the host +- **Whether the repository requires approving reviews** on the base branch (branch + protection or ruleset), and how many. This determines which approval source is + permitted — it is not optional context +- Any other required repository policy checks satisfied +- The configured merge method is one the repository actually allows + +If the repository reports **no** branch protection and **no** applicable ruleset, that is +a CONFIRMED finding of "no third-party review required" — record it explicitly as such. +If the policy cannot be read at all, it is **UNVERIFIED → MERGE BLOCKED**; absence of +evidence is not evidence of absence. + +### G. Human approval + +- Explicit human approval to execute the merge of this specific PR at this specific SHA, + from one of the two sources in "Approval Semantics", with the source named in the report + +## Approval Semantics + +The human approval gate may be satisfied by exactly one of two sources. Which source +applies is determined by repository policy and PR authorship — never by preference, +convenience, or configuration. + +| Source | When it applies | +|---|---| +| **1. GitHub review approval** | The normal path: a third-party reviewer submits an `APPROVED` review. | +| **2. Explicit out-of-band human approval** | Only for a **self-authored PR** in a repository whose policy does **not** require third-party review. | + +**Repository policy always wins.** Determine, from a trusted source, whether branch +protection or a repository ruleset requires approving reviews on the base branch: + +- If the repository requires N approving reviews → that requirement is authoritative. + Source 1 is the only acceptable path, and N GitHub `APPROVED` reviews are required. + **Out-of-band approval can never substitute for, bypass, or reduce it.** +- If that requirement cannot be determined → **UNVERIFIED → MERGE BLOCKED**. Never + assume a repository is unprotected. + +**Never fabricate a review record.** A self-authored PR must not be recorded, reported, +or counted as carrying a GitHub `APPROVED` review by its own author. GitHub does not +permit author self-approval; claiming one is falsifying evidence. When source 2 applies, +report it explicitly as out-of-band approval, and report the GitHub approval count as the +true value (typically 0). + +### Source 1 — GitHub review approval + +This is a contract, not an implementation. Any source that can answer these questions is +acceptable, provided it can report, per review: the reviewer identity, whether the +reviewer is a human or a bot, the review state, the review's submission time, and the +commit the review was submitted against. + +**A review counts as an effective human approval only when all hold:** + +- The reviewer is a **human**, not a bot. +- The review state is **APPROVED**. +- It is that reviewer's **latest effective review**. +- The review was submitted against a commit equal to the **current PR HEAD**. + +**Determining a reviewer's latest effective state:** + +- Only `APPROVED`, `CHANGES_REQUESTED`, and `DISMISSED` change a reviewer's state. +- `COMMENTED` and `PENDING` reviews never change it. +- Each reviewer contributes **at most one** state: their most recent state-changing review. + +**Never counted as an approval:** + +| Case | Result | +|---|---| +| Bot review (any state) | not an approval | +| `COMMENTED` / `PENDING` | not an approval | +| Review that was dismissed | not an approval | +| Reviewer approved, then later requested changes | not an approval — and blocking | +| Approval submitted against an older commit (stale HEAD) | not an approval | +| Reviewer identity, timestamp, or reviewed commit cannot be determined | UNVERIFIED → BLOCKED | + +**Bot identification.** Treat a reviewer as a bot when the host reports the account as a +bot type, when the login carries a bot marker such as a `[bot]` suffix, or when the login +is a known automation account for this repository (for example the code-review bot). +Automated review tooling never contributes a human approval, regardless of verdict. + +**Outcomes:** + +- Effective third-party approvals ≥ `requiredApprovals`, and no blocking review → gate CONFIRMED. +- Effective third-party approvals < `requiredApprovals` → **MERGE BLOCKED**, unless source 2 applies. +- Any reviewer's latest effective state is `CHANGES_REQUESTED` → **MERGE BLOCKED**. + A blocking review blocks under **both** sources; out-of-band approval never overrides it. +- Review data cannot be obtained or is incomplete → **UNVERIFIED → MERGE BLOCKED**. + +### Source 2 — Explicit out-of-band human approval (self-authored PRs) + +A single maintainer cannot approve their own pull request on GitHub. Requiring a GitHub +`APPROVED` review in that situation would make the gate permanently unsatisfiable, which +is a broken gate, not a safe one. This source exists for exactly that case. + +**Out-of-band approval does not mean "approval is not required".** It means the approval +is recorded here rather than as a GitHub review, under stricter conditions. + +**All of the following must hold:** + +- [ ] The PR is **self-authored** — the approver is the PR author +- [ ] Repository policy does **not** require third-party approving reviews (determined, + not assumed) +- [ ] No reviewer has an outstanding `CHANGES_REQUESTED` +- [ ] Every technical gate (A–F) is CONFIRMED for the verification SHA +- [ ] An explicit approval record exists, containing all of: + - PR number + - **Exact PR HEAD SHA** being approved + - An explicit statement approving the merge (not general praise, not "looks good", + not silence) + - Approver identity + - Approval timestamp and context + +If any box is unchecked → **MERGE BLOCKED**. + +**HEAD binding is absolute here.** The approval is valid for the named SHA and nothing +else. If the PR HEAD changes for any reason, the out-of-band approval is **invalidated** +and a fresh explicit approval for the new SHA is required. An approval for an earlier SHA +is never carried forward. + +Approval is never inferred from a passing build, from elapsed time, from a comment that +reads as positive, from the absence of objection, or from the fact that the same person +wrote the code. + +## HEAD Binding + +Every gate is bound to one SHA — the PR HEAD observed at the start of verification. + +- Record the verification SHA explicitly, and report it in every result. +- CI evidence, review evidence, and build/test evidence must each belong to that SHA. +- If the PR HEAD changes at any point during verification, the run is invalid. + Report **BLOCKED — PR HEAD changed during verification** and start over. +- A new push to the PR invalidates all prior evidence, including prior approvals. + +## Merge Workflow + +```text +VERIFY PR IDENTITY + ↓ +VERIFY CURRENT HEAD + ↓ +VERIFY GIT STATE + ↓ +VERIFY BUILD / TEST + ↓ +VERIFY CI FOR EXACT HEAD + ↓ +VERIFY EFFECTIVE HUMAN REVIEWS + ↓ +VERIFY MERGEABILITY + ↓ +PRODUCE MERGE CANDIDATE REPORT + ↓ +HUMAN REVIEW + ↓ +EXPLICIT HUMAN APPROVAL + ↓ +MERGE EXECUTION + ↓ +POST-MERGE VERIFICATION +``` + +**Technical verification success is not permission to merge.** Passing every gate +through "VERIFY MERGEABILITY" produces a **MERGE CANDIDATE** and nothing more. The +transition to MERGE EXECUTION is authorised only by an explicit human decision. + +The skill's default mode is verification only: it reads state, changes nothing, pushes +nothing, and is safe to run at any time. + +## Merge Execution + +No shell-specific command is prescribed. Choose the mechanism from the trusted sources +available, honouring the repository's merge policy and the configured merge method. + +**The configured `mergeMethod` must be a method the repository actually allows.** Read +the repository's enabled merge methods from a trusted source and compare. A configured +method that the repository does not permit, or that the host cannot execute, is a +**CONFIGURATION ERROR → MERGE BLOCKED** — not UNVERIFIED, and never silently substituted +for a different method. Never pick a method the configuration did not specify. + +**Prefer a mechanism that lets you state the expected HEAD**, so the host itself refuses +the merge if the PR moved. Where the host supports it, pass the expected SHA rather than +merging whatever is current. + +**Immediately before executing the merge, re-confirm all of:** + +- [ ] Explicit human approval exists for this PR at this SHA +- [ ] PR HEAD unchanged since verification +- [ ] CI still valid and successful for the current HEAD +- [ ] Effective human approvals still satisfy the required count +- [ ] No blocking review state has appeared +- [ ] Mergeability unchanged; no conflicts +- [ ] Base branch has not moved in a way that invalidates the verification + +If any of these cannot be re-confirmed: **BLOCKED**. Do not merge. Return to VERIFY. + +Never bypass branch protection, never force-push, never push directly to the base +branch, and never enable auto-merge to satisfy a gate. + +## Post-Merge Verification + +Required evidence, each CONFIRMED: + +- PR state is `MERGED` +- The actual merge commit is identified +- The base branch contains the expected result +- Base branch HEAD and state verified after the merge +- Post-merge CI result, where the repository requires one +- Linked issue state updated as expected +- Branch cleanup eligibility determined + +Anything not established here is **UNVERIFIED**. Report it as such — a completed merge +does not retroactively confirm what was never checked. + +## Failure Behaviour + +| Situation | Result | +|---|---| +| Any required evidence UNVERIFIED | **MERGE BLOCKED** | +| Any gate item only INFERRED | **MERGE BLOCKED** | +| CI failed, pending, queued, or in progress | **MERGE BLOCKED** | +| CI belongs to a different SHA than PR HEAD | **MERGE BLOCKED** (stale) | +| Third-party approvals below `requiredApprovals`, and source 2 does not apply | **MERGE BLOCKED** | +| Any `CHANGES_REQUESTED` outstanding (under either approval source) | **MERGE BLOCKED** | +| Repository requires approving reviews, and they are absent | **MERGE BLOCKED** — out-of-band cannot substitute | +| Repository review requirement cannot be determined | **UNVERIFIED → MERGE BLOCKED** | +| Out-of-band approval named a different SHA than the verification SHA | **MERGE BLOCKED** — re-approval required | +| Out-of-band approval claimed for a PR the approver did not author | **MERGE BLOCKED** | +| `mergeMethod` invalid, or not enabled in repository settings | **CONFIG ERROR → MERGE BLOCKED** | +| Merge conflict, or mergeability unknown | **MERGE BLOCKED** | +| Working tree dirty at local verification | **MERGE BLOCKED** | +| PR HEAD changed mid-verification | **BLOCKED**, restart verification | +| Configuration missing, malformed, or invalid | **CONFIG ERROR → MERGE BLOCKED** | +| Configuration attempts to weaken fixed safety policy | **CONFIG ERROR → MERGE BLOCKED** | +| No explicit human approval | **MERGE BLOCKED** | +| No trusted source can establish a required fact | **UNVERIFIED → MERGE BLOCKED** | + +There is no configuration, flag, or argument that converts any of these into a pass. + +## Configuration + +`.kiro/merge.config.json` carries **data only**. All behaviour is defined in this +document. Configuration can make the gate *stricter*, never weaker. + +Schema: + +| Key | Type | Meaning | +|---|---|---| +| `requiredApprovals` | integer ≥ 1 | Number of **third-party** GitHub `APPROVED` reviews required (source 1). Must be at least 1; there is no way to require zero. It does **not** count the PR author, and it is not a switch for source 2. | +| `mergeMethod` | `"merge"` \| `"squash"` \| `"rebase"` | Merge method to use during MERGE EXECUTION. These are the only methods GitHub can execute for a pull request. | +| `deleteBranchAfterMerge` | boolean | Whether the PR branch is eligible for deletion after a confirmed merge. | + +Rules: + +- Missing file, malformed JSON, an unknown key, a key of the wrong type, or + `requiredApprovals < 1` → **CONFIG ERROR → MERGE BLOCKED**. There is no default + fallback for `requiredApprovals`. +- `mergeMethod` outside the three values above → **CONFIG ERROR → MERGE BLOCKED**. + `ff-only` is **not** a valid value: GitHub's pull request merge offers only merge, + squash, and rebase, so a fast-forward-only method cannot be executed through it. +- `mergeMethod` not enabled in the repository's settings → **CONFIG ERROR → MERGE BLOCKED**. +- Anything not in the table above is not configurable. Human approval, fail-closed + behaviour, HEAD binding, repository-policy precedence, the conditions under which + out-of-band approval is permitted, and auto-merge being disabled are all fixed policy, + deliberately absent from the schema so they cannot be switched off or loosened. + +## Report Format + +Report the verification SHA, then each evidence group with its classification, then the +verdict. See `../EXAMPLE-REPORT.md` for a worked example. + +The verdict is exactly one of: + +- **MERGE CANDIDATE** — every gate CONFIRMED; awaiting human review and explicit approval +- **MERGE BLOCKED** — at least one gate failed, INFERRED, or UNVERIFIED +- **MERGED** — merge executed after explicit approval, with post-merge verification result + +Never report "safe to merge" or "ready to merge" as a substitute for MERGE CANDIDATE; +those phrasings read as authorisation, which this skill cannot grant. + +## Related + +- `../batch-skill/SKILL.md` — batch orchestration and parallel safety +- `../WORKFLOW.md` — end-to-end workflow from issue to merged PR +- `../EXAMPLE-REPORT.md` — reporting example +- Issue #18 — Batch and Merge Skills +- Issue #6 — PureSharp v1.0.0 roadmap diff --git a/.gitignore b/.gitignore index 6dcf0dc..282577f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,5 +17,9 @@ obj/ *.tmp *.temp +# Ignore Claude Code and build output +.omc/ +nupkg-output/ + # Ignore NuGet package cache (if applicable) # .nuget/ diff --git a/.kiro/batch.config.json b/.kiro/batch.config.json new file mode 100644 index 0000000..37e5c8f --- /dev/null +++ b/.kiro/batch.config.json @@ -0,0 +1,4 @@ +{ + "$description": "PureSharp Batch Skill configuration. DATA ONLY. All batch behaviour and all safety policy are defined in .claude/skills/batch-skill/SKILL.md, which is the SSOT. maxParallelTasks is a ceiling, not a licence: it can only lower concurrency, never authorise parallelism that the CONFIRMED-only evidence bar has not already permitted. An unknown key, a wrong type, or maxParallelTasks < 1 is a CONFIG ERROR and blocks the batch. The v1.0 roadmap and its phases live in GitHub Issue #6, not here.", + "maxParallelTasks": 2 +} diff --git a/.kiro/merge.config.json b/.kiro/merge.config.json new file mode 100644 index 0000000..63824b5 --- /dev/null +++ b/.kiro/merge.config.json @@ -0,0 +1,6 @@ +{ + "$description": "PureSharp Merge Skill configuration. DATA ONLY. All merge behaviour and all safety policy are defined in .claude/skills/merge-skill/SKILL.md, which is the SSOT. requiredApprovals is the number of THIRD-PARTY GitHub APPROVED reviews required; it never counts the PR author and is not a switch for out-of-band approval. mergeMethod must be one of merge/squash/rebase (the only methods GitHub can execute for a pull request) and must be enabled in the repository settings. Everything else (explicit human approval, fail-closed gating, HEAD binding, repository-policy precedence, the conditions permitting out-of-band approval, auto-merge disabled) is fixed policy and is deliberately absent so it cannot be switched off. An unknown key, a wrong type, requiredApprovals < 1, or an invalid/unavailable mergeMethod is a CONFIG ERROR and blocks the merge.", + "requiredApprovals": 1, + "mergeMethod": "merge", + "deleteBranchAfterMerge": true +}