@surlymochan/evalid 0.0.0-stage → 0.4.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 +94 -0
- package/LICENSE +21 -0
- package/README.md +315 -2
- package/RELEASE_NOTES.md +124 -0
- package/atoms/registry.json +758 -0
- package/bin/xflow.js +7261 -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 +96 -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 +1130 -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 +1014 -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 +481 -0
- package/workflows/yolo.yaml +241 -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 +107 -0
- package/xflow/atoms/i6b_tdd_proof_validate.py +184 -0
- package/xflow/atoms/i6c_tdd_quality_review.py +372 -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 +956 -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 +47 -0
- package/xflow/ralph/SKILL.md +123 -0
- package/xflow/scripts/check_installed_xflow_skill_sync.sh +44 -0
- package/xflow/scripts/common.py +483 -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 +75 -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,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())
|
package/specs/README.md
ADDED
|
@@ -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.
|
package/specs/product.md
ADDED
|
@@ -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`.
|