stagemesh 0.6.0__py3-none-any.whl
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.
- stagemesh/__init__.py +7 -0
- stagemesh/_build_info.py +3 -0
- stagemesh/acceptance.py +121 -0
- stagemesh/acceptance_matrix.py +52 -0
- stagemesh/activity.py +989 -0
- stagemesh/activity_periods.py +282 -0
- stagemesh/agent_policy.py +241 -0
- stagemesh/agent_skills.py +519 -0
- stagemesh/api_server.py +1372 -0
- stagemesh/attribution.py +48 -0
- stagemesh/audit.py +71 -0
- stagemesh/auto_plan.py +497 -0
- stagemesh/autonomy/__init__.py +30 -0
- stagemesh/autonomy/base_state.py +291 -0
- stagemesh/autonomy/ci_diagnosis.py +644 -0
- stagemesh/autonomy/cli.py +219 -0
- stagemesh/autonomy/corpus.py +142 -0
- stagemesh/autonomy/decisions.py +325 -0
- stagemesh/autonomy/delivery.py +373 -0
- stagemesh/autonomy/dependencies.py +315 -0
- stagemesh/autonomy/destructive_git.py +104 -0
- stagemesh/autonomy/gitfacts.py +235 -0
- stagemesh/autonomy/github_adapter.py +310 -0
- stagemesh/autonomy/hooks.py +39 -0
- stagemesh/autonomy/integration.py +65 -0
- stagemesh/autonomy/isolation.py +313 -0
- stagemesh/autonomy/merge_policy.py +319 -0
- stagemesh/autonomy/provenance.py +385 -0
- stagemesh/autonomy/recovery_policy.py +148 -0
- stagemesh/autonomy/review_adapter.py +139 -0
- stagemesh/autonomy/review_policy.py +198 -0
- stagemesh/autonomy/scope.py +80 -0
- stagemesh/autonomy/supervisor.py +1302 -0
- stagemesh/autonomy/wiring.py +145 -0
- stagemesh/baseline.py +117 -0
- stagemesh/block_kinds.py +259 -0
- stagemesh/blocked_recovery.py +188 -0
- stagemesh/candidate_environments.py +363 -0
- stagemesh/candidate_inspection.py +211 -0
- stagemesh/capabilities.py +1580 -0
- stagemesh/capability_contracts.py +546 -0
- stagemesh/capability_discovery.py +341 -0
- stagemesh/capability_vendor.py +512 -0
- stagemesh/capacity.py +96 -0
- stagemesh/ci.py +76 -0
- stagemesh/ci_optimization.py +259 -0
- stagemesh/ci_validation_plan.py +356 -0
- stagemesh/ci_wait.py +27 -0
- stagemesh/claude_plugin_capabilities.py +344 -0
- stagemesh/cli.py +6188 -0
- stagemesh/completion_audit.py +112 -0
- stagemesh/concurrency.py +257 -0
- stagemesh/config.py +1146 -0
- stagemesh/config_migration.py +245 -0
- stagemesh/continuous_driver.py +628 -0
- stagemesh/contract_binding.py +176 -0
- stagemesh/contract_check.py +275 -0
- stagemesh/contract_feasibility.py +284 -0
- stagemesh/contracts.py +1428 -0
- stagemesh/coordinator.py +1320 -0
- stagemesh/dashboard.py +81 -0
- stagemesh/delivery_followup.py +493 -0
- stagemesh/delivery_state.py +223 -0
- stagemesh/demo.py +71 -0
- stagemesh/diagnosis.py +926 -0
- stagemesh/distributed.py +144 -0
- stagemesh/domain.py +109 -0
- stagemesh/driver_child.py +66 -0
- stagemesh/driver_scheduler.py +241 -0
- stagemesh/e2e_acceptance.py +66 -0
- stagemesh/e2e_evidence.py +486 -0
- stagemesh/efficiency.py +669 -0
- stagemesh/execution.py +755 -0
- stagemesh/execution_ownership.py +61 -0
- stagemesh/external_evidence.py +86 -0
- stagemesh/fast_forward.py +712 -0
- stagemesh/final_report.py +212 -0
- stagemesh/focused_validation.py +269 -0
- stagemesh/follow_through.py +227 -0
- stagemesh/followup_scheduler.py +103 -0
- stagemesh/gate_execution.py +188 -0
- stagemesh/gate_process.py +243 -0
- stagemesh/git.py +208 -0
- stagemesh/git_identity.py +310 -0
- stagemesh/github.py +278 -0
- stagemesh/github_acceptance.py +73 -0
- stagemesh/github_bootstrap.py +154 -0
- stagemesh/handoff.py +630 -0
- stagemesh/hands_off_recovery.py +54 -0
- stagemesh/integration.py +221 -0
- stagemesh/integration_recovery.py +266 -0
- stagemesh/landing_recovery.py +696 -0
- stagemesh/lifecycle.py +49 -0
- stagemesh/mcp_capabilities.py +302 -0
- stagemesh/mcp_proxy.py +288 -0
- stagemesh/migrations.py +203 -0
- stagemesh/objective_governance.py +1126 -0
- stagemesh/objective_roots.py +87 -0
- stagemesh/objectives.py +109 -0
- stagemesh/observability.py +212 -0
- stagemesh/operator.py +446 -0
- stagemesh/operator_actions.py +417 -0
- stagemesh/operator_attention.py +165 -0
- stagemesh/operator_control.py +390 -0
- stagemesh/operator_diagnostics.py +191 -0
- stagemesh/operator_doctor.py +256 -0
- stagemesh/operator_projects.py +136 -0
- stagemesh/operator_providers.py +355 -0
- stagemesh/outbound_lifecycle.py +115 -0
- stagemesh/parallel.py +1103 -0
- stagemesh/persistence.py +2046 -0
- stagemesh/persistence_backends.py +56 -0
- stagemesh/planning_execution.py +559 -0
- stagemesh/postgres_store.py +306 -0
- stagemesh/process_identity.py +151 -0
- stagemesh/profile.py +345 -0
- stagemesh/profile_default.py +93 -0
- stagemesh/profile_smoke.py +377 -0
- stagemesh/progress.py +245 -0
- stagemesh/provider_acceptance.py +556 -0
- stagemesh/provider_auth.py +184 -0
- stagemesh/provider_authorization.py +263 -0
- stagemesh/provider_catalog.py +118 -0
- stagemesh/provider_cooldown.py +175 -0
- stagemesh/provider_events.py +440 -0
- stagemesh/provider_pool.py +1348 -0
- stagemesh/providers.py +1838 -0
- stagemesh/quality_policy.py +293 -0
- stagemesh/queue_control.py +127 -0
- stagemesh/queue_reconcile.py +178 -0
- stagemesh/queue_run.py +226 -0
- stagemesh/queue_visibility.py +117 -0
- stagemesh/readiness.py +323 -0
- stagemesh/reattribution.py +73 -0
- stagemesh/recovery.py +1695 -0
- stagemesh/recovery_decision.py +234 -0
- stagemesh/redaction.py +130 -0
- stagemesh/registry.py +125 -0
- stagemesh/regression_orchestrator.py +1219 -0
- stagemesh/release.py +143 -0
- stagemesh/release_readiness.py +135 -0
- stagemesh/remediation.py +432 -0
- stagemesh/remediation_recovery.py +116 -0
- stagemesh/remote_hosting.py +138 -0
- stagemesh/research_context.py +645 -0
- stagemesh/retry.py +81 -0
- stagemesh/review.py +1041 -0
- stagemesh/review_disposition.py +299 -0
- stagemesh/review_identity.py +148 -0
- stagemesh/routing.py +116 -0
- stagemesh/run_ready.py +1230 -0
- stagemesh/run_window.py +1568 -0
- stagemesh/runtime_freshness.py +132 -0
- stagemesh/runtime_info.py +192 -0
- stagemesh/scheduling.py +59 -0
- stagemesh/security.py +24 -0
- stagemesh/selection_scope.py +300 -0
- stagemesh/serialized_integration.py +410 -0
- stagemesh/skill_packs/frontend-design/LICENSE.txt +177 -0
- stagemesh/skill_packs/frontend-design/SKILL.md +71 -0
- stagemesh/skill_packs/manifest.json +57 -0
- stagemesh/skill_packs/superpowers/LICENSE.txt +21 -0
- stagemesh/skill_packs/superpowers/receiving-code-review/SKILL.md +205 -0
- stagemesh/skill_packs/superpowers/systematic-debugging/SKILL.md +283 -0
- stagemesh/skill_packs/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
- stagemesh/skill_packs/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
- stagemesh/skill_packs/superpowers/systematic-debugging/defense-in-depth.md +122 -0
- stagemesh/skill_packs/superpowers/systematic-debugging/find-polluter.sh +72 -0
- stagemesh/skill_packs/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
- stagemesh/skill_packs/superpowers/test-driven-development/SKILL.md +330 -0
- stagemesh/skill_packs/superpowers/test-driven-development/writing-good-tests.md +198 -0
- stagemesh/skill_packs/superpowers/verification-before-completion/SKILL.md +120 -0
- stagemesh/spec_integrity.py +1390 -0
- stagemesh/spec_planning.py +578 -0
- stagemesh/spec_refs.py +93 -0
- stagemesh/stage_dispatch.py +48 -0
- stagemesh/step_progress.py +144 -0
- stagemesh/survivor_wave.py +1256 -0
- stagemesh/task_completion.py +236 -0
- stagemesh/task_selection.py +424 -0
- stagemesh/task_sources.py +685 -0
- stagemesh/test_isolation.py +291 -0
- stagemesh/test_taxonomy.py +999 -0
- stagemesh/timing.py +146 -0
- stagemesh/ui/app.css +57 -0
- stagemesh/ui/app.js +1691 -0
- stagemesh/ui/index.html +387 -0
- stagemesh/ui_launcher.py +129 -0
- stagemesh/validation.py +553 -0
- stagemesh/validation_components.py +353 -0
- stagemesh/validation_plan.py +489 -0
- stagemesh/validation_reuse.py +216 -0
- stagemesh/validation_services.py +969 -0
- stagemesh/validation_slot.py +228 -0
- stagemesh/visual_reference.py +283 -0
- stagemesh/window_journal.py +90 -0
- stagemesh/work_transport.py +125 -0
- stagemesh/workers.py +83 -0
- stagemesh/workspace_guard.py +1028 -0
- stagemesh/workspaces.py +351 -0
- stagemesh-0.6.0.dist-info/LICENSE +21 -0
- stagemesh-0.6.0.dist-info/METADATA +172 -0
- stagemesh-0.6.0.dist-info/RECORD +205 -0
- stagemesh-0.6.0.dist-info/WHEEL +4 -0
- stagemesh-0.6.0.dist-info/entry_points.txt +2 -0
stagemesh/__init__.py
ADDED
stagemesh/_build_info.py
ADDED
stagemesh/acceptance.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import time
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from .security import WorkspaceBoundary
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class AcceptanceCheck:
|
|
15
|
+
name: str
|
|
16
|
+
status: str
|
|
17
|
+
output: str
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AcceptanceValidationError(ValueError):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def run_check(name: str, command: list[str], cwd: Path) -> AcceptanceCheck:
|
|
25
|
+
name = _validate_text(name, "acceptance check name")
|
|
26
|
+
command = _validate_command(command)
|
|
27
|
+
cwd = _validate_root(cwd)
|
|
28
|
+
result = subprocess.run(command, cwd=cwd, text=True, capture_output=True, check=False)
|
|
29
|
+
status = "PASS" if result.returncode == 0 else "FAIL"
|
|
30
|
+
return AcceptanceCheck(name, status, result.stdout + result.stderr)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def local_acceptance_report(root: Path, include_acceptance: bool = True) -> dict[str, object]:
|
|
34
|
+
root = _validate_root(root)
|
|
35
|
+
checks = [
|
|
36
|
+
run_check("compile", [sys.executable, "-m", "compileall", "-q", "src", "scripts", "build_backend.py"], root),
|
|
37
|
+
run_check("invariants", [sys.executable, "scripts/invariants.py"], root),
|
|
38
|
+
run_check("provider_acceptance", [sys.executable, "scripts/provider_acceptance.py"], root),
|
|
39
|
+
run_check("github_acceptance", [sys.executable, "scripts/github_acceptance.py"], root),
|
|
40
|
+
run_check("live_acceptance", [sys.executable, "scripts/live_acceptance.py", "--json"], root),
|
|
41
|
+
run_check("clean_acceptance", [sys.executable, "scripts/clean_acceptance.py"], root),
|
|
42
|
+
run_check("install", [sys.executable, "-m", "pip", "install", ".", "--target", ".tmp-install", "--no-cache-dir", "--upgrade"], root),
|
|
43
|
+
]
|
|
44
|
+
if include_acceptance:
|
|
45
|
+
checks.insert(2, run_check("acceptance", [sys.executable, "scripts/acceptance.py"], root))
|
|
46
|
+
gaps = proof_gaps(checks)
|
|
47
|
+
return {
|
|
48
|
+
"generated_at": time.time(),
|
|
49
|
+
"status": "PASS" if all(check.status == "PASS" for check in checks) else "FAIL",
|
|
50
|
+
"proof_status": "BLOCKED_ON_EXTERNAL_EVIDENCE" if gaps else "PROVEN",
|
|
51
|
+
"proof_gaps": gaps,
|
|
52
|
+
"checks": [
|
|
53
|
+
{"name": check.name, "status": check.status, "output": check.output[-4000:]}
|
|
54
|
+
for check in checks
|
|
55
|
+
],
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def write_acceptance_report(root: Path, output: Path, include_acceptance: bool = True) -> None:
|
|
60
|
+
root = _validate_root(root)
|
|
61
|
+
output = WorkspaceBoundary(root).require_inside(output)
|
|
62
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
63
|
+
output.write_text(
|
|
64
|
+
json.dumps(local_acceptance_report(root, include_acceptance), indent=2, sort_keys=True),
|
|
65
|
+
encoding="utf-8",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def proof_gaps(checks: list[AcceptanceCheck]) -> list[dict[str, str]]:
|
|
70
|
+
gaps: list[dict[str, str]] = []
|
|
71
|
+
for check in checks:
|
|
72
|
+
parsed = _structured_proof_gaps(check)
|
|
73
|
+
if parsed:
|
|
74
|
+
gaps.extend(parsed)
|
|
75
|
+
continue
|
|
76
|
+
for line in check.output.splitlines():
|
|
77
|
+
if "NOT_CONFIGURED" in line or "NOT_PROVEN" in line:
|
|
78
|
+
gaps.append({"check": check.name, "evidence": line.strip()})
|
|
79
|
+
return gaps
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _structured_proof_gaps(check: AcceptanceCheck) -> list[dict[str, str]]:
|
|
83
|
+
try:
|
|
84
|
+
data = json.loads(check.output)
|
|
85
|
+
except json.JSONDecodeError:
|
|
86
|
+
return []
|
|
87
|
+
if not isinstance(data, dict) or not isinstance(data.get("checks"), list):
|
|
88
|
+
return []
|
|
89
|
+
gaps: list[dict[str, str]] = []
|
|
90
|
+
for item in data["checks"]:
|
|
91
|
+
if not isinstance(item, dict):
|
|
92
|
+
continue
|
|
93
|
+
name = item.get("name")
|
|
94
|
+
status = item.get("status")
|
|
95
|
+
if isinstance(name, str) and status in {"NOT_CONFIGURED", "NOT_PROVEN"}:
|
|
96
|
+
gaps.append({"check": check.name, "evidence": f"{name}: {status}"})
|
|
97
|
+
return gaps
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _validate_text(value: str, field: str, max_length: int = 200) -> str:
|
|
101
|
+
if not isinstance(value, str):
|
|
102
|
+
raise AcceptanceValidationError(f"{field} must be a string")
|
|
103
|
+
normalized = value.strip()
|
|
104
|
+
if not normalized:
|
|
105
|
+
raise AcceptanceValidationError(f"{field} must be a non-empty string")
|
|
106
|
+
if len(normalized) > max_length:
|
|
107
|
+
raise AcceptanceValidationError(f"{field} must be {max_length} characters or fewer")
|
|
108
|
+
return normalized
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _validate_command(command: list[str]) -> list[str]:
|
|
112
|
+
if not isinstance(command, list) or not command:
|
|
113
|
+
raise AcceptanceValidationError("acceptance command must be a non-empty list")
|
|
114
|
+
return [_validate_text(arg, "acceptance command argument", 1000) for arg in command]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _validate_root(root: Path) -> Path:
|
|
118
|
+
resolved = Path(root).resolve()
|
|
119
|
+
if not resolved.exists() or not resolved.is_dir():
|
|
120
|
+
raise AcceptanceValidationError("acceptance root must be an existing directory")
|
|
121
|
+
return resolved
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from .completion_audit import completion_audit
|
|
8
|
+
from .persistence import Store
|
|
9
|
+
from .security import WorkspaceBoundary
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AcceptanceMatrixValidationError(ValueError):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class MatrixRow:
|
|
18
|
+
area: str
|
|
19
|
+
status: str
|
|
20
|
+
evidence: str
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def acceptance_matrix(store: Store | None = None, candidate_sha: str | None = None) -> dict[str, object]:
|
|
24
|
+
audit = completion_audit(store, candidate_sha)
|
|
25
|
+
rows = [
|
|
26
|
+
MatrixRow(str(item["requirement"]), str(item["status"]), str(item["evidence"]))
|
|
27
|
+
for item in audit["items"]
|
|
28
|
+
]
|
|
29
|
+
proven = sum(1 for row in rows if row.status == "PROVEN")
|
|
30
|
+
return {
|
|
31
|
+
"status": "COMPLETE" if proven == len(rows) else "INCOMPLETE",
|
|
32
|
+
"proven": proven,
|
|
33
|
+
"total": len(rows),
|
|
34
|
+
"rows": [row.__dict__ for row in rows],
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def write_acceptance_matrix(
|
|
39
|
+
path: Path, store: Store | None = None, root: Path | None = None, candidate_sha: str | None = None
|
|
40
|
+
) -> None:
|
|
41
|
+
path = _validate_output(path, root)
|
|
42
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
path.write_text(json.dumps(acceptance_matrix(store, candidate_sha), indent=2, sort_keys=True), encoding="utf-8")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _validate_output(path: Path, root: Path | None) -> Path:
|
|
47
|
+
output = Path(path).resolve()
|
|
48
|
+
if root is not None:
|
|
49
|
+
return WorkspaceBoundary(Path(root).resolve()).require_inside(output)
|
|
50
|
+
if not output.name or output.is_dir():
|
|
51
|
+
raise AcceptanceMatrixValidationError("acceptance matrix output must name a file")
|
|
52
|
+
return output
|