@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.
Files changed (192) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/LICENSE +21 -0
  3. package/README.md +315 -2
  4. package/RELEASE_NOTES.md +102 -0
  5. package/atoms/registry.json +758 -0
  6. package/bin/xflow.js +7208 -0
  7. package/docs/adoption/README.md +128 -0
  8. package/docs/adoption/openflow-release-hardening.md +61 -0
  9. package/docs/benchmark-openflow-vs-gstack-superpowers-openspec-2026-05-25.md +81 -0
  10. package/docs/compatibility.md +52 -0
  11. package/docs/competitive-benchmark.md +108 -0
  12. package/docs/corps-operator-guide.md +75 -0
  13. package/docs/demo-proof.md +126 -0
  14. package/docs/examples-gallery.md +115 -0
  15. package/docs/fixtures/tracker-item.json +7 -0
  16. package/docs/goal-vs-codex.md +129 -0
  17. package/docs/gstack-comparison.md +88 -0
  18. package/docs/install-upgrade.md +133 -0
  19. package/docs/integrations.md +49 -0
  20. package/docs/launch-demo.md +123 -0
  21. package/docs/launch-dossier.md +180 -0
  22. package/docs/methodology.md +149 -0
  23. package/docs/npm-publish-handoff.md +83 -0
  24. package/docs/openspec-migration.md +106 -0
  25. package/docs/public-benchmark.md +68 -0
  26. package/docs/public-release.md +145 -0
  27. package/docs/quality-assessment.md +139 -0
  28. package/docs/quickstart.md +156 -0
  29. package/docs/reviewer-guide.md +43 -0
  30. package/docs/spec-kit-benchmark.md +73 -0
  31. package/docs/super-assistant-comparison.md +106 -0
  32. package/docs/superpowers-comparison.md +82 -0
  33. package/docs/team-adoption.md +123 -0
  34. package/docs/tooling-matrix.md +91 -0
  35. package/docs/walkthrough.md +76 -0
  36. package/docs/workflow-manual.md +1125 -0
  37. package/package.json +83 -4
  38. package/prompts/pencil-draft.md +46 -0
  39. package/prompts/pencil-refine.md +46 -0
  40. package/prompts/phase-artifact.md +24 -0
  41. package/prompts/phase-execution.md +32 -0
  42. package/schemas/competitor-reconstruction-contract.schema.json +91 -0
  43. package/schemas/llm-design-review-aggregate.schema.json +83 -0
  44. package/schemas/visual-benchmark.schema.json +978 -0
  45. package/schemas/workflow.schema.json +100 -0
  46. package/scripts/run-tests.mjs +23 -0
  47. package/scripts/takein_digest.py +139 -0
  48. package/specs/README.md +118 -0
  49. package/specs/architecture.md +36 -0
  50. package/specs/product.md +33 -0
  51. package/specs/workflow.md +349 -0
  52. package/src/agent_team/atoms/codex-app-bridge.js +8 -0
  53. package/src/agent_team/atoms/design/competitor-reconstruction-review.js +44 -0
  54. package/src/agent_team/atoms/design/contract-freeze.js +8 -0
  55. package/src/agent_team/atoms/design/generation-contract.js +442 -0
  56. package/src/agent_team/atoms/design/reconstruction-pack.js +246 -0
  57. package/src/agent_team/atoms/design/reference-surface-lock.js +49 -0
  58. package/src/agent_team/atoms/patch-challenge.js +19 -0
  59. package/src/agent_team/atoms/pencil/accept.js +9 -0
  60. package/src/agent_team/atoms/pencil/draft.js +365 -0
  61. package/src/agent_team/atoms/pencil/refine.js +229 -0
  62. package/src/agent_team/atoms/phase-run-dispatch.js +8 -0
  63. package/src/agent_team/atoms/team-run.js +380 -0
  64. package/src/agent_team/atoms/visual/aesthetic-review.js +231 -0
  65. package/src/agent_team/atoms/visual/benchmark-repair-plan.js +291 -0
  66. package/src/agent_team/atoms/visual/benchmark.js +1652 -0
  67. package/src/agent_team/atoms/visual/design-selection.js +23 -0
  68. package/src/agent_team/atoms/visual/direction-synthesis.js +124 -0
  69. package/src/agent_team/atoms/visual/dom-rect-export.js +129 -0
  70. package/src/agent_team/atoms/visual/image-diff.js +186 -0
  71. package/src/agent_team/atoms/visual/layout-competition.js +8 -0
  72. package/src/agent_team/atoms/visual/page-evidence-capture.js +806 -0
  73. package/src/agent_team/atoms/visual/playwright-runtime.js +8 -0
  74. package/src/agent_team/atoms/visual/review-aggregate.js +87 -0
  75. package/src/agent_team/atoms/visual/review.js +77 -0
  76. package/src/agent_team/atoms/visual/visual-report.js +197 -0
  77. package/src/agent_team/atoms/visual/visual-token-export.js +417 -0
  78. package/src/agent_team/common.js +311 -0
  79. package/src/core/atoms/agent-invoke.js +684 -0
  80. package/src/core/atoms/event/ingest.js +30 -0
  81. package/src/core/atoms/experience/digest.js +55 -0
  82. package/src/core/atoms/gate/artifact-verify.js +83 -0
  83. package/src/core/atoms/gate/competitor-contract-validate.js +119 -0
  84. package/src/core/atoms/gate/evidence-collect.js +64 -0
  85. package/src/core/atoms/gate/payload-from-phase-run.js +78 -0
  86. package/src/core/atoms/gate/visual-benchmark-validate.js +183 -0
  87. package/src/core/atoms/gate/workbench.js +79 -0
  88. package/src/core/atoms/intake/classify.js +15 -0
  89. package/src/core/atoms/intake/design-skill-select.js +16 -0
  90. package/src/core/atoms/intake/preview-or-refine.js +19 -0
  91. package/src/core/atoms/intake/recommend.js +20 -0
  92. package/src/core/atoms/intake/research-same-category.js +19 -0
  93. package/src/core/atoms/intervention/create.js +30 -0
  94. package/src/core/atoms/memory/manage.js +27 -0
  95. package/src/core/atoms/memory/mount.js +13 -0
  96. package/src/core/atoms/mission/create.js +19 -0
  97. package/src/core/atoms/mission/list.js +14 -0
  98. package/src/core/atoms/mission/show.js +26 -0
  99. package/src/core/atoms/notify/checkpoint.js +46 -0
  100. package/src/core/atoms/phase-run/complete.js +42 -0
  101. package/src/core/atoms/phase-run/fail.js +40 -0
  102. package/src/core/atoms/phase-run/persist.js +39 -0
  103. package/src/core/atoms/phase-run/start.js +30 -0
  104. package/src/core/atoms/plugin/run.js +76 -0
  105. package/src/core/atoms/policy/gate.js +90 -0
  106. package/src/core/atoms/policy/resolve.js +11 -0
  107. package/src/core/atoms/storage/sync.js +57 -0
  108. package/src/core/atoms/workflow/advance.js +25 -0
  109. package/src/core/atoms/workflow/guard.js +127 -0
  110. package/src/core/atoms/workflow/state-load.js +37 -0
  111. package/src/core/bindings.js +37 -0
  112. package/src/core/change-artifacts.js +134 -0
  113. package/src/core/competitive-score.js +265 -0
  114. package/src/core/concurrency-policy.js +35 -0
  115. package/src/core/execution-log.js +108 -0
  116. package/src/core/intake-recommendation.js +134 -0
  117. package/src/core/memory-state.js +62 -0
  118. package/src/core/mission-state.js +780 -0
  119. package/src/core/pending-gates.js +66 -0
  120. package/src/core/phase-cost.js +116 -0
  121. package/src/core/phase-run-read.js +27 -0
  122. package/src/core/policy-overlay.js +180 -0
  123. package/src/core/state-store.js +201 -0
  124. package/src/core/workflow-executor.js +998 -0
  125. package/src/core/workflow-integrity.js +111 -0
  126. package/src/core/workflow-loader.js +163 -0
  127. package/src/core/workflow-rerun.js +84 -0
  128. package/src/core/workflow-state.js +119 -0
  129. package/src/server.js +1307 -0
  130. package/workflows/corps.yaml +479 -0
  131. package/workflows/yolo.yaml +233 -0
  132. package/xflow/README.md +76 -0
  133. package/xflow/aha/SKILL.md +82 -0
  134. package/xflow/aha/scripts/append_aha.py +50 -0
  135. package/xflow/archive/scripts/archive_change.py +338 -0
  136. package/xflow/archive/templates/merge-design.md +54 -0
  137. package/xflow/archive/templates/merge-workflow.md +26 -0
  138. package/xflow/atoms/__init__.py +6 -0
  139. package/xflow/atoms/a1_issue_create_or_patch.py +70 -0
  140. package/xflow/atoms/a2_branch_create_and_link.py +42 -0
  141. package/xflow/atoms/a3_repo_doctor.py +11 -0
  142. package/xflow/atoms/a4_project_set_status.py +11 -0
  143. package/xflow/atoms/a5_archive_commit_push_close.py +11 -0
  144. package/xflow/atoms/a6_pr_create.py +72 -0
  145. package/xflow/atoms/b1_change_scaffold.py +11 -0
  146. package/xflow/atoms/b2_status_read.py +16 -0
  147. package/xflow/atoms/b2b_status_write.py +20 -0
  148. package/xflow/atoms/b3_status_transition.py +27 -0
  149. package/xflow/atoms/b4_handoff_scaffold_or_refresh.py +11 -0
  150. package/xflow/atoms/b5_aha_append.py +11 -0
  151. package/xflow/atoms/b6_takein_digest.py +11 -0
  152. package/xflow/atoms/b6b_lookback_digest.py +11 -0
  153. package/xflow/atoms/b7_change_mission_bind.py +43 -0
  154. package/xflow/atoms/c1_mem.py +54 -0
  155. package/xflow/atoms/e6_gate_local_precheck.py +23 -0
  156. package/xflow/atoms/h1_design_lite_gate.py +74 -0
  157. package/xflow/atoms/i6a_tdd_run.py +104 -0
  158. package/xflow/atoms/i6b_tdd_proof_validate.py +165 -0
  159. package/xflow/atoms/i6c_tdd_quality_review.py +357 -0
  160. package/xflow/atoms/j1_tests_run.py +129 -0
  161. package/xflow/atoms/j4a_spec_consistency_structural.py +105 -0
  162. package/xflow/atoms/j4b_spec_delta_review.py +316 -0
  163. package/xflow/atoms/j4c_openspec_migration_map.py +121 -0
  164. package/xflow/atoms/j4d_spec_clarify_gate.py +373 -0
  165. package/xflow/atoms/j6_cr_review.py +443 -0
  166. package/xflow/atoms/k1_artifacts_complete_check.py +39 -0
  167. package/xflow/atoms/k2_merge_snippets_apply.py +11 -0
  168. package/xflow/atoms/k3_handoff_refresh.py +14 -0
  169. package/xflow/atoms/k4_mem_lesson_persist.py +65 -0
  170. package/xflow/atoms/k5_archive_publish.py +21 -0
  171. package/xflow/atoms/k6_aha_merge.py +42 -0
  172. package/xflow/atoms/tdd_lib.py +747 -0
  173. package/xflow/corps/SKILL.md +109 -0
  174. package/xflow/exec/scripts/set_issue_in_progress.py +159 -0
  175. package/xflow/goal/SKILL.md +150 -0
  176. package/xflow/handoff/SKILL.md +95 -0
  177. package/xflow/handoff/scripts/scaffold_handoff.py +304 -0
  178. package/xflow/lookback/SKILL.md +66 -0
  179. package/xflow/lookback/scripts/lookback_digest.py +46 -0
  180. package/xflow/openissue/scripts/open_issue_flow.py +438 -0
  181. package/xflow/plan/SKILL.md +38 -0
  182. package/xflow/ralph/SKILL.md +123 -0
  183. package/xflow/scripts/check_installed_xflow_skill_sync.sh +44 -0
  184. package/xflow/scripts/common.py +480 -0
  185. package/xflow/scripts/doctor.py +278 -0
  186. package/xflow/scripts/sync_installed_xflow_skill.sh +134 -0
  187. package/xflow/takein/SKILL.md +81 -0
  188. package/xflow/takein/scripts/takein_digest.py +88 -0
  189. package/xflow/yolo/SKILL.md +66 -0
  190. package/xflow/yolo/scripts/scaffold_specs_change.py +673 -0
  191. package/xflow/yolo/scripts/yolo_gate.py +312 -0
  192. package/xflow/yolo/templates/DESIGN.md +179 -0
@@ -0,0 +1,100 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://openflow/schemas/workflow.schema.json",
4
+ "title": "XFlow Workflow Definition",
5
+ "type": "object",
6
+ "required": ["name", "version", "track", "requires", "phases"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "name": { "type": "string" },
10
+ "version": { "type": "integer", "minimum": 1 },
11
+ "description": { "type": "string" },
12
+ "track": { "type": "string", "enum": ["lite", "heavy"] },
13
+ "parallel": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "properties": {
17
+ "max_agents": { "type": "integer", "minimum": 1, "maximum": 16 },
18
+ "policy": { "type": "string", "enum": ["weighted", "fixed"] }
19
+ }
20
+ },
21
+ "requires": {
22
+ "type": "object",
23
+ "properties": {
24
+ "agentos_http": { "type": "boolean" },
25
+ "agentos_bin": { "type": "boolean" },
26
+ "gh": { "type": "boolean" },
27
+ "pencil": { "type": "boolean" }
28
+ },
29
+ "additionalProperties": false
30
+ },
31
+ "phases": {
32
+ "type": "array",
33
+ "minItems": 1,
34
+ "items": {
35
+ "type": "object",
36
+ "required": ["id", "label", "required"],
37
+ "additionalProperties": false,
38
+ "properties": {
39
+ "id": { "type": "string" },
40
+ "label": { "type": "string" },
41
+ "catalog_ref": { "type": "integer", "minimum": 1, "maximum": 27 },
42
+ "required": { "type": "boolean" },
43
+ "condition": {
44
+ "type": "object",
45
+ "description": "Skip phase unless condition met",
46
+ "properties": {
47
+ "input_field": { "type": "string" },
48
+ "equals": {}
49
+ }
50
+ },
51
+ "atoms": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "object",
55
+ "required": ["id"],
56
+ "properties": {
57
+ "id": { "type": "string" },
58
+ "with": { "type": "object" },
59
+ "parallel_group": { "type": "string" },
60
+ "parallel_weight": { "type": "integer", "minimum": 1, "maximum": 16 }
61
+ }
62
+ }
63
+ },
64
+ "preconditions": {
65
+ "type": "array",
66
+ "items": {
67
+ "type": "object",
68
+ "properties": {
69
+ "phase_artifact": { "type": "string" },
70
+ "predicate": { "type": "string", "enum": ["exists", "nonempty", "equals", "truthy"] },
71
+ "value": {}
72
+ }
73
+ }
74
+ },
75
+ "artifacts": {
76
+ "type": "array",
77
+ "items": {
78
+ "type": "object",
79
+ "required": ["path"],
80
+ "properties": {
81
+ "path": { "type": "string" },
82
+ "optional": { "type": "boolean", "default": false }
83
+ }
84
+ }
85
+ },
86
+ "gate": {
87
+ "type": "object",
88
+ "required": ["type"],
89
+ "properties": {
90
+ "type": { "type": "string", "enum": ["deterministic", "artifact-verify", "llm-judge", "human", "skip"] },
91
+ "atom": { "type": "string" },
92
+ "with": { "type": "object" },
93
+ "on_fail": { "type": "string", "enum": ["stop", "retry", "advance-with-warning"] }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
@@ -0,0 +1,23 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { readdirSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+
5
+ const repoRoot = process.cwd();
6
+ const requestedFiles = process.argv.slice(2);
7
+ const testFiles = requestedFiles.length > 0
8
+ ? requestedFiles
9
+ : readdirSync(resolve(repoRoot, 'test'))
10
+ .filter((name) => name.endsWith('.test.js'))
11
+ .sort()
12
+ .map((name) => `test/${name}`);
13
+
14
+ for (const testFile of testFiles) {
15
+ const result = spawnSync(process.execPath, [testFile], {
16
+ cwd: repoRoot,
17
+ stdio: 'inherit',
18
+ });
19
+
20
+ if (result.status !== 0) {
21
+ process.exit(result.status ?? 1);
22
+ }
23
+ }
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env python3
2
+ """Generate a compact xflow takeover digest from project handoff artifacts."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import subprocess
9
+ from pathlib import Path
10
+
11
+
12
+ ROOT_FILES = ("HANDOFF.md", "AHA.md", "DESIGN.md")
13
+
14
+
15
+ def run_git(project_root: Path, args: list[str]) -> str:
16
+ try:
17
+ return subprocess.run(
18
+ ["git", *args],
19
+ cwd=project_root,
20
+ check=True,
21
+ text=True,
22
+ capture_output=True,
23
+ ).stdout.strip()
24
+ except (FileNotFoundError, subprocess.CalledProcessError):
25
+ return ""
26
+
27
+
28
+ def read_excerpt(path: Path, limit: int) -> dict[str, object]:
29
+ if not path.exists():
30
+ return {
31
+ "path": str(path),
32
+ "exists": False,
33
+ "excerpt": "",
34
+ "line_count": 0,
35
+ "truncated": False,
36
+ }
37
+
38
+ lines = path.read_text(encoding="utf-8").splitlines()
39
+ excerpt_lines = lines[:limit]
40
+ return {
41
+ "path": str(path),
42
+ "exists": True,
43
+ "excerpt": "\n".join(excerpt_lines),
44
+ "line_count": len(lines),
45
+ "truncated": len(lines) > limit,
46
+ }
47
+
48
+
49
+ def build_digest(project_root: Path, excerpt_lines: int) -> dict[str, object]:
50
+ project_root = project_root.expanduser().resolve()
51
+ files = {name: read_excerpt(project_root / name, excerpt_lines) for name in ROOT_FILES}
52
+ status = run_git(project_root, ["status", "-sb"])
53
+ branch = run_git(project_root, ["branch", "--show-current"])
54
+ head = run_git(project_root, ["log", "-1", "--oneline", "--decorate"])
55
+ origin_head = run_git(project_root, ["rev-parse", "--verify", "origin/HEAD"])
56
+
57
+ warnings: list[str] = []
58
+ if not files["HANDOFF.md"]["exists"]:
59
+ warnings.append("HANDOFF.md is missing; intake context is incomplete.")
60
+ if not files["AHA.md"]["exists"]:
61
+ warnings.append("AHA.md is missing; durable lessons may be unavailable.")
62
+ if status and "\n" in status:
63
+ warnings.append("Working tree is dirty; stage deliberately and avoid blanket reset commands.")
64
+
65
+ return {
66
+ "project_root": str(project_root),
67
+ "git": {
68
+ "branch": branch or None,
69
+ "head": head or None,
70
+ "origin_head": origin_head or None,
71
+ "status_sb": status or None,
72
+ },
73
+ "files": files,
74
+ "warnings": warnings,
75
+ "recommended_first_action": "Compare HANDOFF/AHA claims against git status, then inspect only files directly relevant to the active objective.",
76
+ }
77
+
78
+
79
+ def render_markdown(digest: dict[str, object]) -> str:
80
+ git = digest["git"]
81
+ files = digest["files"]
82
+ warnings = digest["warnings"]
83
+ lines = [
84
+ "# xflow Takein Digest",
85
+ "",
86
+ f"Project root: `{digest['project_root']}`",
87
+ f"Branch: `{git.get('branch') or 'unknown'}`",
88
+ f"HEAD: `{git.get('head') or 'unknown'}`",
89
+ "",
90
+ "## Git Status",
91
+ "",
92
+ "```text",
93
+ git.get("status_sb") or "(unavailable)",
94
+ "```",
95
+ "",
96
+ "## Warnings",
97
+ "",
98
+ ]
99
+ if warnings:
100
+ lines.extend(f"- {warning}" for warning in warnings)
101
+ else:
102
+ lines.append("- None")
103
+ lines.extend(["", "## Artifacts", ""])
104
+ for name, payload in files.items():
105
+ exists = "present" if payload["exists"] else "missing"
106
+ truncated = " truncated" if payload["truncated"] else ""
107
+ lines.extend([
108
+ f"### {name} ({exists}, {payload['line_count']} lines{truncated})",
109
+ "",
110
+ "```markdown",
111
+ payload["excerpt"] or "",
112
+ "```",
113
+ "",
114
+ ])
115
+ lines.extend([
116
+ "## Recommended First Action",
117
+ "",
118
+ str(digest["recommended_first_action"]),
119
+ ])
120
+ return "\n".join(lines).rstrip() + "\n"
121
+
122
+
123
+ def main() -> int:
124
+ parser = argparse.ArgumentParser(description=__doc__)
125
+ parser.add_argument("--project-root", default=".", help="Project root containing HANDOFF.md and AHA.md.")
126
+ parser.add_argument("--excerpt-lines", type=int, default=160, help="Maximum lines to include per artifact.")
127
+ parser.add_argument("--json", action="store_true", help="Print JSON instead of markdown.")
128
+ args = parser.parse_args()
129
+
130
+ digest = build_digest(Path(args.project_root), max(1, args.excerpt_lines))
131
+ if args.json:
132
+ print(json.dumps(digest, indent=2, ensure_ascii=False))
133
+ else:
134
+ print(render_markdown(digest), end="")
135
+ return 0
136
+
137
+
138
+ if __name__ == "__main__":
139
+ raise SystemExit(main())
@@ -0,0 +1,118 @@
1
+ # Specs
2
+
3
+ This directory is the single Superflow-owned root directory at the project root.
4
+
5
+ It has two layers:
6
+
7
+ - `specs/*.md` for durable project source-of-truth specs
8
+ - `specs/changes/<change-id>/` for per-change working artifacts
9
+
10
+ ## Layout
11
+
12
+ ```text
13
+ specs/
14
+ |-- README.md
15
+ |-- product.md
16
+ |-- architecture.md
17
+ |-- workflow.md
18
+ |-- ux.md # optional (or use DESIGN.md)
19
+ |-- DESIGN.md # optional design system
20
+ `-- changes/
21
+ `-- <change-id>/
22
+ |-- proposal.md
23
+ |-- plan.md
24
+ |-- findings.md # optional research notes for long or uncertain changes
25
+ |-- progress.md # optional rolling status for long-running changes
26
+ |-- status.json
27
+ |-- design.md # if frontend/UI change
28
+ |-- merge-product.md # optional
29
+ |-- merge-architecture.md
30
+ |-- merge-workflow.md
31
+ |-- merge-ux.md
32
+ `-- merge-design.md # if design change
33
+ ```
34
+
35
+ ## Root specs vs change specs
36
+
37
+ Use root specs for durable truth:
38
+
39
+ - `product.md`
40
+ - product goals
41
+ - accepted behavior
42
+ - scope boundaries
43
+ - `architecture.md`
44
+ - system shape
45
+ - module boundaries
46
+ - technical invariants
47
+ - `workflow.md`
48
+ - delivery rules
49
+ - QA / review / release rules
50
+ - `ux.md` / `DESIGN.md`
51
+ - visual tone
52
+ - color system
53
+ - typography
54
+ - layout rules
55
+ - component patterns
56
+
57
+ Use `specs/changes/<change-id>/` for change-scoped work:
58
+
59
+ - proposal
60
+ - plan
61
+ - design reasoning (if UI)
62
+ - machine-readable state
63
+ - explicit archive merge snippets
64
+
65
+ `xflow:plan` only writes `plan.md`. It does not create `tasks.md`.
66
+
67
+ For research-heavy or long-running changes, `findings.md` and `progress.md`
68
+ may be added as auxiliary notes. They are optional and do not replace the plan.
69
+
70
+ ## DESIGN.md
71
+
72
+ `DESIGN.md` is the canonical design system file.
73
+
74
+ It follows the format from Google Stitch / awesome-design-md.
75
+
76
+ Use it OR `specs/ux.md` — never both with overlapping content.
77
+
78
+ When a change involves UI:
79
+
80
+ 1. Check if `DESIGN.md` exists
81
+ 2. If not, create one from template
82
+ 3. Run design-check in yolo workflow
83
+ 4. Archive design decisions to Design Decisions Log
84
+
85
+ ## Archive rule
86
+
87
+ Do not treat `proposal.md`, `plan.md`, or `design.md` as automatic sources for root spec updates.
88
+
89
+ When a change produces durable truth, write the exact durable facts into explicit merge files:
90
+
91
+ - `merge-product.md`
92
+ - `merge-architecture.md`
93
+ - `merge-workflow.md` for workflow or capability deltas
94
+ - `merge-ux.md`
95
+ - `merge-design.md`
96
+
97
+ Archive should prefer these explicit merge files over trying to summarize large documents.
98
+
99
+ This is intentional:
100
+
101
+ - it reduces accidental deletion of older truth
102
+ - it reduces under-summary or over-summary of the current change
103
+ - it keeps the durable root specs stable and auditable
104
+
105
+ ## Status rule
106
+
107
+ `status.json` is the machine-readable state for the active change.
108
+
109
+ Use it to track:
110
+
111
+ - change type (backend | frontend | full-stack | infrastructure | docs)
112
+ - current stage
113
+ - verification state
114
+ - design alignment (if frontend)
115
+ - archival readiness
116
+ - next action
117
+
118
+ Do not use it as a replacement for the human-readable plan or proposal.
@@ -0,0 +1,36 @@
1
+ # Architecture Spec
2
+
3
+ ## System Shape
4
+
5
+ - Major modules and boundaries.
6
+
7
+ ## Data Flow
8
+
9
+ - Main request / event / state flow.
10
+
11
+ ## Technical Constraints
12
+
13
+ - Durable invariants and constraints.
14
+
15
+ ## Notes
16
+
17
+ - Long-lived architecture decisions land here after archive.
18
+
19
+
20
+ ## Change: timeline-analytics
21
+
22
+ Source: `specs/changes/timeline-analytics/merge-architecture.md`
23
+ Archived: 2026-04-16T15:52:04Z
24
+
25
+ - Timeline analytics remain derived data. `src/server.js` computes analytics from `getMissionDetail(...).timeline` and does not persist a second summary model.
26
+ - Active workflow run cleanup is centralized around the in-memory `activeWorkflowRuns` map plus `.as-xflow/active-runs.json` persistence. Orphan acknowledge deletes the matching active run entry, rewrites touched project roots, and updates the rerun record with `acknowledged_at` audit metadata.
27
+ - Rerun history is never physically deleted as part of orphan cleanup. Audit state stays in `reruns` and `operator_actions`; only the active-run control surface is cleared.
28
+
29
+
30
+ ## Change: handoff-current-state
31
+
32
+ Source: `specs/changes/handoff-current-state/merge-architecture.md`
33
+ Archived: 2026-04-16T16:09:18Z
34
+
35
+ - Root handoff current-state facts are now generated from local status and git state by `xflow/handoff/scripts/scaffold_handoff.py`.
36
+ - The generated handoff block is intentionally narrow: it does not synthesize a full Context Pack and does not query GitHub for merge state. It reduces drift for high-risk execution metadata while preserving human-authored durable context.
@@ -0,0 +1,33 @@
1
+ # Product Spec
2
+
3
+ ## Purpose
4
+
5
+ - What the product exists to do.
6
+
7
+ ## Core User Journeys
8
+
9
+ - Primary journey:
10
+
11
+ ## Scope Boundaries
12
+
13
+ - In scope:
14
+ - Out of scope:
15
+
16
+ ## Accepted Behavior
17
+
18
+ - Durable product requirements land here after archive.
19
+
20
+
21
+ ## Change: timeline-analytics
22
+
23
+ Source: `specs/changes/timeline-analytics/merge-product.md`
24
+ Archived: 2026-04-16T15:52:04Z
25
+
26
+ - Control-plane mission timeline now has a derived analytics endpoint:
27
+ - `GET /api/missions/:missionId/timeline/analytics`
28
+ - returns event totals, event kind distribution, time range, rerun status/mode counts, operator action kind/status counts, phase run counts, and phase run session derived-status counts.
29
+ - Operators can explicitly acknowledge a recovered orphan rerun:
30
+ - `POST /api/missions/:missionId/reruns/:rerunId` with `{"action":"acknowledge-orphan"}`
31
+ - only `orphaned` reruns are eligible.
32
+ - acknowledged orphan reruns remain auditable in mission detail as `canceled` and include a `rerun_orphan_acknowledge` operator action.
33
+ - acknowledged orphan runs are removed from active run summary and `.as-xflow/active-runs.json`.