feat: add READY_FOR_DELIVERY architecture gate #4
@@ -0,0 +1,17 @@
|
||||
name: Validate skill
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Run policy tests
|
||||
run: python3 -m unittest discover -s tests -v
|
||||
- name: Validate whitespace
|
||||
run: git diff --check HEAD^ HEAD
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: corp-v1-channel-architecture
|
||||
description: "Use when operating or synchronizing a Corp v1 project's architecture channel. Maintains C4-based architecture documentation, Draw.io diagrams, architecture decisions, and requirements while correlating verified activity across the project's seven channels."
|
||||
version: 1.7.0
|
||||
version: 1.8.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
metadata:
|
||||
@@ -229,9 +229,22 @@ Use canonical Task IDs `TASK-<ZERO_PADDED_NUMBER>` and separate project-scoped d
|
||||
|
||||
Maintain a version allocation registry linking Features to intended versions. Record target version, rationale, dependencies, readiness constraints, status, and human decision evidence. Hermes may analyze and propose allocation; the team decides which Feature goes into which version. Do not invent version assignments or treat a proposal as final.
|
||||
|
||||
## Delivery Readiness State
|
||||
|
||||
Architecture uses the task flow `IN_DESIGN → READY_FOR_DELIVERY → IN_PROGRESS`. `READY_FOR_DELIVERY` is a fail-closed, pre-execution readiness state: Architecture may emit it for an exact Task only when all of the following evidence is durable and linked to that Task:
|
||||
|
||||
1. an exact item-specific `Approved for Implementation` decision from a human team member;
|
||||
2. complete task inputs, including implementation artifacts, concrete inputs and outputs, failure boundaries, exclusions, verification steps, and future acceptance-evidence requirements;
|
||||
3. evidence that all entry dependencies are satisfied; and
|
||||
4. for a Task that affects the user interface or user experience, exact approved UI/UX implementation-handoff evidence; otherwise the readiness record explicitly records UI/UX as not applicable with a rationale.
|
||||
|
||||
`READY_FOR_DELIVERY` does not mean Focus admission, assignment, claim, implementation start, `delivery_started`, or `IN_PROGRESS`. Architecture records the satisfied gate and sends a handoff to Kanban for a separate exact-task Focus-admission decision; only the authorized delivery-flow owner may subsequently record `IN_PROGRESS` when implementation actually starts.
|
||||
|
||||
Scope owns the canonical Task lifecycle schema. Architecture must not silently mutate or outrun Scope-owned canonical lifecycle schema: when the schema cannot represent `READY_FOR_DELIVERY`, return the handoff to Scope for canonicalization and keep the Task in its prior state. Never infer this state from solution-package completeness, UI/UX discussion, dependency expectations, CI success, or implementation activity.
|
||||
|
||||
## Kanban Handoff
|
||||
|
||||
After human Feature implementation approval, Architecture sends dependency-ready task records to Kanban. Architecture does not place tasks into Focus `InBacklog`; Kanban records the separate human task-admission decision. Keep task dependencies and readiness evidence current when Kanban or Delivery reports drift.
|
||||
After human Feature implementation approval, Architecture applies the `READY_FOR_DELIVERY` gate to each exact Task and sends only qualifying task records to Kanban. Architecture does not place tasks into Focus `InBacklog`; Kanban records the separate human task-admission decision. Keep task dependencies and readiness evidence current when Kanban or Delivery reports drift.
|
||||
|
||||
## Proactive Iteration Requirement
|
||||
|
||||
@@ -291,6 +304,7 @@ Requires team approval for:
|
||||
14. Publishing static diagram exports without onboarding the editable `.drawio` source into Docusaurus.
|
||||
15. Reintroducing Architecture Feature pages or task reader navigation instead of linking canonical Scope pages.
|
||||
16. Renaming task display IDs by rewriting historic canonical identities, evidence, or append-only hashes.
|
||||
17. Treating `READY_FOR_DELIVERY` as automatic Focus admission or `IN_PROGRESS`, or emitting it without exact implementation approval, complete task inputs, satisfied entry dependencies, and applicable approved UI/UX handoff evidence.
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
@@ -311,7 +325,8 @@ Requires team approval for:
|
||||
- [ ] Every Feature allocated to the planned release has a reviewed, non-placeholder Task breakdown covering every acceptance outcome and applicable requirement, with acyclic within-Feature and cross-Feature dependencies.
|
||||
- [ ] Task display IDs use `<UPPERCASE_PROJECT_CODE>-TS-<NUMBER>` without rewriting historic canonical identities, evidence, or append-only hashes.
|
||||
- [ ] Only a human team member moved a Feature to `Approved for Implementation` or finalized its version.
|
||||
- [ ] Tasks were proposed to Kanban with readiness/dependency evidence; Architecture did not self-admit them to Focus `InBacklog`.
|
||||
- [ ] Every emitted `READY_FOR_DELIVERY` Task has exact implementation approval, complete task inputs, satisfied entry dependencies, and applicable approved UI/UX handoff evidence (or an explicit not-applicable rationale).
|
||||
- [ ] `READY_FOR_DELIVERY` remained distinct from Focus admission, assignment, claim, `delivery_started`, and `IN_PROGRESS`; Architecture did not self-admit Tasks to Focus `InBacklog`.
|
||||
- [ ] At least one useful solution artifact was improved, or the exact human approval/clarification gate was documented.
|
||||
- [ ] Proposed items remain visibly proposed.
|
||||
- [ ] Documentation and diagram checks passed.
|
||||
|
||||
@@ -11,6 +11,11 @@ def task_section(skill: str) -> str:
|
||||
return operative.split("## Task and Dependency Breakdown", 1)[1].split("## Version Allocation", 1)[0]
|
||||
|
||||
|
||||
def readiness_section(skill: str) -> str:
|
||||
operative = COMMENT.sub("", skill)
|
||||
return operative.split("## Delivery Readiness State", 1)[1].split("## Kanban Handoff", 1)[0]
|
||||
|
||||
|
||||
def policy_failures(section: str, approval_rule: str) -> list[str]:
|
||||
section = COMMENT.sub("", section)
|
||||
patterns = {
|
||||
@@ -28,6 +33,22 @@ def policy_failures(section: str, approval_rule: str) -> list[str]:
|
||||
return [name for name, pattern in patterns.items() if re.search(pattern, section) is None]
|
||||
|
||||
|
||||
def readiness_failures(section: str) -> list[str]:
|
||||
patterns = {
|
||||
"sequence": r"`IN_DESIGN → READY_FOR_DELIVERY → IN_PROGRESS`",
|
||||
"implementation-approval": r"exact item-specific `Approved for Implementation`",
|
||||
"complete-inputs": r"complete task inputs",
|
||||
"entry-dependencies": r"all entry dependencies are satisfied",
|
||||
"ui-ux-evidence": r"approved UI/UX implementation-handoff evidence",
|
||||
"ui-ux-not-applicable": r"explicitly records UI/UX as not applicable",
|
||||
"not-execution": r"does not mean Focus admission, assignment, claim, implementation start, `delivery_started`, or `IN_PROGRESS`",
|
||||
"kanban-admission": r"handoff to Kanban for a separate exact-task Focus-admission decision",
|
||||
"scope-schema": r"must not silently mutate or outrun Scope-owned canonical lifecycle schema",
|
||||
"scope-fallback": r"return the handoff to Scope for canonicalization and keep the Task in its prior state",
|
||||
}
|
||||
return [name for name, pattern in patterns.items() if re.search(pattern, section) is None]
|
||||
|
||||
|
||||
class TaskBreakdownPolicyTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -38,7 +59,7 @@ class TaskBreakdownPolicyTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_operational_policy_is_complete_and_structured(self):
|
||||
self.assertIn("version: 1.7.0", self.skill)
|
||||
self.assertIn("version: 1.8.0", self.skill)
|
||||
self.assertEqual(policy_failures(self.task_section, self.approval_rule), [])
|
||||
|
||||
def test_comments_and_weakened_rules_cannot_satisfy_policy(self):
|
||||
@@ -57,6 +78,28 @@ class TaskBreakdownPolicyTest(unittest.TestCase):
|
||||
with self.subTest(name=name):
|
||||
self.assertTrue(policy_failures(self.task_section.replace(old, new), self.approval_rule))
|
||||
|
||||
def test_ready_for_delivery_is_a_fail_closed_pre_execution_state(self):
|
||||
section = readiness_section(self.skill)
|
||||
self.assertEqual(readiness_failures(section), [])
|
||||
|
||||
def test_ready_for_delivery_gate_cannot_be_weakened(self):
|
||||
section = readiness_section(self.skill)
|
||||
mutations = [
|
||||
("exact item-specific `Approved for Implementation`", "implementation is expected"),
|
||||
("complete task inputs", "partial task inputs"),
|
||||
("all entry dependencies are satisfied", "entry dependencies are expected to be satisfied"),
|
||||
("approved UI/UX implementation-handoff evidence", "a UI/UX discussion"),
|
||||
("explicitly records UI/UX as not applicable with a rationale", "assumes UI/UX is not applicable"),
|
||||
("separate exact-task Focus-admission decision", "automatic Focus admission"),
|
||||
("does not mean Focus admission", "means Focus admission"),
|
||||
("return the handoff to Scope for canonicalization and keep the Task in its prior state", "continue with a local readiness state"),
|
||||
]
|
||||
for old, new in mutations:
|
||||
with self.subTest(old=old):
|
||||
changed = section.replace(old, new)
|
||||
self.assertNotEqual(changed, section)
|
||||
self.assertTrue(readiness_failures(changed))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user