@surlymochan/evalid 0.0.0-stage → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/LICENSE +21 -0
- package/README.md +315 -2
- package/RELEASE_NOTES.md +102 -0
- package/atoms/registry.json +758 -0
- package/bin/xflow.js +7208 -0
- package/docs/adoption/README.md +128 -0
- package/docs/adoption/openflow-release-hardening.md +61 -0
- package/docs/benchmark-openflow-vs-gstack-superpowers-openspec-2026-05-25.md +81 -0
- package/docs/compatibility.md +52 -0
- package/docs/competitive-benchmark.md +108 -0
- package/docs/corps-operator-guide.md +75 -0
- package/docs/demo-proof.md +126 -0
- package/docs/examples-gallery.md +115 -0
- package/docs/fixtures/tracker-item.json +7 -0
- package/docs/goal-vs-codex.md +129 -0
- package/docs/gstack-comparison.md +88 -0
- package/docs/install-upgrade.md +133 -0
- package/docs/integrations.md +49 -0
- package/docs/launch-demo.md +123 -0
- package/docs/launch-dossier.md +180 -0
- package/docs/methodology.md +149 -0
- package/docs/npm-publish-handoff.md +83 -0
- package/docs/openspec-migration.md +106 -0
- package/docs/public-benchmark.md +68 -0
- package/docs/public-release.md +145 -0
- package/docs/quality-assessment.md +139 -0
- package/docs/quickstart.md +156 -0
- package/docs/reviewer-guide.md +43 -0
- package/docs/spec-kit-benchmark.md +73 -0
- package/docs/super-assistant-comparison.md +106 -0
- package/docs/superpowers-comparison.md +82 -0
- package/docs/team-adoption.md +123 -0
- package/docs/tooling-matrix.md +91 -0
- package/docs/walkthrough.md +76 -0
- package/docs/workflow-manual.md +1125 -0
- package/package.json +83 -4
- package/prompts/pencil-draft.md +46 -0
- package/prompts/pencil-refine.md +46 -0
- package/prompts/phase-artifact.md +24 -0
- package/prompts/phase-execution.md +32 -0
- package/schemas/competitor-reconstruction-contract.schema.json +91 -0
- package/schemas/llm-design-review-aggregate.schema.json +83 -0
- package/schemas/visual-benchmark.schema.json +978 -0
- package/schemas/workflow.schema.json +100 -0
- package/scripts/run-tests.mjs +23 -0
- package/scripts/takein_digest.py +139 -0
- package/specs/README.md +118 -0
- package/specs/architecture.md +36 -0
- package/specs/product.md +33 -0
- package/specs/workflow.md +349 -0
- package/src/agent_team/atoms/codex-app-bridge.js +8 -0
- package/src/agent_team/atoms/design/competitor-reconstruction-review.js +44 -0
- package/src/agent_team/atoms/design/contract-freeze.js +8 -0
- package/src/agent_team/atoms/design/generation-contract.js +442 -0
- package/src/agent_team/atoms/design/reconstruction-pack.js +246 -0
- package/src/agent_team/atoms/design/reference-surface-lock.js +49 -0
- package/src/agent_team/atoms/patch-challenge.js +19 -0
- package/src/agent_team/atoms/pencil/accept.js +9 -0
- package/src/agent_team/atoms/pencil/draft.js +365 -0
- package/src/agent_team/atoms/pencil/refine.js +229 -0
- package/src/agent_team/atoms/phase-run-dispatch.js +8 -0
- package/src/agent_team/atoms/team-run.js +380 -0
- package/src/agent_team/atoms/visual/aesthetic-review.js +231 -0
- package/src/agent_team/atoms/visual/benchmark-repair-plan.js +291 -0
- package/src/agent_team/atoms/visual/benchmark.js +1652 -0
- package/src/agent_team/atoms/visual/design-selection.js +23 -0
- package/src/agent_team/atoms/visual/direction-synthesis.js +124 -0
- package/src/agent_team/atoms/visual/dom-rect-export.js +129 -0
- package/src/agent_team/atoms/visual/image-diff.js +186 -0
- package/src/agent_team/atoms/visual/layout-competition.js +8 -0
- package/src/agent_team/atoms/visual/page-evidence-capture.js +806 -0
- package/src/agent_team/atoms/visual/playwright-runtime.js +8 -0
- package/src/agent_team/atoms/visual/review-aggregate.js +87 -0
- package/src/agent_team/atoms/visual/review.js +77 -0
- package/src/agent_team/atoms/visual/visual-report.js +197 -0
- package/src/agent_team/atoms/visual/visual-token-export.js +417 -0
- package/src/agent_team/common.js +311 -0
- package/src/core/atoms/agent-invoke.js +684 -0
- package/src/core/atoms/event/ingest.js +30 -0
- package/src/core/atoms/experience/digest.js +55 -0
- package/src/core/atoms/gate/artifact-verify.js +83 -0
- package/src/core/atoms/gate/competitor-contract-validate.js +119 -0
- package/src/core/atoms/gate/evidence-collect.js +64 -0
- package/src/core/atoms/gate/payload-from-phase-run.js +78 -0
- package/src/core/atoms/gate/visual-benchmark-validate.js +183 -0
- package/src/core/atoms/gate/workbench.js +79 -0
- package/src/core/atoms/intake/classify.js +15 -0
- package/src/core/atoms/intake/design-skill-select.js +16 -0
- package/src/core/atoms/intake/preview-or-refine.js +19 -0
- package/src/core/atoms/intake/recommend.js +20 -0
- package/src/core/atoms/intake/research-same-category.js +19 -0
- package/src/core/atoms/intervention/create.js +30 -0
- package/src/core/atoms/memory/manage.js +27 -0
- package/src/core/atoms/memory/mount.js +13 -0
- package/src/core/atoms/mission/create.js +19 -0
- package/src/core/atoms/mission/list.js +14 -0
- package/src/core/atoms/mission/show.js +26 -0
- package/src/core/atoms/notify/checkpoint.js +46 -0
- package/src/core/atoms/phase-run/complete.js +42 -0
- package/src/core/atoms/phase-run/fail.js +40 -0
- package/src/core/atoms/phase-run/persist.js +39 -0
- package/src/core/atoms/phase-run/start.js +30 -0
- package/src/core/atoms/plugin/run.js +76 -0
- package/src/core/atoms/policy/gate.js +90 -0
- package/src/core/atoms/policy/resolve.js +11 -0
- package/src/core/atoms/storage/sync.js +57 -0
- package/src/core/atoms/workflow/advance.js +25 -0
- package/src/core/atoms/workflow/guard.js +127 -0
- package/src/core/atoms/workflow/state-load.js +37 -0
- package/src/core/bindings.js +37 -0
- package/src/core/change-artifacts.js +134 -0
- package/src/core/competitive-score.js +265 -0
- package/src/core/concurrency-policy.js +35 -0
- package/src/core/execution-log.js +108 -0
- package/src/core/intake-recommendation.js +134 -0
- package/src/core/memory-state.js +62 -0
- package/src/core/mission-state.js +780 -0
- package/src/core/pending-gates.js +66 -0
- package/src/core/phase-cost.js +116 -0
- package/src/core/phase-run-read.js +27 -0
- package/src/core/policy-overlay.js +180 -0
- package/src/core/state-store.js +201 -0
- package/src/core/workflow-executor.js +998 -0
- package/src/core/workflow-integrity.js +111 -0
- package/src/core/workflow-loader.js +163 -0
- package/src/core/workflow-rerun.js +84 -0
- package/src/core/workflow-state.js +119 -0
- package/src/server.js +1307 -0
- package/workflows/corps.yaml +479 -0
- package/workflows/yolo.yaml +233 -0
- package/xflow/README.md +76 -0
- package/xflow/aha/SKILL.md +82 -0
- package/xflow/aha/scripts/append_aha.py +50 -0
- package/xflow/archive/scripts/archive_change.py +338 -0
- package/xflow/archive/templates/merge-design.md +54 -0
- package/xflow/archive/templates/merge-workflow.md +26 -0
- package/xflow/atoms/__init__.py +6 -0
- package/xflow/atoms/a1_issue_create_or_patch.py +70 -0
- package/xflow/atoms/a2_branch_create_and_link.py +42 -0
- package/xflow/atoms/a3_repo_doctor.py +11 -0
- package/xflow/atoms/a4_project_set_status.py +11 -0
- package/xflow/atoms/a5_archive_commit_push_close.py +11 -0
- package/xflow/atoms/a6_pr_create.py +72 -0
- package/xflow/atoms/b1_change_scaffold.py +11 -0
- package/xflow/atoms/b2_status_read.py +16 -0
- package/xflow/atoms/b2b_status_write.py +20 -0
- package/xflow/atoms/b3_status_transition.py +27 -0
- package/xflow/atoms/b4_handoff_scaffold_or_refresh.py +11 -0
- package/xflow/atoms/b5_aha_append.py +11 -0
- package/xflow/atoms/b6_takein_digest.py +11 -0
- package/xflow/atoms/b6b_lookback_digest.py +11 -0
- package/xflow/atoms/b7_change_mission_bind.py +43 -0
- package/xflow/atoms/c1_mem.py +54 -0
- package/xflow/atoms/e6_gate_local_precheck.py +23 -0
- package/xflow/atoms/h1_design_lite_gate.py +74 -0
- package/xflow/atoms/i6a_tdd_run.py +104 -0
- package/xflow/atoms/i6b_tdd_proof_validate.py +165 -0
- package/xflow/atoms/i6c_tdd_quality_review.py +357 -0
- package/xflow/atoms/j1_tests_run.py +129 -0
- package/xflow/atoms/j4a_spec_consistency_structural.py +105 -0
- package/xflow/atoms/j4b_spec_delta_review.py +316 -0
- package/xflow/atoms/j4c_openspec_migration_map.py +121 -0
- package/xflow/atoms/j4d_spec_clarify_gate.py +373 -0
- package/xflow/atoms/j6_cr_review.py +443 -0
- package/xflow/atoms/k1_artifacts_complete_check.py +39 -0
- package/xflow/atoms/k2_merge_snippets_apply.py +11 -0
- package/xflow/atoms/k3_handoff_refresh.py +14 -0
- package/xflow/atoms/k4_mem_lesson_persist.py +65 -0
- package/xflow/atoms/k5_archive_publish.py +21 -0
- package/xflow/atoms/k6_aha_merge.py +42 -0
- package/xflow/atoms/tdd_lib.py +747 -0
- package/xflow/corps/SKILL.md +109 -0
- package/xflow/exec/scripts/set_issue_in_progress.py +159 -0
- package/xflow/goal/SKILL.md +150 -0
- package/xflow/handoff/SKILL.md +95 -0
- package/xflow/handoff/scripts/scaffold_handoff.py +304 -0
- package/xflow/lookback/SKILL.md +66 -0
- package/xflow/lookback/scripts/lookback_digest.py +46 -0
- package/xflow/openissue/scripts/open_issue_flow.py +438 -0
- package/xflow/plan/SKILL.md +38 -0
- package/xflow/ralph/SKILL.md +123 -0
- package/xflow/scripts/check_installed_xflow_skill_sync.sh +44 -0
- package/xflow/scripts/common.py +480 -0
- package/xflow/scripts/doctor.py +278 -0
- package/xflow/scripts/sync_installed_xflow_skill.sh +134 -0
- package/xflow/takein/SKILL.md +81 -0
- package/xflow/takein/scripts/takein_digest.py +88 -0
- package/xflow/yolo/SKILL.md +66 -0
- package/xflow/yolo/scripts/scaffold_specs_change.py +673 -0
- package/xflow/yolo/scripts/yolo_gate.py +312 -0
- package/xflow/yolo/templates/DESIGN.md +179 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import argparse
|
|
3
|
+
import json
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
sys.path.append(str(Path(__file__).resolve().parents[2] / "scripts"))
|
|
9
|
+
|
|
10
|
+
from common import assert_stage_transition_allowed, assert_status_transition_allowed, load_status # noqa: E402
|
|
11
|
+
from doctor import run_doctor_checks # noqa: E402
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
BASE_ARTIFACTS = ("proposal.md", "plan.md", "tasks.md", "status.json")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def check(name: str, ok: bool, detail: str, *, severity: str = "error", value: Any | None = None) -> dict[str, Any]:
|
|
18
|
+
payload: dict[str, Any] = {
|
|
19
|
+
"name": name,
|
|
20
|
+
"ok": ok,
|
|
21
|
+
"detail": detail,
|
|
22
|
+
"severity": severity,
|
|
23
|
+
}
|
|
24
|
+
if value is not None:
|
|
25
|
+
payload["value"] = value
|
|
26
|
+
return payload
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def parse_args() -> argparse.Namespace:
|
|
30
|
+
parser = argparse.ArgumentParser(
|
|
31
|
+
description="Run deterministic Superflow Yolo gate checks before entering the next workflow phase.",
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument("--project-root", default=".", help="Project root containing specs/changes.")
|
|
34
|
+
parser.add_argument("--change-id", required=True, help="Superflow change id.")
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"--phase",
|
|
37
|
+
required=True,
|
|
38
|
+
choices=["pre-openissue", "post-openissue", "pre-exec", "pre-archive"],
|
|
39
|
+
help="Named Yolo gate to validate.",
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument("--json", action="store_true", help="Print machine-readable JSON output.")
|
|
42
|
+
return parser.parse_args()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def run_yolo_gate(project_root: str | Path, change_id: str, phase: str) -> dict[str, Any]:
|
|
46
|
+
status_path, status = load_status(project_root, change_id)
|
|
47
|
+
project_root_path = Path(project_root).expanduser().resolve()
|
|
48
|
+
change_root = project_root_path / "specs" / "changes" / change_id
|
|
49
|
+
change_type = status.get("change_type", "backend")
|
|
50
|
+
issue_doc_path = change_root / "issue.md"
|
|
51
|
+
checks: list[dict[str, Any]] = []
|
|
52
|
+
|
|
53
|
+
checks.append(
|
|
54
|
+
check(
|
|
55
|
+
"status-file",
|
|
56
|
+
status_path.exists(),
|
|
57
|
+
f"Loaded status file {status_path}" if status_path.exists() else f"Missing status file {status_path}",
|
|
58
|
+
value=str(status_path),
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
for artifact in BASE_ARTIFACTS:
|
|
63
|
+
artifact_path = change_root / artifact
|
|
64
|
+
checks.append(
|
|
65
|
+
check(
|
|
66
|
+
f"artifact-{artifact}",
|
|
67
|
+
artifact_path.exists(),
|
|
68
|
+
f"Found {artifact}" if artifact_path.exists() else f"Missing required artifact {artifact}",
|
|
69
|
+
value=str(artifact_path),
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
checks.append(
|
|
74
|
+
check(
|
|
75
|
+
"artifact-issue-md",
|
|
76
|
+
issue_doc_path.exists(),
|
|
77
|
+
"Found issue.md" if issue_doc_path.exists() else "Missing required issue.md",
|
|
78
|
+
value=str(issue_doc_path),
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
needs_design = change_type in {"frontend", "full-stack"}
|
|
83
|
+
if needs_design:
|
|
84
|
+
design_path = change_root / "design.md"
|
|
85
|
+
checks.append(
|
|
86
|
+
check(
|
|
87
|
+
"artifact-design-md",
|
|
88
|
+
design_path.exists(),
|
|
89
|
+
"Found design.md for UI-bearing change" if design_path.exists() else "Missing design.md for frontend/full-stack change",
|
|
90
|
+
value=str(design_path),
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
checks.append(
|
|
94
|
+
check(
|
|
95
|
+
"design-alignment-not-rejected",
|
|
96
|
+
status.get("design_aligned") != "no",
|
|
97
|
+
"design_aligned is not rejected" if status.get("design_aligned") != "no" else "design_aligned=no blocks further Yolo progression",
|
|
98
|
+
value=status.get("design_aligned"),
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
current_stage = status.get("current_stage")
|
|
103
|
+
status_value = status.get("status")
|
|
104
|
+
verification_status = status.get("verification_status")
|
|
105
|
+
archival_status = status.get("archival_status")
|
|
106
|
+
repo = status.get("target_repo")
|
|
107
|
+
issue_number = status.get("issue_number")
|
|
108
|
+
branch_name = status.get("branch_name")
|
|
109
|
+
checkout_path = status.get("checkout_path")
|
|
110
|
+
issue_title = status.get("issue_title") or status.get("title")
|
|
111
|
+
issue_body = issue_doc_path.read_text(encoding="utf-8") if issue_doc_path.exists() else None
|
|
112
|
+
checkout_exists = bool(checkout_path) and Path(checkout_path).expanduser().exists()
|
|
113
|
+
|
|
114
|
+
if phase == "pre-openissue":
|
|
115
|
+
stage_ok = True
|
|
116
|
+
status_ok = True
|
|
117
|
+
try:
|
|
118
|
+
assert_stage_transition_allowed(current_stage, "plan", current_status=status_value)
|
|
119
|
+
except SystemExit as exc:
|
|
120
|
+
stage_ok = False
|
|
121
|
+
stage_detail = str(exc)
|
|
122
|
+
else:
|
|
123
|
+
stage_detail = f"current_stage={current_stage} can advance to plan/openissue"
|
|
124
|
+
try:
|
|
125
|
+
assert_status_transition_allowed(status_value, "active")
|
|
126
|
+
except SystemExit as exc:
|
|
127
|
+
status_ok = False
|
|
128
|
+
status_detail = str(exc)
|
|
129
|
+
else:
|
|
130
|
+
status_detail = f"status={status_value} can advance to active"
|
|
131
|
+
checks.append(
|
|
132
|
+
check(
|
|
133
|
+
"stage-ready-for-openissue",
|
|
134
|
+
stage_ok,
|
|
135
|
+
stage_detail,
|
|
136
|
+
value=current_stage,
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
checks.append(check("status-ready-for-openissue", status_ok, status_detail, value=status_value))
|
|
140
|
+
checks.append(
|
|
141
|
+
check(
|
|
142
|
+
"archival-not-finished",
|
|
143
|
+
archival_status != "archived",
|
|
144
|
+
"Change is not archived yet" if archival_status != "archived" else "Change is already archived",
|
|
145
|
+
value=archival_status,
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
checks.append(check("issue-title-present", bool(issue_title), "Issue title is present" if issue_title else "Issue title is required before openissue", value=issue_title))
|
|
149
|
+
checks.append(check("issue-body-present", bool(issue_body and issue_body.strip()), "issue.md has body content" if issue_body and issue_body.strip() else "issue.md must contain body content before openissue", value=str(issue_doc_path)))
|
|
150
|
+
elif phase == "post-openissue":
|
|
151
|
+
checks.extend(
|
|
152
|
+
[
|
|
153
|
+
check("status-target-repo", bool(repo), "target_repo recorded" if repo else "target_repo missing after openissue", value=repo),
|
|
154
|
+
check("status-issue-number", bool(issue_number), "issue_number recorded" if issue_number else "issue_number missing after openissue", value=issue_number),
|
|
155
|
+
check("status-branch-name", bool(branch_name), "branch_name recorded" if branch_name else "branch_name missing after openissue", value=branch_name),
|
|
156
|
+
check("status-checkout-path", bool(checkout_path), "checkout_path recorded" if checkout_path else "checkout_path missing after openissue", value=checkout_path),
|
|
157
|
+
check("issue-title-present", bool(issue_title), "Issue title is present" if issue_title else "Issue title is required", value=issue_title),
|
|
158
|
+
check("issue-body-present", bool(issue_body and issue_body.strip()), "issue.md has body content" if issue_body and issue_body.strip() else "issue.md must contain body content", value=str(issue_doc_path)),
|
|
159
|
+
check("checkout-path-exists", checkout_exists, "checkout_path exists" if checkout_exists else "checkout_path must point to an existing checkout", value=checkout_path),
|
|
160
|
+
]
|
|
161
|
+
)
|
|
162
|
+
elif phase == "pre-exec":
|
|
163
|
+
stage_ok = True
|
|
164
|
+
status_ok = True
|
|
165
|
+
try:
|
|
166
|
+
assert_stage_transition_allowed(current_stage, "tdd", current_status=status_value)
|
|
167
|
+
except SystemExit as exc:
|
|
168
|
+
stage_ok = False
|
|
169
|
+
stage_detail = str(exc)
|
|
170
|
+
else:
|
|
171
|
+
stage_detail = f"current_stage={current_stage} can advance to tdd/exec"
|
|
172
|
+
try:
|
|
173
|
+
assert_status_transition_allowed(status_value, "active")
|
|
174
|
+
except SystemExit as exc:
|
|
175
|
+
status_ok = False
|
|
176
|
+
status_detail = str(exc)
|
|
177
|
+
else:
|
|
178
|
+
status_detail = f"status={status_value} can advance/remain active"
|
|
179
|
+
checks.extend(
|
|
180
|
+
[
|
|
181
|
+
check("status-target-repo", bool(repo), "target_repo recorded" if repo else "target_repo missing before exec", value=repo),
|
|
182
|
+
check("status-issue-number", bool(issue_number), "issue_number recorded" if issue_number else "issue_number missing before exec", value=issue_number),
|
|
183
|
+
check("status-branch-name", bool(branch_name), "branch_name recorded" if branch_name else "branch_name missing before exec", value=branch_name),
|
|
184
|
+
check("status-checkout-path", bool(checkout_path), "checkout_path recorded" if checkout_path else "checkout_path missing before exec", value=checkout_path),
|
|
185
|
+
check("issue-title-present", bool(issue_title), "Issue title is present" if issue_title else "Issue title is required", value=issue_title),
|
|
186
|
+
check("checkout-path-exists", checkout_exists, "checkout_path exists" if checkout_exists else "checkout_path must point to an existing checkout", value=checkout_path),
|
|
187
|
+
check(
|
|
188
|
+
"stage-ready-for-exec",
|
|
189
|
+
stage_ok,
|
|
190
|
+
stage_detail,
|
|
191
|
+
value=current_stage,
|
|
192
|
+
),
|
|
193
|
+
check("status-ready-for-exec", status_ok, status_detail, value=status_value),
|
|
194
|
+
check(
|
|
195
|
+
"status-not-archived",
|
|
196
|
+
archival_status != "archived",
|
|
197
|
+
"Change is not archived yet" if archival_status != "archived" else "Change is already archived",
|
|
198
|
+
value=archival_status,
|
|
199
|
+
),
|
|
200
|
+
]
|
|
201
|
+
)
|
|
202
|
+
elif phase == "pre-archive":
|
|
203
|
+
stage_ok = True
|
|
204
|
+
status_done_ok = True
|
|
205
|
+
try:
|
|
206
|
+
assert_stage_transition_allowed(
|
|
207
|
+
current_stage,
|
|
208
|
+
"archive",
|
|
209
|
+
current_status=status_value,
|
|
210
|
+
allow_terminal_status_override=("done", "blocked"),
|
|
211
|
+
)
|
|
212
|
+
except SystemExit as exc:
|
|
213
|
+
stage_ok = False
|
|
214
|
+
stage_detail = str(exc)
|
|
215
|
+
else:
|
|
216
|
+
stage_detail = f"current_stage={current_stage} / status={status_value} can advance to archive"
|
|
217
|
+
try:
|
|
218
|
+
if status_value == "blocked":
|
|
219
|
+
assert_status_transition_allowed(status_value, "blocked", allow_terminal_status_override=("blocked",))
|
|
220
|
+
elif status_value == "done":
|
|
221
|
+
assert_status_transition_allowed(status_value, "done", allow_terminal_status_override=("done",))
|
|
222
|
+
else:
|
|
223
|
+
assert_status_transition_allowed(status_value, "done")
|
|
224
|
+
except SystemExit as exc:
|
|
225
|
+
status_done_ok = False
|
|
226
|
+
status_done_detail = str(exc)
|
|
227
|
+
else:
|
|
228
|
+
status_done_detail = f"status={status_value} can advance/finalize for archive"
|
|
229
|
+
checks.extend(
|
|
230
|
+
[
|
|
231
|
+
check("status-target-repo", bool(repo), "target_repo recorded" if repo else "target_repo missing before archive", value=repo),
|
|
232
|
+
check("status-issue-number", bool(issue_number), "issue_number recorded" if issue_number else "issue_number missing before archive", value=issue_number),
|
|
233
|
+
check("status-branch-name", bool(branch_name), "branch_name recorded" if branch_name else "branch_name missing before archive", value=branch_name),
|
|
234
|
+
check("status-checkout-path", bool(checkout_path), "checkout_path recorded" if checkout_path else "checkout_path missing before archive", value=checkout_path),
|
|
235
|
+
check(
|
|
236
|
+
"verification-ready",
|
|
237
|
+
verification_status == "passed" or status_value == "blocked",
|
|
238
|
+
"Verification is passed or change is blocked" if (verification_status == "passed" or status_value == "blocked") else "verification_status must be passed before archive unless change is blocked",
|
|
239
|
+
value={"status": status_value, "verification_status": verification_status},
|
|
240
|
+
),
|
|
241
|
+
check(
|
|
242
|
+
"stage-ready-for-archive",
|
|
243
|
+
stage_ok,
|
|
244
|
+
stage_detail,
|
|
245
|
+
value={"current_stage": current_stage, "status": status_value},
|
|
246
|
+
),
|
|
247
|
+
check("status-ready-for-archive", status_done_ok, status_done_detail, value=status_value),
|
|
248
|
+
]
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
doctor_phases = {"post-openissue", "pre-exec", "pre-archive"}
|
|
252
|
+
doctor_should_run = phase in doctor_phases and all([repo, issue_number, branch_name, checkout_path])
|
|
253
|
+
if doctor_should_run:
|
|
254
|
+
doctor_result = run_doctor_checks(
|
|
255
|
+
project_root=project_root_path,
|
|
256
|
+
change_id=change_id,
|
|
257
|
+
repo=repo,
|
|
258
|
+
issue_number=int(issue_number),
|
|
259
|
+
branch_name=branch_name,
|
|
260
|
+
checkout_path_override=checkout_path,
|
|
261
|
+
)
|
|
262
|
+
checks.append(
|
|
263
|
+
check(
|
|
264
|
+
"doctor-gate",
|
|
265
|
+
doctor_result["ok"],
|
|
266
|
+
"doctor checks passed" if doctor_result["ok"] else "doctor checks failed",
|
|
267
|
+
value={"hard_failures": doctor_result["hard_failures"], "warnings": doctor_result["warnings"]},
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
elif phase in doctor_phases:
|
|
271
|
+
checks.append(
|
|
272
|
+
check(
|
|
273
|
+
"doctor-gate",
|
|
274
|
+
False,
|
|
275
|
+
"doctor prerequisites missing from status.json",
|
|
276
|
+
value={
|
|
277
|
+
"target_repo": repo,
|
|
278
|
+
"issue_number": issue_number,
|
|
279
|
+
"branch_name": branch_name,
|
|
280
|
+
"checkout_path": checkout_path,
|
|
281
|
+
},
|
|
282
|
+
)
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
ok = all(item["ok"] or item["severity"] == "warn" for item in checks)
|
|
286
|
+
hard_failures = [item for item in checks if not item["ok"] and item["severity"] != "warn"]
|
|
287
|
+
warnings = [item for item in checks if not item["ok"] and item["severity"] == "warn"]
|
|
288
|
+
return {
|
|
289
|
+
"change_id": change_id,
|
|
290
|
+
"phase": phase,
|
|
291
|
+
"ok": ok,
|
|
292
|
+
"hard_failures": len(hard_failures),
|
|
293
|
+
"warnings": len(warnings),
|
|
294
|
+
"checks": checks,
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def main() -> int:
|
|
299
|
+
args = parse_args()
|
|
300
|
+
result = run_yolo_gate(args.project_root, args.change_id, args.phase)
|
|
301
|
+
if args.json:
|
|
302
|
+
print(json.dumps(result, indent=2))
|
|
303
|
+
else:
|
|
304
|
+
print(f"Yolo gate: {result['phase']} for {result['change_id']}")
|
|
305
|
+
for item in result["checks"]:
|
|
306
|
+
prefix = "PASS" if item["ok"] else ("WARN" if item["severity"] == "warn" else "FAIL")
|
|
307
|
+
print(f"[{prefix}] {item['name']}: {item['detail']}")
|
|
308
|
+
return 0 if result["ok"] else 1
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
if __name__ == "__main__":
|
|
312
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Design System Template
|
|
2
|
+
|
|
3
|
+
> This template follows the DESIGN.md format from Google Stitch / awesome-design-md.
|
|
4
|
+
> Drop into project root as `DESIGN.md` or merge into `specs/ux.md`.
|
|
5
|
+
|
|
6
|
+
## Brand & Purpose
|
|
7
|
+
|
|
8
|
+
- Product: [what the product is]
|
|
9
|
+
- Audience: [who uses it]
|
|
10
|
+
- Core value: [one-line positioning statement]
|
|
11
|
+
|
|
12
|
+
## Visual Tone
|
|
13
|
+
|
|
14
|
+
- Primary tone: [minimal | maximalist | brutalist | editorial | organic | luxury | playful | industrial | retro-futuristic | dark-mode-first]
|
|
15
|
+
- Secondary tone: [optional refinement or modifier]
|
|
16
|
+
- Reference brand: [optional, e.g., "similar to Linear" or "inspired by Notion"]
|
|
17
|
+
|
|
18
|
+
## Color System
|
|
19
|
+
|
|
20
|
+
| Token | Value | Usage |
|
|
21
|
+
|-------|-------|-------|
|
|
22
|
+
| Background | [color] | Primary page background |
|
|
23
|
+
| Surface | [color] | Cards, panels, elevated surfaces |
|
|
24
|
+
| Primary | [color] | Main brand color, key actions |
|
|
25
|
+
| Accent | [color] | Highlights, links, focus states |
|
|
26
|
+
| Text | [color] | Primary text content |
|
|
27
|
+
| Text Muted | [color] | Secondary text, placeholders |
|
|
28
|
+
| Border | [color] | Dividers, input borders |
|
|
29
|
+
| Success | [color] | Positive states, confirmations |
|
|
30
|
+
| Error | [color] | Errors, destructive actions |
|
|
31
|
+
| Warning | [color] | Caution states |
|
|
32
|
+
|
|
33
|
+
Define as CSS variables:
|
|
34
|
+
|
|
35
|
+
```css
|
|
36
|
+
:root {
|
|
37
|
+
--color-background: [value];
|
|
38
|
+
--color-surface: [value];
|
|
39
|
+
--color-primary: [value];
|
|
40
|
+
--color-accent: [value];
|
|
41
|
+
--color-text: [value];
|
|
42
|
+
--color-text-muted: [value];
|
|
43
|
+
--color-border: [value];
|
|
44
|
+
--color-success: [value];
|
|
45
|
+
--color-error: [value];
|
|
46
|
+
--color-warning: [value];
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Typography
|
|
51
|
+
|
|
52
|
+
| Role | Font | Weight | Size |
|
|
53
|
+
|------|------|--------|------|
|
|
54
|
+
| Display | [font family] | [weight] | [size range] |
|
|
55
|
+
| Heading | [font family] | [weight] | [size range] |
|
|
56
|
+
| Body | [font family] | [weight] | [base size] |
|
|
57
|
+
| Mono | [font family] | [weight] | [size] |
|
|
58
|
+
| Label | [font family] | [weight] | [size] |
|
|
59
|
+
|
|
60
|
+
Typography scale (optional):
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
:root {
|
|
64
|
+
--font-display: [family];
|
|
65
|
+
--font-body: [family];
|
|
66
|
+
--font-mono: [family];
|
|
67
|
+
--text-xs: [size];
|
|
68
|
+
--text-sm: [size];
|
|
69
|
+
--text-base: [size];
|
|
70
|
+
--text-lg: [size];
|
|
71
|
+
--text-xl: [size];
|
|
72
|
+
--text-2xl: [size];
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Layout & Spacing
|
|
77
|
+
|
|
78
|
+
- Density: [dense | balanced | sparse]
|
|
79
|
+
- Max width: [content width limit, e.g., 1200px]
|
|
80
|
+
- Grid: [column system, e.g., 12-column]
|
|
81
|
+
- Spacing base: [4px | 8px]
|
|
82
|
+
|
|
83
|
+
Spacing scale:
|
|
84
|
+
|
|
85
|
+
```css
|
|
86
|
+
:root {
|
|
87
|
+
--space-1: [base * 0.5];
|
|
88
|
+
--space-2: [base * 1];
|
|
89
|
+
--space-3: [base * 2];
|
|
90
|
+
--space-4: [base * 3];
|
|
91
|
+
--space-5: [base * 4];
|
|
92
|
+
--space-6: [base * 6];
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Motion
|
|
97
|
+
|
|
98
|
+
- Animation level: [none | subtle | moderate | rich]
|
|
99
|
+
- Transition timing: [fast ~100ms | normal ~200ms | slow ~300ms]
|
|
100
|
+
- Micro-interactions: [hover states, loading states, focus effects]
|
|
101
|
+
|
|
102
|
+
Motion guidelines:
|
|
103
|
+
|
|
104
|
+
- Entrance: [stagger | fade | slide | none]
|
|
105
|
+
- Exit: [fade | slide | none]
|
|
106
|
+
- Hover: [scale | color shift | underline | shadow]
|
|
107
|
+
- Loading: [spinner | skeleton | progress bar]
|
|
108
|
+
|
|
109
|
+
## Visual Details
|
|
110
|
+
|
|
111
|
+
- Border radius: [sharp 0px | soft 4-8px | round 12px+]
|
|
112
|
+
- Shadow level: [none | subtle | moderate | strong]
|
|
113
|
+
- Icon style: [outline | solid | minimal | custom]
|
|
114
|
+
- Illustration style: [none | abstract | realistic | brand-specific]
|
|
115
|
+
|
|
116
|
+
## Component Patterns
|
|
117
|
+
|
|
118
|
+
### Buttons
|
|
119
|
+
|
|
120
|
+
| Variant | Style |
|
|
121
|
+
|---------|-------|
|
|
122
|
+
| Primary | [background, text, radius, shadow] |
|
|
123
|
+
| Secondary | [background, text, radius] |
|
|
124
|
+
| Ghost | [no background, text only] |
|
|
125
|
+
| Destructive | [error color variant] |
|
|
126
|
+
|
|
127
|
+
### Cards
|
|
128
|
+
|
|
129
|
+
- Border: [none | visible | shadow-only]
|
|
130
|
+
- Padding: [spacing value]
|
|
131
|
+
- Radius: [border radius]
|
|
132
|
+
- Shadow: [shadow level]
|
|
133
|
+
|
|
134
|
+
### Inputs
|
|
135
|
+
|
|
136
|
+
- Border: [width, color]
|
|
137
|
+
- Focus: [ring color, ring width]
|
|
138
|
+
- Error: [border color, icon]
|
|
139
|
+
- Radius: [border radius]
|
|
140
|
+
|
|
141
|
+
### Navigation
|
|
142
|
+
|
|
143
|
+
- Style: [sidebar | topbar | tabs | mix]
|
|
144
|
+
- Active state: [background change | border | indicator]
|
|
145
|
+
- Collapsed: [icon-only | hidden | responsive]
|
|
146
|
+
|
|
147
|
+
## Best For
|
|
148
|
+
|
|
149
|
+
- Ideal use cases:
|
|
150
|
+
- [when this design works best]
|
|
151
|
+
- [suitable product types]
|
|
152
|
+
- [appropriate audience]
|
|
153
|
+
|
|
154
|
+
- Avoid:
|
|
155
|
+
- [when not to use this direction]
|
|
156
|
+
- [mismatched product types]
|
|
157
|
+
|
|
158
|
+
## Design Decisions Log
|
|
159
|
+
|
|
160
|
+
Record design decisions that outlive individual changes:
|
|
161
|
+
|
|
162
|
+
- [YYYY-MM-DD] [change-id]: [decision made] — [reasoning]
|
|
163
|
+
- [YYYY-MM-DD] [change-id]: [decision made] — [reasoning]
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Quick Tone Reference
|
|
168
|
+
|
|
169
|
+
When choosing a visual tone, consider:
|
|
170
|
+
|
|
171
|
+
| Tone | Best For | Key Brands |
|
|
172
|
+
|------|----------|------------|
|
|
173
|
+
| Minimal Clean | Tools, dashboards, productivity | Linear, Vercel, Raycast |
|
|
174
|
+
| Editorial Warm | Content, docs, blogs | Notion, Medium, Mintlify |
|
|
175
|
+
| Dark Cinematic | Media, AI tools, dev tools | ElevenLabs, Cursor, RunwayML |
|
|
176
|
+
| Developer-First | Terminal, CLI, APIs | Ollama, Warp, Supabase |
|
|
177
|
+
| Friendly Playful | Consumer apps, SaaS | Lovable, Zapier, Cal.com |
|
|
178
|
+
| Enterprise Clean | B2B, infrastructure | HashiCorp, MongoDB, ClickHouse |
|
|
179
|
+
| Luxury Refined | Premium products | Apple, Figma, Linear (pro) |
|