platformforge 0.1.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.
Files changed (659) hide show
  1. platformforge/__init__.py +7 -0
  2. platformforge/__main__.py +5 -0
  3. platformforge/_forge_portal.py +913 -0
  4. platformforge/_graphstudio.py +376 -0
  5. platformforge/_graphview.py +181 -0
  6. platformforge/_installkit.py +1706 -0
  7. platformforge/agents/__init__.py +156 -0
  8. platformforge/agents/bench.py +61 -0
  9. platformforge/agents/contextpack.py +137 -0
  10. platformforge/agents/contracts.py +394 -0
  11. platformforge/agents/coordinators.py +98 -0
  12. platformforge/agents/critic.py +113 -0
  13. platformforge/agents/debate.py +161 -0
  14. platformforge/agents/executors.py +160 -0
  15. platformforge/agents/guardian.py +48 -0
  16. platformforge/agents/mirrors.py +240 -0
  17. platformforge/agents/orchestrator.py +295 -0
  18. platformforge/agents/planner.py +116 -0
  19. platformforge/agents/playbook.py +51 -0
  20. platformforge/agents/referee.py +132 -0
  21. platformforge/agents/reviewers.py +113 -0
  22. platformforge/agents/roster.py +893 -0
  23. platformforge/agents/runledger.py +85 -0
  24. platformforge/agents/runstore.py +74 -0
  25. platformforge/agents/specialists.py +73 -0
  26. platformforge/agents/taskspec.py +94 -0
  27. platformforge/agents/uniqueness.py +115 -0
  28. platformforge/agents/verifier.py +106 -0
  29. platformforge/aiplat/__init__.py +4 -0
  30. platformforge/aiplat/models.py +175 -0
  31. platformforge/analytics/__init__.py +6 -0
  32. platformforge/analytics/capacity.py +109 -0
  33. platformforge/analytics/debt.py +92 -0
  34. platformforge/analytics/dx.py +69 -0
  35. platformforge/analytics/finops_v4.py +171 -0
  36. platformforge/analytics/goldenpath.py +131 -0
  37. platformforge/analytics/history.py +233 -0
  38. platformforge/analytics/measurement.py +149 -0
  39. platformforge/analytics/models.py +127 -0
  40. platformforge/analytics/opsanalytics.py +119 -0
  41. platformforge/analytics/policyintel.py +139 -0
  42. platformforge/analytics/reliability.py +106 -0
  43. platformforge/analytics/soak.py +135 -0
  44. platformforge/analytics/store.py +254 -0
  45. platformforge/bench.py +174 -0
  46. platformforge/cases/__init__.py +13 -0
  47. platformforge/cases/casefile.py +106 -0
  48. platformforge/cases/context_audit.py +134 -0
  49. platformforge/cases/ledgers.py +174 -0
  50. platformforge/cases/replay.py +142 -0
  51. platformforge/cases/routing_audit.py +162 -0
  52. platformforge/caveman/__init__.py +11 -0
  53. platformforge/caveman/compress.py +156 -0
  54. platformforge/cicd/__init__.py +16 -0
  55. platformforge/cicd/backstage.py +51 -0
  56. platformforge/cicd/dockerfile.py +64 -0
  57. platformforge/cicd/github_actions.py +122 -0
  58. platformforge/cicd/gitlab_ci.py +56 -0
  59. platformforge/cicd/gitops.py +130 -0
  60. platformforge/cli/__init__.py +0 -0
  61. platformforge/cli/fleetcmd.py +457 -0
  62. platformforge/cli/main.py +3832 -0
  63. platformforge/cloud/__init__.py +8 -0
  64. platformforge/cloud/aws.py +254 -0
  65. platformforge/cloud/common.py +69 -0
  66. platformforge/cloud/multicloud.py +143 -0
  67. platformforge/collect/__init__.py +11 -0
  68. platformforge/collect/detect.py +254 -0
  69. platformforge/context/__init__.py +10 -0
  70. platformforge/context/capsule.py +60 -0
  71. platformforge/context/gateway.py +227 -0
  72. platformforge/context/refs.py +49 -0
  73. platformforge/context/sufficiency.py +50 -0
  74. platformforge/core/__init__.py +1 -0
  75. platformforge/core/hashing.py +39 -0
  76. platformforge/core/ownership.py +220 -0
  77. platformforge/core/receipts.py +74 -0
  78. platformforge/core/redaction.py +97 -0
  79. platformforge/core/store.py +119 -0
  80. platformforge/core/workspace.py +89 -0
  81. platformforge/data/contracts/agent-handoff.schema.json +26 -0
  82. platformforge/data/contracts/agent-run.schema.json +27 -0
  83. platformforge/data/contracts/agent-spec.schema.json +43 -0
  84. platformforge/data/contracts/capability.schema.json +23 -0
  85. platformforge/data/contracts/change-event.schema.json +22 -0
  86. platformforge/data/contracts/change-intent.schema.json +62 -0
  87. platformforge/data/contracts/change-plan.schema.json +43 -0
  88. platformforge/data/contracts/collector-receipt.schema.json +36 -0
  89. platformforge/data/contracts/context-pack.schema.json +29 -0
  90. platformforge/data/contracts/debate.schema.json +31 -0
  91. platformforge/data/contracts/distribution-manifest-v1.schema.json +81 -0
  92. platformforge/data/contracts/drift-event.schema.json +21 -0
  93. platformforge/data/contracts/fact.schema.json +35 -0
  94. platformforge/data/contracts/finding.schema.json +20 -0
  95. platformforge/data/contracts/graph-v2.schema.json +67 -0
  96. platformforge/data/contracts/graph.schema.json +40 -0
  97. platformforge/data/contracts/install-receipt-v1.schema.json +49 -0
  98. platformforge/data/contracts/observation.schema.json +93 -0
  99. platformforge/data/contracts/receipt.schema.json +21 -0
  100. platformforge/data/contracts/recommendation.schema.json +32 -0
  101. platformforge/data/contracts/refusal.schema.json +16 -0
  102. platformforge/data/contracts/slo-contract.schema.json +25 -0
  103. platformforge/data/contracts/task-spec.schema.json +37 -0
  104. platformforge/data/contracts/workspace-manifest-v1.schema.json +62 -0
  105. platformforge/data/evals/cases/agent-budget-exhaustion/case.yaml +6 -0
  106. platformforge/data/evals/cases/agent-conflicting-specialists/case.yaml +11 -0
  107. platformforge/data/evals/cases/agent-fleet-optimization/case.yaml +13 -0
  108. platformforge/data/evals/cases/agent-host-no-subagents/case.yaml +6 -0
  109. platformforge/data/evals/cases/agent-incident-multi/case.yaml +13 -0
  110. platformforge/data/evals/cases/agent-missing-evidence/case.yaml +6 -0
  111. platformforge/data/evals/cases/agent-multi-domain-audit/case.yaml +14 -0
  112. platformforge/data/evals/cases/agent-production-change/case.yaml +15 -0
  113. platformforge/data/evals/cases/agent-security-mandatory/case.yaml +12 -0
  114. platformforge/data/evals/cases/agent-simple-iac/case.yaml +14 -0
  115. platformforge/data/evals/cases/approval-integrity-seal/case.yaml +6 -0
  116. platformforge/data/evals/cases/capacity-hot/case.yaml +7 -0
  117. platformforge/data/evals/cases/capacity-hot/fixture/capacity.json +5 -0
  118. platformforge/data/evals/cases/catalog-noowner/case.yaml +7 -0
  119. platformforge/data/evals/cases/catalog-noowner/fixture/catalog-info.yaml +6 -0
  120. platformforge/data/evals/cases/contract-fact/case.yaml +5 -0
  121. platformforge/data/evals/cases/contract-fact/fixture/doc.json +2 -0
  122. platformforge/data/evals/cases/cosign-unverified/case.yaml +8 -0
  123. platformforge/data/evals/cases/cosign-unverified/fixture/sig.json +33 -0
  124. platformforge/data/evals/cases/expected-delta-refusal/case.yaml +6 -0
  125. platformforge/data/evals/cases/finops-noattr/case.yaml +9 -0
  126. platformforge/data/evals/cases/finops-noattr/fixture/costs.json +7 -0
  127. platformforge/data/evals/cases/fleet-inv-absent-allocation-unknown/case.yaml +7 -0
  128. platformforge/data/evals/cases/fleet-inv-centrality-not-criticality/case.yaml +7 -0
  129. platformforge/data/evals/cases/fleet-inv-correlation-not-causality/case.yaml +7 -0
  130. platformforge/data/evals/cases/fleet-inv-dx-no-person-metrics/case.yaml +7 -0
  131. platformforge/data/evals/cases/fleet-inv-federation-restricted-denied/case.yaml +7 -0
  132. platformforge/data/evals/cases/fleet-inv-federation-secret-denied/case.yaml +7 -0
  133. platformforge/data/evals/cases/fleet-inv-history-window-deterministic/case.yaml +7 -0
  134. platformforge/data/evals/cases/fleet-inv-low-util-not-deletable/case.yaml +7 -0
  135. platformforge/data/evals/cases/fleet-inv-member-key-deterministic/case.yaml +7 -0
  136. platformforge/data/evals/cases/fleet-inv-missing-denominator/case.yaml +7 -0
  137. platformforge/data/evals/cases/fleet-inv-partial-coverage-visible/case.yaml +7 -0
  138. platformforge/data/evals/cases/fleet-inv-plan-changeintent-only/case.yaml +7 -0
  139. platformforge/data/evals/cases/fleet-inv-report-all-cited/case.yaml +7 -0
  140. platformforge/data/evals/cases/fleet-inv-small-sample-confidence/case.yaml +7 -0
  141. platformforge/data/evals/cases/fleet-inv-uncertain-optimization-suppressed/case.yaml +7 -0
  142. platformforge/data/evals/cases/gha-dangerous/case.yaml +12 -0
  143. platformforge/data/evals/cases/gha-dangerous/fixture/.github/workflows/ci.yaml +11 -0
  144. platformforge/data/evals/cases/gitops-v2/case.yaml +11 -0
  145. platformforge/data/evals/cases/gitops-v2/fixture/argo.yaml +41 -0
  146. platformforge/data/evals/cases/graph-k8s-blast/case.yaml +7 -0
  147. platformforge/data/evals/cases/graph-k8s-blast/fixture/deploy.yaml +15 -0
  148. platformforge/data/evals/cases/iac-module-nopin/case.yaml +8 -0
  149. platformforge/data/evals/cases/iac-module-nopin/fixture/main.tf +3 -0
  150. platformforge/data/evals/cases/iac-plan-replace/case.yaml +8 -0
  151. platformforge/data/evals/cases/iac-plan-replace/fixture/plan.json +12 -0
  152. platformforge/data/evals/cases/iac-sg-open/case.yaml +8 -0
  153. platformforge/data/evals/cases/iac-sg-open/fixture/main.tf +9 -0
  154. platformforge/data/evals/cases/iam-oidc/case.yaml +8 -0
  155. platformforge/data/evals/cases/iam-oidc/fixture/policy.json +11 -0
  156. platformforge/data/evals/cases/iam-wildcard-positive/case.yaml +8 -0
  157. platformforge/data/evals/cases/iam-wildcard-positive/fixture/policy.json +3 -0
  158. platformforge/data/evals/cases/k8s-bad-actor/case.yaml +19 -0
  159. platformforge/data/evals/cases/k8s-bad-actor/fixture/app.yaml +97 -0
  160. platformforge/data/evals/cases/k8s-beta-api/case.yaml +8 -0
  161. platformforge/data/evals/cases/k8s-beta-api/fixture/cr.yaml +7 -0
  162. platformforge/data/evals/cases/k8s-dep-api-boundary/case.yaml +15 -0
  163. platformforge/data/evals/cases/k8s-dep-api-boundary/fixture/app.yaml +25 -0
  164. platformforge/data/evals/cases/k8s-dep-api-clean/case.yaml +12 -0
  165. platformforge/data/evals/cases/k8s-dep-api-clean/fixture/app.yaml +29 -0
  166. platformforge/data/evals/cases/k8s-dep-api-unknown/case.yaml +11 -0
  167. platformforge/data/evals/cases/k8s-dep-api-unknown/fixture/app.yaml +25 -0
  168. platformforge/data/evals/cases/k8s-dep-api-v120/case.yaml +12 -0
  169. platformforge/data/evals/cases/k8s-dep-api-v120/fixture/app.yaml +25 -0
  170. platformforge/data/evals/cases/k8s-dep-api-v129/case.yaml +9 -0
  171. platformforge/data/evals/cases/k8s-dep-api-v129/fixture/app.yaml +25 -0
  172. platformforge/data/evals/cases/k8s-hpa-noreq/case.yaml +8 -0
  173. platformforge/data/evals/cases/k8s-hpa-noreq/fixture/app.yaml +28 -0
  174. platformforge/data/evals/cases/k8s-limits-boundary/case.yaml +10 -0
  175. platformforge/data/evals/cases/k8s-limits-boundary/fixture/app.yaml +15 -0
  176. platformforge/data/evals/cases/k8s-limits-negative/case.yaml +8 -0
  177. platformforge/data/evals/cases/k8s-limits-negative/fixture/deploy.yaml +15 -0
  178. platformforge/data/evals/cases/k8s-limits-positive/case.yaml +8 -0
  179. platformforge/data/evals/cases/k8s-limits-positive/fixture/deploy.yaml +14 -0
  180. platformforge/data/evals/cases/k8s-nopdb/case.yaml +7 -0
  181. platformforge/data/evals/cases/k8s-nopdb/fixture/app.yaml +34 -0
  182. platformforge/data/evals/cases/knowledge-registry/case.yaml +10 -0
  183. platformforge/data/evals/cases/kyverno-dep/case.yaml +10 -0
  184. platformforge/data/evals/cases/kyverno-dep/fixture/pol.yaml +18 -0
  185. platformforge/data/evals/cases/kyverno-legacy/case.yaml +8 -0
  186. platformforge/data/evals/cases/kyverno-legacy/fixture/pol.yaml +7 -0
  187. platformforge/data/evals/cases/live-aws-collect/case.yaml +11 -0
  188. platformforge/data/evals/cases/live-aws-collect/fixture/aws/ec2_describe-vpcs.json +15 -0
  189. platformforge/data/evals/cases/live-aws-collect/fixture/aws/iam_list-users.denied.txt +1 -0
  190. platformforge/data/evals/cases/live-aws-collect/fixture/aws/sts_get-caller-identity.json +5 -0
  191. platformforge/data/evals/cases/live-drift/case.yaml +8 -0
  192. platformforge/data/evals/cases/live-drift/fixture/after.json +22 -0
  193. platformforge/data/evals/cases/live-drift/fixture/before.json +22 -0
  194. platformforge/data/evals/cases/live-incident/case.yaml +7 -0
  195. platformforge/data/evals/cases/live-incident/fixture/changes.json +8 -0
  196. platformforge/data/evals/cases/live-incident/fixture/incident.json +7 -0
  197. platformforge/data/evals/cases/live-k8s-collect/case.yaml +10 -0
  198. platformforge/data/evals/cases/live-k8s-collect/fixture/kubectl/get_configmaps.denied.txt +1 -0
  199. platformforge/data/evals/cases/live-k8s-collect/fixture/kubectl/get_deployments.apps.json +25 -0
  200. platformforge/data/evals/cases/live-k8s-collect/fixture/kubectl/get_pods.json +17 -0
  201. platformforge/data/evals/cases/live-k8s-collect/fixture/kubectl/get_secrets.json +13 -0
  202. platformforge/data/evals/cases/live-multicluster/case.yaml +7 -0
  203. platformforge/data/evals/cases/live-multicluster/fixture/clusters.json +6 -0
  204. platformforge/data/evals/cases/live-plan/case.yaml +7 -0
  205. platformforge/data/evals/cases/live-plan/fixture/drift.json +8 -0
  206. platformforge/data/evals/cases/live-reconcile/case.yaml +7 -0
  207. platformforge/data/evals/cases/live-reconcile/fixture/desired.json +7 -0
  208. platformforge/data/evals/cases/live-reconcile/fixture/observed.json +18 -0
  209. platformforge/data/evals/cases/live-secrets-boundary/case.yaml +8 -0
  210. platformforge/data/evals/cases/live-secrets-boundary/fixture/envelope.json +16 -0
  211. platformforge/data/evals/cases/live-temporal-graph/case.yaml +10 -0
  212. platformforge/data/evals/cases/live-temporal-graph/fixture/graph.json +22 -0
  213. platformforge/data/evals/cases/ops-approval/case.yaml +6 -0
  214. platformforge/data/evals/cases/ops-convergence/case.yaml +6 -0
  215. platformforge/data/evals/cases/ops-execution-safety/case.yaml +6 -0
  216. platformforge/data/evals/cases/ops-intent/case.yaml +6 -0
  217. platformforge/data/evals/cases/ops-planning/case.yaml +6 -0
  218. platformforge/data/evals/cases/ops-policy/case.yaml +6 -0
  219. platformforge/data/evals/cases/ops-rollback/case.yaml +6 -0
  220. platformforge/data/evals/cases/ops-verification/case.yaml +6 -0
  221. platformforge/data/evals/cases/rollback-argocd-revision/case.yaml +6 -0
  222. platformforge/data/evals/cases/rollback-blind-inverse/case.yaml +6 -0
  223. platformforge/data/evals/cases/rollback-git-commit/case.yaml +6 -0
  224. platformforge/data/evals/cases/rollback-impossible/case.yaml +6 -0
  225. platformforge/data/evals/cases/rollback-k8s-annotation-restore/case.yaml +6 -0
  226. platformforge/data/evals/cases/rollback-k8s-scale/case.yaml +6 -0
  227. platformforge/data/evals/cases/rollback-material-tamper/case.yaml +6 -0
  228. platformforge/data/evals/cases/rollback-terraform-replan/case.yaml +6 -0
  229. platformforge/data/evals/cases/rollback-unknown/case.yaml +6 -0
  230. platformforge/data/evals/cases/routing-specialist/case.yaml +9 -0
  231. platformforge/data/evals/cases/rtk-roundtrip/case.yaml +5 -0
  232. platformforge/data/evals/cases/rtk-roundtrip/fixture/verbose.txt +300 -0
  233. platformforge/data/evals/cases/sbom-vuln/case.yaml +9 -0
  234. platformforge/data/evals/cases/sbom-vuln/fixture/sbom.json +9 -0
  235. platformforge/data/evals/cases/secret-prose-mixed/fixture/app.env +1 -0
  236. platformforge/data/evals/cases/secret-prose-mixed/fixture/policy-notes.md +7 -0
  237. platformforge/data/evals/cases/secrets-noleak/case.yaml +5 -0
  238. platformforge/data/evals/cases/secrets-noleak/fixture/app.env +2 -0
  239. platformforge/data/evals/cases/slo-fastburn/case.yaml +8 -0
  240. platformforge/data/evals/cases/slo-fastburn/fixture/events.yaml +2 -0
  241. platformforge/data/evals/cases/slo-fastburn/fixture/slo.yaml +4 -0
  242. platformforge/data/evals/cases/slo-noinput/case.yaml +8 -0
  243. platformforge/data/evals/cases/slo-noinput/fixture/events.yaml +1 -0
  244. platformforge/data/evals/cases/slo-noinput/fixture/slo.yaml +4 -0
  245. platformforge/data/evals/cases/sot-conflict/case.yaml +6 -0
  246. platformforge/data/evals/cases/token-budget/case.yaml +6 -0
  247. platformforge/data/evals/cases/token-budget/fixture/big.py +50 -0
  248. platformforge/data/evals/cases/xr-delete/case.yaml +8 -0
  249. platformforge/data/evals/cases/xr-delete/fixture/xr.yaml +10 -0
  250. platformforge/data/evals/cases/xr-graph-chain/case.yaml +8 -0
  251. platformforge/data/evals/cases/xr-graph-chain/fixture/xrd.yaml +90 -0
  252. platformforge/data/evals/cases/xr-negative-crd/case.yaml +8 -0
  253. platformforge/data/evals/cases/xr-negative-crd/fixture/widget.yaml +19 -0
  254. platformforge/data/evals/cases/xr-upbound-mr/case.yaml +8 -0
  255. platformforge/data/evals/cases/xr-upbound-mr/fixture/bucket.yaml +12 -0
  256. platformforge/data/evals/qpt-bench/change-review/case.yaml +5 -0
  257. platformforge/data/evals/qpt-bench/change-review/fixture/plan.json +9 -0
  258. platformforge/data/evals/qpt-bench/gha-security/case.yaml +5 -0
  259. platformforge/data/evals/qpt-bench/gha-security/fixture/ci.yml +10 -0
  260. platformforge/data/evals/qpt-bench/iam-investigate/case.yaml +5 -0
  261. platformforge/data/evals/qpt-bench/iam-investigate/fixture/policy.json +6 -0
  262. platformforge/data/evals/qpt-bench/incident-analysis/case.yaml +5 -0
  263. platformforge/data/evals/qpt-bench/incident-analysis/fixture/query.json +5 -0
  264. platformforge/data/evals/qpt-bench/incident-analysis/fixture/rules.yaml +6 -0
  265. platformforge/data/evals/qpt-bench/k8s-review/case.yaml +6 -0
  266. platformforge/data/evals/qpt-bench/k8s-review/fixture/deploy.yaml +15 -0
  267. platformforge/data/evals/qpt-bench/tf-security/case.yaml +5 -0
  268. platformforge/data/evals/qpt-bench/tf-security/fixture/main.tf +17 -0
  269. platformforge/data/knowledge/aws/eks.yaml +20 -0
  270. platformforge/data/knowledge/aws/iam.yaml +28 -0
  271. platformforge/data/knowledge/aws/network-exposure.yaml +19 -0
  272. platformforge/data/knowledge/aws/organizations.yaml +19 -0
  273. platformforge/data/knowledge/crossplane/composition-providers.yaml +20 -0
  274. platformforge/data/knowledge/crossplane/managed-resources.yaml +26 -0
  275. platformforge/data/knowledge/crossplane/v1-v2.yaml +25 -0
  276. platformforge/data/knowledge/kubernetes/api-deprecations.yaml +33 -0
  277. platformforge/data/knowledge/kubernetes/autoscaling-rbac.yaml +27 -0
  278. platformforge/data/knowledge/kubernetes/gateway-api.yaml +20 -0
  279. platformforge/data/knowledge/kubernetes/pod-security.yaml +26 -0
  280. platformforge/data/knowledge/sources.yaml +516 -0
  281. platformforge/data/knowledge/terraform/lifecycle.yaml +18 -0
  282. platformforge/data/knowledge/terraform/plan-semantics.yaml +26 -0
  283. platformforge/data/lab/chaos-pod-kill/chaos.yaml +3 -0
  284. platformforge/data/lab/chaos-pod-kill/facts.json +13 -0
  285. platformforge/data/lab/fleets/acme/capacity.yaml +35 -0
  286. platformforge/data/lab/fleets/acme/costs.yaml +25 -0
  287. platformforge/data/lab/fleets/acme/events.yaml +41 -0
  288. platformforge/data/lab/fleets/acme/fleet.yaml +51 -0
  289. platformforge/data/lab/fleets/acme/graph.yaml +45 -0
  290. platformforge/data/lab/fleets/acme/policies.yaml +28 -0
  291. platformforge/data/lab/fleets/acme/requests.yaml +24 -0
  292. platformforge/data/lab/scenarios/argo-bad-rollout/expected.yaml +6 -0
  293. platformforge/data/lab/scenarios/argo-bad-rollout/fixture/app.yaml +9 -0
  294. platformforge/data/lab/scenarios/aws-dump/expected.yaml +19 -0
  295. platformforge/data/lab/scenarios/aws-dump/fixture/compute.json +4 -0
  296. platformforge/data/lab/scenarios/aws-dump/fixture/iam.json +7 -0
  297. platformforge/data/lab/scenarios/aws-dump/fixture/network.json +6 -0
  298. platformforge/data/lab/scenarios/aws-dump/fixture/org.json +4 -0
  299. platformforge/data/lab/scenarios/aws-dump/fixture/storage.json +4 -0
  300. platformforge/data/lab/scenarios/container-unsigned/expected.yaml +5 -0
  301. platformforge/data/lab/scenarios/container-unsigned/fixture/supply.json +11 -0
  302. platformforge/data/lab/scenarios/cost-idle-workload/expected.yaml +5 -0
  303. platformforge/data/lab/scenarios/cost-idle-workload/fixture/costs.json +12 -0
  304. platformforge/data/lab/scenarios/crossplane-platform/expected.yaml +16 -0
  305. platformforge/data/lab/scenarios/crossplane-platform/fixture/negative.yaml +18 -0
  306. platformforge/data/lab/scenarios/crossplane-platform/fixture/xrd.yaml +90 -0
  307. platformforge/data/lab/scenarios/demo-platform/expected.yaml +16 -0
  308. platformforge/data/lab/scenarios/demo-platform/fixture/.github/workflows/ci.yml +10 -0
  309. platformforge/data/lab/scenarios/demo-platform/fixture/deploy.yaml +16 -0
  310. platformforge/data/lab/scenarios/demo-platform/fixture/infra.tf +5 -0
  311. platformforge/data/lab/scenarios/fleet-ai/expected.yaml +12 -0
  312. platformforge/data/lab/scenarios/fleet-capacity/expected.yaml +12 -0
  313. platformforge/data/lab/scenarios/fleet-cost/expected.yaml +18 -0
  314. platformforge/data/lab/scenarios/fleet-federation/expected.yaml +11 -0
  315. platformforge/data/lab/scenarios/fleet-golden-path/expected.yaml +18 -0
  316. platformforge/data/lab/scenarios/fleet-op-hotspot/expected.yaml +11 -0
  317. platformforge/data/lab/scenarios/fleet-ownership/expected.yaml +17 -0
  318. platformforge/data/lab/scenarios/fleet-partial/expected.yaml +10 -0
  319. platformforge/data/lab/scenarios/fleet-policy-friction/expected.yaml +10 -0
  320. platformforge/data/lab/scenarios/fleet-recurring-incident/expected.yaml +12 -0
  321. platformforge/data/lab/scenarios/fleet-report/expected.yaml +13 -0
  322. platformforge/data/lab/scenarios/fleet-risk/expected.yaml +18 -0
  323. platformforge/data/lab/scenarios/gitops-drift/expected.yaml +6 -0
  324. platformforge/data/lab/scenarios/gitops-drift/fixture/app.yaml +12 -0
  325. platformforge/data/lab/scenarios/k8s-bad-readiness/expected.yaml +6 -0
  326. platformforge/data/lab/scenarios/k8s-bad-readiness/fixture/deploy.yaml +23 -0
  327. platformforge/data/lab/scenarios/k8s-bad-readiness/fixture/netpol.yaml +9 -0
  328. platformforge/data/lab/scenarios/k8s-missing-limits/expected.yaml +6 -0
  329. platformforge/data/lab/scenarios/k8s-missing-limits/fixture/deploy.yaml +26 -0
  330. platformforge/data/lab/scenarios/k8s-missing-limits/fixture/netpol.yaml +9 -0
  331. platformforge/data/lab/scenarios/k8s-single-replica/expected.yaml +5 -0
  332. platformforge/data/lab/scenarios/k8s-single-replica/fixture/deploy.yaml +26 -0
  333. platformforge/data/lab/scenarios/k8s-single-replica/fixture/netpol.yaml +4 -0
  334. platformforge/data/lab/scenarios/live-aws-collect/expected.yaml +4 -0
  335. platformforge/data/lab/scenarios/live-aws-collect/fixture/aws/ec2_describe-vpcs.json +15 -0
  336. platformforge/data/lab/scenarios/live-aws-collect/fixture/aws/iam_list-users.denied.txt +1 -0
  337. platformforge/data/lab/scenarios/live-aws-collect/fixture/aws/sts_get-caller-identity.json +5 -0
  338. platformforge/data/lab/scenarios/live-k8s-collect/expected.yaml +4 -0
  339. platformforge/data/lab/scenarios/live-k8s-collect/fixture/kubectl/get_configmaps.denied.txt +1 -0
  340. platformforge/data/lab/scenarios/live-k8s-collect/fixture/kubectl/get_deployments.apps.json +25 -0
  341. platformforge/data/lab/scenarios/live-k8s-collect/fixture/kubectl/get_pods.json +17 -0
  342. platformforge/data/lab/scenarios/live-k8s-collect/fixture/kubectl/get_secrets.json +13 -0
  343. platformforge/data/lab/scenarios/live-kind/expected.yaml +14 -0
  344. platformforge/data/lab/scenarios/live-kind/fixture/kubectl/get_configmaps.denied.txt +1 -0
  345. platformforge/data/lab/scenarios/live-kind/fixture/kubectl/get_deployments.apps.json +25 -0
  346. platformforge/data/lab/scenarios/live-kind/fixture/kubectl/get_pods.json +17 -0
  347. platformforge/data/lab/scenarios/live-kind/fixture/kubectl/get_secrets.json +13 -0
  348. platformforge/data/lab/scenarios/network-policy-missing/expected.yaml +6 -0
  349. platformforge/data/lab/scenarios/network-policy-missing/fixture/deploy.yaml +26 -0
  350. platformforge/data/lab/scenarios/ops-bad-rollout/expected.yaml +3 -0
  351. platformforge/data/lab/scenarios/ops-bad-rollout/fixture/ops.yaml +33 -0
  352. platformforge/data/lab/scenarios/ops-break-glass/expected.yaml +3 -0
  353. platformforge/data/lab/scenarios/ops-break-glass/fixture/ops.yaml +21 -0
  354. platformforge/data/lab/scenarios/ops-broken-selector/expected.yaml +3 -0
  355. platformforge/data/lab/scenarios/ops-broken-selector/fixture/ops.yaml +21 -0
  356. platformforge/data/lab/scenarios/ops-changed-plan-hash/expected.yaml +3 -0
  357. platformforge/data/lab/scenarios/ops-changed-plan-hash/fixture/ops.yaml +20 -0
  358. platformforge/data/lab/scenarios/ops-conflicting-operation/expected.yaml +3 -0
  359. platformforge/data/lab/scenarios/ops-conflicting-operation/fixture/ops.yaml +21 -0
  360. platformforge/data/lab/scenarios/ops-expired-approval/expected.yaml +3 -0
  361. platformforge/data/lab/scenarios/ops-expired-approval/fixture/ops.yaml +20 -0
  362. platformforge/data/lab/scenarios/ops-partial-failure/expected.yaml +3 -0
  363. platformforge/data/lab/scenarios/ops-partial-failure/fixture/ops.yaml +24 -0
  364. platformforge/data/lab/scenarios/ops-policy-denial/expected.yaml +3 -0
  365. platformforge/data/lab/scenarios/ops-policy-denial/fixture/ops.yaml +17 -0
  366. platformforge/data/lab/scenarios/ops-replica-drift/expected.yaml +3 -0
  367. platformforge/data/lab/scenarios/ops-replica-drift/fixture/ops.yaml +28 -0
  368. platformforge/data/lab/scenarios/ops-rollback-annotate/expected.yaml +3 -0
  369. platformforge/data/lab/scenarios/ops-rollback-annotate/fixture/ops.yaml +41 -0
  370. platformforge/data/lab/scenarios/ops-rollback-gitops/expected.yaml +3 -0
  371. platformforge/data/lab/scenarios/ops-rollback-gitops/fixture/ops.yaml +38 -0
  372. platformforge/data/lab/scenarios/ops-rollback-impossible/expected.yaml +3 -0
  373. platformforge/data/lab/scenarios/ops-rollback-impossible/fixture/ops.yaml +34 -0
  374. platformforge/data/lab/scenarios/ops-rollback-scale/expected.yaml +3 -0
  375. platformforge/data/lab/scenarios/ops-rollback-scale/fixture/ops.yaml +40 -0
  376. platformforge/data/lab/scenarios/ops-rollback-terraform/expected.yaml +3 -0
  377. platformforge/data/lab/scenarios/ops-rollback-terraform/fixture/ops.yaml +38 -0
  378. platformforge/data/lab/scenarios/ops-rollback-terraform/fixture/tf/tfplan.bin +1 -0
  379. platformforge/data/lab/scenarios/ops-stale-observation/expected.yaml +3 -0
  380. platformforge/data/lab/scenarios/ops-stale-observation/fixture/ops.yaml +20 -0
  381. platformforge/data/lab/scenarios/secret-exposure/expected.yaml +5 -0
  382. platformforge/data/lab/scenarios/secret-exposure/fixture/app.env +2 -0
  383. platformforge/data/lab/scenarios/slo-burn/expected.yaml +5 -0
  384. platformforge/data/lab/scenarios/slo-burn/fixture/events.yaml +2 -0
  385. platformforge/data/lab/scenarios/slo-burn/fixture/slo.yaml +4 -0
  386. platformforge/data/lab/scenarios/terraform-iam-wildcard/expected.yaml +5 -0
  387. platformforge/data/lab/scenarios/terraform-iam-wildcard/fixture/policy.json +14 -0
  388. platformforge/data/lab/scenarios/terraform-public-bucket/expected.yaml +6 -0
  389. platformforge/data/lab/scenarios/terraform-public-bucket/fixture/main.tf +5 -0
  390. platformforge/data/portable_skills/platformforge-agents/SKILL.md +47 -0
  391. platformforge/data/portable_skills/platformforge-change/SKILL.md +41 -0
  392. platformforge/data/portable_skills/platformforge-core/SKILL.md +62 -0
  393. platformforge/data/portable_skills/platformforge-economy/SKILL.md +42 -0
  394. platformforge/data/portable_skills/platformforge-finops/SKILL.md +34 -0
  395. platformforge/data/portable_skills/platformforge-fleet/SKILL.md +39 -0
  396. platformforge/data/portable_skills/platformforge-governance/SKILL.md +76 -0
  397. platformforge/data/portable_skills/platformforge-graph/SKILL.md +46 -0
  398. platformforge/data/portable_skills/platformforge-lab/SKILL.md +39 -0
  399. platformforge/data/portable_skills/platformforge-sdd/SKILL.md +39 -0
  400. platformforge/data/portable_skills/platformforge-security/SKILL.md +38 -0
  401. platformforge/data/portable_skills/platformforge-sre/SKILL.md +41 -0
  402. platformforge/data/rules/catalog/finops.yaml +26 -0
  403. platformforge/data/rules/catalog/gitops.yaml +161 -0
  404. platformforge/data/rules/catalog/iac.yaml +84 -0
  405. platformforge/data/rules/catalog/k8s.yaml +322 -0
  406. platformforge/data/rules/catalog/orchestration.yaml +99 -0
  407. platformforge/data/rules/catalog/product.yaml +42 -0
  408. platformforge/data/rules/catalog/routing.yaml +122 -0
  409. platformforge/data/rules/catalog/security.yaml +159 -0
  410. platformforge/data/rules/catalog/sre.yaml +67 -0
  411. platformforge/diagnose/__init__.py +75 -0
  412. platformforge/distribution/__init__.py +18 -0
  413. platformforge/distribution/bundle.py +127 -0
  414. platformforge/distribution/hostflow.py +247 -0
  415. platformforge/distribution/models.py +80 -0
  416. platformforge/distribution/service.py +225 -0
  417. platformforge/economy/__init__.py +27 -0
  418. platformforge/economy/bench.py +66 -0
  419. platformforge/economy/budget.py +198 -0
  420. platformforge/economy/cache.py +287 -0
  421. platformforge/economy/checkpoint.py +112 -0
  422. platformforge/economy/collection.py +142 -0
  423. platformforge/economy/doctor.py +207 -0
  424. platformforge/economy/engine.py +158 -0
  425. platformforge/economy/envelope.py +61 -0
  426. platformforge/economy/fleetpack.py +86 -0
  427. platformforge/economy/ledger.py +232 -0
  428. platformforge/economy/plan.py +131 -0
  429. platformforge/economy/pricing.py +101 -0
  430. platformforge/economy/qpt.py +286 -0
  431. platformforge/economy/reconcile.py +86 -0
  432. platformforge/economy/verifyplan.py +107 -0
  433. platformforge/economy/waste.py +123 -0
  434. platformforge/evals/__init__.py +16 -0
  435. platformforge/evals/coverage.py +140 -0
  436. platformforge/evals/fleet_invariants.py +260 -0
  437. platformforge/evals/ops_invariants.py +158 -0
  438. platformforge/evals/runner.py +541 -0
  439. platformforge/federation/__init__.py +4 -0
  440. platformforge/federation/node.py +135 -0
  441. platformforge/finops/__init__.py +14 -0
  442. platformforge/finops/alloc.py +31 -0
  443. platformforge/finops/costs.py +79 -0
  444. platformforge/finops/focus.py +100 -0
  445. platformforge/finops/graph_cost.py +51 -0
  446. platformforge/finops/ingest.py +144 -0
  447. platformforge/finops/insights.py +193 -0
  448. platformforge/finops/unit.py +36 -0
  449. platformforge/fleet/__init__.py +5 -0
  450. platformforge/fleet/loader.py +73 -0
  451. platformforge/fleet/models.py +155 -0
  452. platformforge/fleet/orggraph.py +172 -0
  453. platformforge/fleet/query.py +154 -0
  454. platformforge/forge/__init__.py +9 -0
  455. platformforge/forge/collect.py +88 -0
  456. platformforge/forge/delegate.py +77 -0
  457. platformforge/forge/manifest.py +106 -0
  458. platformforge/freeze/__init__.py +22 -0
  459. platformforge/freeze/exceptions.py +56 -0
  460. platformforge/freeze/manifest.py +167 -0
  461. platformforge/freeze/snapshots.py +108 -0
  462. platformforge/graph/__init__.py +39 -0
  463. platformforge/graph/backend.py +174 -0
  464. platformforge/graph/bench.py +245 -0
  465. platformforge/graph/build.py +130 -0
  466. platformforge/graph/delivery.py +183 -0
  467. platformforge/graph/diff.py +292 -0
  468. platformforge/graph/events.py +116 -0
  469. platformforge/graph/migrate.py +44 -0
  470. platformforge/graph/model.py +264 -0
  471. platformforge/graph/persist.py +97 -0
  472. platformforge/graph/query.py +290 -0
  473. platformforge/graph/temporal.py +78 -0
  474. platformforge/graph/vocab.py +63 -0
  475. platformforge/graphview.py +94 -0
  476. platformforge/iac/__init__.py +7 -0
  477. platformforge/iac/drift.py +53 -0
  478. platformforge/iac/plan.py +84 -0
  479. platformforge/iac/terraform.py +123 -0
  480. platformforge/install/__init__.py +1 -0
  481. platformforge/install/service.py +421 -0
  482. platformforge/k8s/__init__.py +8 -0
  483. platformforge/k8s/helm.py +152 -0
  484. platformforge/k8s/hubble.py +87 -0
  485. platformforge/k8s/manifests.py +513 -0
  486. platformforge/knowledge/__init__.py +1 -0
  487. platformforge/knowledge/packs.py +157 -0
  488. platformforge/knowledge/registry.py +249 -0
  489. platformforge/knowledge/select.py +127 -0
  490. platformforge/lab/__init__.py +5 -0
  491. platformforge/lab/chaos.py +71 -0
  492. platformforge/lab/fleetlab.py +351 -0
  493. platformforge/lab/opslab.py +271 -0
  494. platformforge/lab/runner.py +219 -0
  495. platformforge/live/__init__.py +36 -0
  496. platformforge/live/budget.py +92 -0
  497. platformforge/live/capability.py +80 -0
  498. platformforge/live/collectors/__init__.py +6 -0
  499. platformforge/live/collectors/aws.py +370 -0
  500. platformforge/live/collectors/aws_transport.py +98 -0
  501. platformforge/live/collectors/k8s.py +389 -0
  502. platformforge/live/collectors/k8s_transport.py +85 -0
  503. platformforge/live/cursors.py +48 -0
  504. platformforge/live/drift.py +130 -0
  505. platformforge/live/envelope.py +85 -0
  506. platformforge/live/federation.py +113 -0
  507. platformforge/live/fixtures.py +168 -0
  508. platformforge/live/identity.py +258 -0
  509. platformforge/live/incident.py +200 -0
  510. platformforge/live/models.py +435 -0
  511. platformforge/live/reconcile.py +382 -0
  512. platformforge/live/remediate.py +169 -0
  513. platformforge/live/store.py +256 -0
  514. platformforge/live/topology.py +249 -0
  515. platformforge/mcp/__init__.py +7 -0
  516. platformforge/mcp/parity.py +69 -0
  517. platformforge/mcp/registry.py +427 -0
  518. platformforge/mcp/server.py +84 -0
  519. platformforge/mcp/tools.py +732 -0
  520. platformforge/models/__init__.py +21 -0
  521. platformforge/models/base.py +214 -0
  522. platformforge/observe/__init__.py +26 -0
  523. platformforge/observe/capacity.py +39 -0
  524. platformforge/observe/dr.py +67 -0
  525. platformforge/observe/grafana.py +76 -0
  526. platformforge/observe/incident.py +58 -0
  527. platformforge/observe/otel.py +135 -0
  528. platformforge/observe/postmortem.py +72 -0
  529. platformforge/observe/prometheus.py +88 -0
  530. platformforge/observe/slo.py +125 -0
  531. platformforge/ops/__init__.py +8 -0
  532. platformforge/ops/actions.py +215 -0
  533. platformforge/ops/analytics.py +83 -0
  534. platformforge/ops/approval.py +275 -0
  535. platformforge/ops/autorem.py +101 -0
  536. platformforge/ops/config.py +175 -0
  537. platformforge/ops/engine.py +758 -0
  538. platformforge/ops/envelope.py +135 -0
  539. platformforge/ops/executors/__init__.py +1 -0
  540. platformforge/ops/executors/base.py +211 -0
  541. platformforge/ops/executors/git.py +77 -0
  542. platformforge/ops/executors/gitops.py +134 -0
  543. platformforge/ops/executors/terraform.py +84 -0
  544. platformforge/ops/gates.py +135 -0
  545. platformforge/ops/goldenpath.py +180 -0
  546. platformforge/ops/material.py +181 -0
  547. platformforge/ops/models.py +421 -0
  548. platformforge/ops/operation.py +335 -0
  549. platformforge/ops/opgraph.py +233 -0
  550. platformforge/ops/policy.py +275 -0
  551. platformforge/ops/preconditions.py +109 -0
  552. platformforge/ops/registry.py +101 -0
  553. platformforge/ops/risk.py +216 -0
  554. platformforge/ops/rollback.py +287 -0
  555. platformforge/ops/rollback_builders.py +163 -0
  556. platformforge/ops/runbook.py +269 -0
  557. platformforge/ops/simulate.py +125 -0
  558. platformforge/ops/source_of_truth.py +198 -0
  559. platformforge/ops/store.py +157 -0
  560. platformforge/ops/verify.py +190 -0
  561. platformforge/optimize/__init__.py +4 -0
  562. platformforge/optimize/engine.py +109 -0
  563. platformforge/optimize/models.py +68 -0
  564. platformforge/optimize/scan.py +196 -0
  565. platformforge/plan/__init__.py +107 -0
  566. platformforge/portable_cli.py +199 -0
  567. platformforge/portal_adapter.py +740 -0
  568. platformforge/portal_assets/chunk-7_l-b4Tr.js +1 -0
  569. platformforge/portal_assets/chunk-B0Iad6pD.js +1 -0
  570. platformforge/portal_assets/chunk-B605XnCF.js +1 -0
  571. platformforge/portal_assets/chunk-B7N3TXcn.js +1 -0
  572. platformforge/portal_assets/chunk-BAj6yGem.js +1 -0
  573. platformforge/portal_assets/chunk-BGUitn2r.js +1 -0
  574. platformforge/portal_assets/chunk-BVKnCv85.js +1 -0
  575. platformforge/portal_assets/chunk-BYyM9V_w.js +1 -0
  576. platformforge/portal_assets/chunk-BaQMhq-G.js +1 -0
  577. platformforge/portal_assets/chunk-BavOrxVm.js +1 -0
  578. platformforge/portal_assets/chunk-Bb0C24YV.js +1 -0
  579. platformforge/portal_assets/chunk-BfCFGPzs.js +1 -0
  580. platformforge/portal_assets/chunk-C2t4OUVu.js +1 -0
  581. platformforge/portal_assets/chunk-C3pI4QjU.js +1 -0
  582. platformforge/portal_assets/chunk-C4gpbtbP.js +1 -0
  583. platformforge/portal_assets/chunk-CGWeHhKY.js +1 -0
  584. platformforge/portal_assets/chunk-CJCT86Dr.js +1 -0
  585. platformforge/portal_assets/chunk-CXcsLDPJ.js +1 -0
  586. platformforge/portal_assets/chunk-CcjxoLxw.js +1 -0
  587. platformforge/portal_assets/chunk-D-gBPXHa.js +1 -0
  588. platformforge/portal_assets/chunk-D3eZogIe.js +1 -0
  589. platformforge/portal_assets/chunk-DQU0VyoQ.js +1 -0
  590. platformforge/portal_assets/chunk-DqWNkF1O.js +1 -0
  591. platformforge/portal_assets/chunk-DuPPkSIE.js +3 -0
  592. platformforge/portal_assets/chunk-DyIHOW_a.js +1 -0
  593. platformforge/portal_assets/chunk-Fx4zSGL5.js +1 -0
  594. platformforge/portal_assets/chunk-UBKt05Rg.js +1 -0
  595. platformforge/portal_assets/chunk-htnJDQEY.js +1 -0
  596. platformforge/portal_assets/chunk-kXRFMGqe.js +1 -0
  597. platformforge/portal_assets/chunk-qe3u763a.js +1 -0
  598. platformforge/portal_assets/favicon.ico +0 -0
  599. platformforge/portal_assets/index.html +13 -0
  600. platformforge/portal_assets/main-QDFVZK3T.js +5 -0
  601. platformforge/portal_assets/styles-MQEBDFDX.css +1 -0
  602. platformforge/product/__init__.py +10 -0
  603. platformforge/product/backstage.py +49 -0
  604. platformforge/product/catalog.py +74 -0
  605. platformforge/product/crossplane.py +341 -0
  606. platformforge/product/golden_paths/__init__.py +5 -0
  607. platformforge/product/golden_paths/engine.py +97 -0
  608. platformforge/product/golden_paths/library.yaml +198 -0
  609. platformforge/product/golden_paths/model.py +84 -0
  610. platformforge/product/maturity.py +107 -0
  611. platformforge/product/scorecards.py +84 -0
  612. platformforge/resources.py +36 -0
  613. platformforge/risk/__init__.py +5 -0
  614. platformforge/risk/engine.py +95 -0
  615. platformforge/risk/signals.py +49 -0
  616. platformforge/routing/__init__.py +13 -0
  617. platformforge/routing/decision.py +191 -0
  618. platformforge/routing/router.py +328 -0
  619. platformforge/rtk/__init__.py +9 -0
  620. platformforge/rtk/compact.py +127 -0
  621. platformforge/rtk/parsers.py +199 -0
  622. platformforge/rules/__init__.py +5 -0
  623. platformforge/rules/engine.py +345 -0
  624. platformforge/sandbox/__init__.py +7 -0
  625. platformforge/sandbox/env.py +151 -0
  626. platformforge/sandbox/review.py +92 -0
  627. platformforge/sdd/__init__.py +8 -0
  628. platformforge/sdd/lifecycle.py +239 -0
  629. platformforge/security/__init__.py +19 -0
  630. platformforge/security/cosign.py +67 -0
  631. platformforge/security/iam.py +112 -0
  632. platformforge/security/identity.py +84 -0
  633. platformforge/security/kyverno.py +106 -0
  634. platformforge/security/sbom.py +59 -0
  635. platformforge/security/scan.py +63 -0
  636. platformforge/security/slsa.py +86 -0
  637. platformforge/security/supply.py +62 -0
  638. platformforge/tokensave/__init__.py +20 -0
  639. platformforge/tokensave/budget.py +62 -0
  640. platformforge/tokensave/estimate.py +21 -0
  641. platformforge/tokensave/index.py +172 -0
  642. platformforge/tokensave/ledger.py +121 -0
  643. platformforge/tokensave/packs.py +285 -0
  644. platformforge/ui/__init__.py +28 -0
  645. platformforge/ui/app.py +465 -0
  646. platformforge/ui/home.py +113 -0
  647. platformforge/ui/i18n.py +143 -0
  648. platformforge/ui/kit.py +689 -0
  649. platformforge/ui/screen.py +628 -0
  650. platformforge/ui/tui.py +94 -0
  651. platformforge/ui/wizard.py +309 -0
  652. platformforge/workspace/__init__.py +13 -0
  653. platformforge/workspace/models.py +35 -0
  654. platformforge/workspace/service.py +69 -0
  655. platformforge-0.1.0.dist-info/METADATA +212 -0
  656. platformforge-0.1.0.dist-info/RECORD +659 -0
  657. platformforge-0.1.0.dist-info/WHEEL +4 -0
  658. platformforge-0.1.0.dist-info/entry_points.txt +3 -0
  659. platformforge-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,85 @@
1
+ """Agent run ledger — per-run economy accounting (§117).
2
+
3
+ Every agent invocation appends one row: model calls, context bytes,
4
+ output bytes, tool calls, agents used, fanout, duration, cache reuse.
5
+ Separate from TokenLedger (which tracks context engineering); this
6
+ tracks *agentic* spend so quality-per-token can be compared across
7
+ single-specialist vs coordinated strategies (§118–121).
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import time
14
+ from dataclasses import asdict, dataclass, field
15
+ from pathlib import Path
16
+ from typing import Any
17
+
18
+
19
+ @dataclass
20
+ class AgentRunRow:
21
+ run_id: str
22
+ agent: str
23
+ mode: str = "single-specialist" # router mode for comparability
24
+ model_calls: int = 0
25
+ context_bytes: int = 0
26
+ output_bytes: int = 0
27
+ tool_calls: int = 0
28
+ agents: int = 1
29
+ fanout: int = 0
30
+ duration_ms: float = 0.0
31
+ cache_reuse_bytes: int = 0 # §115 shared-pack reuse
32
+ delta_bytes: int = 0 # §116 delta-context savings
33
+ token_basis: str = "unknown" # observed|estimated|unknown
34
+ transcript_ref: str | None = None
35
+ ts: float = field(default_factory=time.time)
36
+ extra: dict[str, Any] = field(default_factory=dict)
37
+
38
+ def __post_init__(self) -> None:
39
+ if self.token_basis not in ("observed", "estimated", "unknown"):
40
+ raise ValueError(f"bad token_basis {self.token_basis!r}")
41
+ if self.token_basis == "observed" and not self.transcript_ref:
42
+ raise ValueError(
43
+ "observed token counts require transcript_ref")
44
+
45
+ def to_dict(self) -> dict[str, Any]:
46
+ return asdict(self)
47
+
48
+
49
+ class AgentRunLedger:
50
+ def __init__(self, root: str | Path):
51
+ self.dir = Path(root) / ".platformforge" / "ledger"
52
+ self.dir.mkdir(parents=True, exist_ok=True)
53
+ self.path = self.dir / "agent-runs.jsonl"
54
+
55
+ def record(self, row: AgentRunRow) -> None:
56
+ with open(self.path, "a") as fh:
57
+ fh.write(json.dumps(row.to_dict(), default=str) + "\n")
58
+
59
+ def rows(self) -> list[dict[str, Any]]:
60
+ if not self.path.exists():
61
+ return []
62
+ return [json.loads(l) for l in self.path.read_text().splitlines()
63
+ if l.strip()]
64
+
65
+ def report(self) -> dict[str, Any]:
66
+ rows = self.rows()
67
+ def tot(k): return sum(r.get(k) or 0 for r in rows)
68
+ by_mode: dict[str, dict[str, Any]] = {}
69
+ for r in rows:
70
+ m = by_mode.setdefault(r.get("mode", "?"), {
71
+ "runs": 0, "model_calls": 0, "context_bytes": 0,
72
+ "tool_calls": 0, "duration_ms": 0.0,
73
+ "cache_reuse_bytes": 0})
74
+ m["runs"] += 1
75
+ for k in ("model_calls", "context_bytes", "tool_calls",
76
+ "duration_ms", "cache_reuse_bytes"):
77
+ m[k] += r.get(k) or 0
78
+ return {"runs": len(rows), "agents_invoked": tot("agents"),
79
+ "model_calls": tot("model_calls"),
80
+ "context_bytes": tot("context_bytes"),
81
+ "output_bytes": tot("output_bytes"),
82
+ "tool_calls": tot("tool_calls"),
83
+ "cache_reuse_bytes": tot("cache_reuse_bytes"),
84
+ "delta_savings_bytes": tot("delta_bytes"),
85
+ "by_mode": by_mode}
@@ -0,0 +1,74 @@
1
+ """Agent run store — .platformforge/runs/ (§135–142).
2
+
3
+ Append-only run records: task spec hash, router decision, agents,
4
+ handoffs, budget, evidence refs, debates, gates, verifier, verdict.
5
+ This is run *memory* — receipts and refs, not long-term agent memory
6
+ (§134) and never user-specific context (§137).
7
+
8
+ Resume preserves spent budget and prior evidence/decisions; it
9
+ revalidates artifact hashes and observation freshness before
10
+ continuing (§141–142).
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ from platformforge.agents.contracts import AgentRunRecord
20
+
21
+
22
+ class RunStore:
23
+ def __init__(self, root: str | Path):
24
+ self.dir = Path(root) / ".platformforge" / "runs"
25
+ self.dir.mkdir(parents=True, exist_ok=True)
26
+
27
+ def _path(self, run_id: str) -> Path:
28
+ if "/" in run_id or ".." in run_id:
29
+ raise ValueError(f"bad run_id {run_id!r}")
30
+ return self.dir / f"{run_id}.json"
31
+
32
+ def save(self, record: AgentRunRecord) -> Path:
33
+ p = self._path(record.run_id)
34
+ p.write_text(json.dumps(record.to_dict(), indent=2,
35
+ sort_keys=True, default=str))
36
+ return p
37
+
38
+ def load(self, run_id: str) -> AgentRunRecord | None:
39
+ p = self._path(run_id)
40
+ if not p.is_file():
41
+ return None
42
+ return AgentRunRecord.from_dict(json.loads(p.read_text()))
43
+
44
+ def runs(self) -> list[str]:
45
+ return sorted(p.stem for p in self.dir.glob("*.json"))
46
+
47
+ def resume(self, run_id: str, *, artifact_hashes: dict[str, str] |
48
+ None = None,
49
+ observation_freshness: str | None = None,
50
+ ) -> dict[str, Any]:
51
+ """§141–142 — resume preserves spent budget/decisions and
52
+ revalidates hashes + freshness before allowing continuation."""
53
+ rec = self.load(run_id)
54
+ if rec is None:
55
+ return {"resumed": False,
56
+ "reason": f"no run record {run_id} — nothing to "
57
+ "resume; start a new run"}
58
+ problems = []
59
+ if artifact_hashes:
60
+ for ref, h in artifact_hashes.items():
61
+ if not h:
62
+ problems.append(f"{ref}: hash unreadable — "
63
+ "re-collect before resume")
64
+ if observation_freshness in ("stale", "superseded", "conflicted"):
65
+ problems.append(
66
+ f"observation freshness is {observation_freshness} — "
67
+ "re-collect runtime evidence before resume")
68
+ return {"resumed": not problems, "run_id": run_id,
69
+ "problems": problems,
70
+ "preserved": {"budget_spent": rec.budget.get("spent"),
71
+ "evidence": list(rec.evidence),
72
+ "decisions": list(rec.debates),
73
+ "verdict": rec.verdict},
74
+ "note": "budget is never reset on resume (§141)"}
@@ -0,0 +1,73 @@
1
+ """Specialist machinery — the §98/§99 finding contract.
2
+
3
+ Every specialist finding is a structured record — claim, status,
4
+ evidence, coverage, freshness, confidence, limitations, next_action —
5
+ never bare prose. `finding()` validates the shape; `grade()` demotes
6
+ any status the evidence cannot carry (no evidence → never confirmed).
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Any
12
+
13
+ from platformforge.agents.contracts import OUTPUT_STATUSES, AgentRefusal, refusal
14
+ from platformforge.models.base import stable_id
15
+
16
+ # statuses that REQUIRE at least one evidence ref (§98 + §55)
17
+ _EVIDENCE_STATUSES = ("confirmed", "supported", "refuted")
18
+
19
+
20
+ def finding(agent: str, claim: str, *, status: str,
21
+ evidence: tuple[str, ...] = (),
22
+ coverage: float | None = None,
23
+ freshness: str = "unresolved",
24
+ confidence: str = "low",
25
+ limitations: tuple[str, ...] = (),
26
+ next_action: str = "") -> dict[str, Any]:
27
+ """One specialist finding. `status` ∈ OUTPUT_STATUSES; evidence
28
+ statuses with no evidence are demoted to `unsupported` with the
29
+ demotion recorded — never silently upgraded (§98)."""
30
+ if status not in OUTPUT_STATUSES:
31
+ return refusal(
32
+ AgentRefusal.HOST_CAPABILITY,
33
+ f"status {status!r} outside OUTPUT_STATUSES",
34
+ "use one of: " + ", ".join(OUTPUT_STATUSES))
35
+ demoted = False
36
+ asked = status
37
+ if status in _EVIDENCE_STATUSES and not evidence:
38
+ demoted = True
39
+ status = "unsupported"
40
+ limitations = tuple(limitations) + (
41
+ "demoted: status required evidence but none was cited",)
42
+ if coverage is not None:
43
+ try:
44
+ coverage = min(max(float(coverage), 0.0), 1.0)
45
+ except (TypeError, ValueError):
46
+ coverage = None
47
+ doc = {"finding_id": stable_id("PF-FND", agent, claim),
48
+ "agent": agent, "claim": claim, "status": status,
49
+ "evidence": list(evidence),
50
+ "coverage": coverage, "freshness": freshness,
51
+ "confidence": confidence,
52
+ "limitations": list(limitations),
53
+ "next_action": next_action}
54
+ if demoted:
55
+ doc["demoted_from"] = asked
56
+ doc["demoted"] = True
57
+ return doc
58
+
59
+
60
+ def grade(findings: list[dict[str, Any]]) -> dict[str, Any]:
61
+ """Aggregate findings — counts per status; unsupported/absence is
62
+ surfaced, not hidden behind totals (§98)."""
63
+ by_status: dict[str, int] = {}
64
+ demoted = 0
65
+ for f in findings:
66
+ by_status[f.get("status", "unresolved")] = \
67
+ by_status.get(f.get("status", "unresolved"), 0) + 1
68
+ demoted += 1 if f.get("demoted") else 0
69
+ return {"total": len(findings), "by_status": by_status,
70
+ "demoted": demoted,
71
+ "ok": by_status.get("confirmed", 0)
72
+ + by_status.get("supported", 0)
73
+ + by_status.get("refuted", 0) > 0}
@@ -0,0 +1,94 @@
1
+ """TaskSpec lifecycle — the deterministic `platform-task-spec-reviewer`.
2
+
3
+ Review (§16) validates scope, evidence requirements, risk, rollback,
4
+ acceptance criteria, unknowns and operation boundaries BEFORE any
5
+ orchestration. A spec that fails review is rejected with notes; a spec
6
+ that passes is `reviewed`, then `seal()`ed — sealed specs are
7
+ content-hashed so the orchestrator executes exactly what was reviewed.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any
13
+
14
+ from platformforge.agents.contracts import AgentRefusal, PlatformTaskSpec, refusal
15
+
16
+ MUTATING_CAPS = ("ops.apply", "ops.approve", "federation.delegate",
17
+ "change.apply", "cloud.mutate")
18
+
19
+ # risk levels that force stronger governance on the spec itself
20
+ _GOVERNED_RISK = ("high", "critical")
21
+
22
+
23
+ def review(spec: PlatformTaskSpec,
24
+ reviewer: str = "platform-task-spec-reviewer") -> PlatformTaskSpec:
25
+ """draft → reviewed | rejected. Deterministic, explainable notes."""
26
+ if spec.state != "draft":
27
+ return spec # only drafts are reviewed; caller sees current state
28
+ notes: list[str] = []
29
+ if not spec.intent.strip():
30
+ notes.append("intent is empty — nothing to plan against")
31
+ if not spec.acceptance_criteria:
32
+ notes.append("no acceptance_criteria — verifier would have "
33
+ "nothing to check")
34
+ if not spec.evidence_requirements:
35
+ notes.append("no evidence_requirements — conclusions would be "
36
+ "unverifiable")
37
+ if spec.risk in _GOVERNED_RISK:
38
+ if spec.rollback_requirement == "none":
39
+ notes.append(f"risk={spec.risk} requires a declared or "
40
+ "material-bound rollback requirement")
41
+ missing = [c for c in MUTATING_CAPS
42
+ if c not in spec.forbidden_capabilities]
43
+ if missing:
44
+ notes.append("risky spec must explicitly forbid: "
45
+ + ", ".join(missing))
46
+ if spec.autonomy not in ("read-only", "propose", "simulate"):
47
+ notes.append(f"autonomy {spec.autonomy!r} outside read-only/"
48
+ "propose/simulate — agents never execute")
49
+ if spec.budget not in ("tiny", "small", "standard", "deep",
50
+ "critical"):
51
+ notes.append(f"unknown budget class {spec.budget!r}")
52
+ if not spec.domains and spec.complexity != "low":
53
+ notes.append("non-trivial spec with no domains — scope is "
54
+ "unbounded")
55
+ if notes:
56
+ return spec.transition("rejected", reviewer=reviewer,
57
+ notes=tuple(notes))
58
+ return spec.transition("reviewed", reviewer=reviewer,
59
+ notes=(("scope/evidence/risk/rollback/"
60
+ "criteria validated"),))
61
+
62
+
63
+ def seal(spec: PlatformTaskSpec) -> PlatformTaskSpec | dict[str, Any]:
64
+ """reviewed → sealed. Only sealed specs may orchestrate (§18)."""
65
+ if spec.state == "rejected":
66
+ return refusal(
67
+ AgentRefusal.SPEC_REJECTED,
68
+ "task spec was rejected: " + "; ".join(spec.review_notes),
69
+ "revise the spec against the review notes and re-review")
70
+ if spec.state != "reviewed":
71
+ return refusal(
72
+ AgentRefusal.SPEC_UNSEALED,
73
+ f"spec is {spec.state!r}, expected 'reviewed'",
74
+ "run the task-spec reviewer first")
75
+ return spec.transition("sealed")
76
+
77
+
78
+ def expire(spec: PlatformTaskSpec) -> PlatformTaskSpec:
79
+ return spec.transition("expired")
80
+
81
+
82
+ def require_sealed(spec: PlatformTaskSpec,
83
+ complex_: bool = True) -> dict[str, Any] | None:
84
+ """§18 — orchestrators refuse unsealed specs for complex work.
85
+ Returns None when OK, else the refusal doc."""
86
+ if spec.state == "sealed":
87
+ return None
88
+ if not complex_ and spec.state == "reviewed":
89
+ return None
90
+ return refusal(
91
+ AgentRefusal.SPEC_UNSEALED,
92
+ f"orchestration requires a sealed TaskSpec (state={spec.state})",
93
+ "platformforge agents plan → review-spec → seal, then dispatch",
94
+ spec_state=spec.state)
@@ -0,0 +1,115 @@
1
+ """Agent fan-out economy (§117–129): uniqueness audit + selective
2
+ agentics helpers.
3
+
4
+ Per-run audit measures who actually contributed — unique vs duplicated
5
+ vs refuted vs discarded contribution (§118). An agent that adds nothing
6
+ is a candidate for routing reduction (§119) — a recommendation, never
7
+ auto-applied (§115). No leaderboard: agents are graded as contribution
8
+ records, not ranked as people (§120).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import asdict, dataclass, field
14
+ from typing import Any
15
+
16
+
17
+ @dataclass
18
+ class AgentContribution:
19
+ agent: str
20
+ contribution_ids: list[str] = field(default_factory=list)
21
+ # finding/artifact ids the agent uniquely produced
22
+ refuted: list[str] = field(default_factory=list)
23
+ discarded: list[str] = field(default_factory=list)
24
+
25
+
26
+ @dataclass
27
+ class AgentUniqueness:
28
+ """§117 — per-run fanout audit."""
29
+ run_id: str = ""
30
+ agents_invoked: list[str] = field(default_factory=list)
31
+ unique_contribution: dict[str, list[str]] = field(default_factory=dict)
32
+ duplicated_contribution: dict[str, list[str]] = field(
33
+ default_factory=dict)
34
+ refuted_contribution: dict[str, list[str]] = field(default_factory=dict)
35
+ discarded_contribution: dict[str, list[str]] = field(
36
+ default_factory=dict)
37
+ findings: list[dict[str, Any]] = field(default_factory=list)
38
+
39
+ def audit(self, contributions: list[AgentContribution]
40
+ ) -> AgentUniqueness:
41
+ """Classify each agent's output ids: an id claimed by ≥2 agents is
42
+ duplicated for the later claimants; refuted/discarded buckets come
43
+ from the contribution rows themselves."""
44
+ seen: dict[str, str] = {}
45
+ for c in contributions:
46
+ self.agents_invoked.append(c.agent)
47
+ unique, dup = [], []
48
+ for cid in c.contribution_ids:
49
+ if cid in seen:
50
+ dup.append(cid)
51
+ else:
52
+ seen[cid] = c.agent
53
+ unique.append(cid)
54
+ if unique:
55
+ self.unique_contribution[c.agent] = unique
56
+ if dup:
57
+ self.duplicated_contribution[c.agent] = dup
58
+ if c.refuted:
59
+ self.refuted_contribution[c.agent] = list(c.refuted)
60
+ if c.discarded:
61
+ self.discarded_contribution[c.agent] = list(c.discarded)
62
+ if not unique and not c.refuted and not c.discarded \
63
+ and not dup:
64
+ self.findings.append({
65
+ "waste_type": "unused_agent", "agent": c.agent,
66
+ "confidence": "high",
67
+ "evidence": "invoked with zero contribution ids",
68
+ "recommended_fix": "review routing rule — candidate "
69
+ "for fanout reduction"})
70
+ elif not unique and (dup or c.refuted or c.discarded):
71
+ self.findings.append({
72
+ "waste_type": "unused_agent", "agent": c.agent,
73
+ "confidence": "medium",
74
+ "evidence": "all contribution ids duplicated, "
75
+ "refuted or discarded",
76
+ "recommended_fix": "routing review — contribution "
77
+ "overlapped entirely"})
78
+ return self
79
+
80
+ def to_dict(self) -> dict[str, Any]:
81
+ d = asdict(self)
82
+ d["agents_invoked_count"] = len(self.agents_invoked)
83
+ d["unique_ratio"] = (
84
+ sum(len(v) for v in self.unique_contribution.values()) /
85
+ max(1, sum(len(v) for v in self.unique_contribution.values())
86
+ + sum(len(v) for v in self.duplicated_contribution.values())))
87
+ return d
88
+
89
+
90
+ # §123 — selective agentics policy (data, not judgment).
91
+ def suggested_fanout(task_type: str, domains: list[str], risk: str,
92
+ conflict: bool = False) -> dict[str, Any]:
93
+ """simple → ≤1 specialist; cross-domain → multi; conflict/high-risk
94
+ → debate/review. Mirrors the Router V2 policy as an economy check."""
95
+ if conflict or risk in ("high", "critical"):
96
+ mode, agents = "debate-or-review", 3
97
+ elif len(domains) > 1:
98
+ mode, agents = "multi-specialist", min(len(domains), 4)
99
+ elif task_type in ("lint", "inventory", "policy", "diff"):
100
+ mode, agents = "deterministic", 0
101
+ else:
102
+ mode, agents = "single-specialist", 1
103
+ return {"mode": mode, "suggested_max_agents": agents,
104
+ "reason": "§123 selective agentics"}
105
+
106
+
107
+ def fanout_verdict(envelope_check: dict[str, Any], requested_agents: int,
108
+ max_agents: int | None) -> dict[str, Any]:
109
+ """§122/§246 — fanout may never exceed the envelope's hard limit."""
110
+ if max_agents is not None and requested_agents > max_agents:
111
+ return {"refusal": "PF-ECONOMY-BUDGET-EXHAUSTED",
112
+ "reason": f"fanout {requested_agents} > max_agents "
113
+ f"{max_agents}",
114
+ "dimension": "fanout"}
115
+ return {"decision": "ok", "fanout": requested_agents}
@@ -0,0 +1,106 @@
1
+ """platform-verifier machinery — independent closure check (§19–21).
2
+
3
+ The verifier is deterministic and INDEPENDENT: the component that
4
+ produced a conclusion cannot be its sole verifier. It maps acceptance
5
+ criteria → evidence, checks coverage/freshness claims, recomputes
6
+ receipts, and returns a verdict with a receipt — it never upgrades a
7
+ claim the evidence doesn't carry.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any
13
+
14
+ from platformforge.agents.contracts import AgentRefusal, AgentRunRecord, refusal
15
+ from platformforge.models.base import stable_id
16
+
17
+ PRODUCER_ROLES = ("orchestrator", "planner", "coordinator",
18
+ "specialist", "executor", "critic")
19
+
20
+
21
+ def verify_run(record: AgentRunRecord,
22
+ *, spec: Any | None = None,
23
+ producers: tuple[str, ...] | None = None,
24
+ evidence_index: dict[str, Any] | None = None,
25
+ verifier: str = "platform-verifier") -> dict[str, Any]:
26
+ """Check a run record before closure.
27
+
28
+ record the run under review
29
+ spec the sealed PlatformTaskSpec (acceptance criteria)
30
+ producers agents that produced the run's outputs
31
+ evidence_index fact_id → fact doc (for existence/freshness checks)
32
+ """
33
+ # default producers = run agents minus the verifier itself — the
34
+ # verifier appears in record.agents as a DAG participant, but it is
35
+ # only independent if it produced none of the conclusions
36
+ producers = tuple(producers) if producers is not None else tuple(
37
+ a for a in record.agents if a != verifier)
38
+ problems: list[str] = []
39
+
40
+ # §21/§183 — independence: a producer cannot be the sole verifier
41
+ if verifier in producers:
42
+ return refusal(
43
+ AgentRefusal.SELF_VERIFICATION,
44
+ f"{verifier} produced this run and cannot verify it",
45
+ "assign a verifier that is not in the producer set",
46
+ producers=list(producers))
47
+ if record.verifier and record.verifier in producers:
48
+ return refusal(
49
+ AgentRefusal.INDEPENDENCE_FAILED,
50
+ f"declared verifier {record.verifier} is in the producer "
51
+ "set", "verify with an agent that produced no output here")
52
+
53
+ # §20 — criteria → evidence map
54
+ criteria = list(getattr(spec, "acceptance_criteria", ()) or ())
55
+ ev_index = evidence_index or {}
56
+ evidence = [e for e in record.evidence
57
+ if not ev_index or e in ev_index]
58
+ missing_ev = [e for e in record.evidence if e not in ev_index] \
59
+ if ev_index else []
60
+ unmapped = []
61
+ if criteria:
62
+ # a criterion is satisfied if any evidence or finding addresses
63
+ # it — deterministic check: evidence must exist at all
64
+ for c in criteria:
65
+ if not evidence:
66
+ unmapped.append(c)
67
+ if unmapped:
68
+ problems.append("criteria with no evidence: "
69
+ + "; ".join(unmapped))
70
+ for f in getattr(spec, "evidence_requirements", ()) or ():
71
+ if not evidence and "coverage" not in f:
72
+ problems.append(f"evidence requirement unmet: {f}")
73
+
74
+ # freshness check when the index carries it
75
+ stale = [eid for eid, f in ev_index.items()
76
+ if isinstance(f, dict)
77
+ and f.get("freshness", {}).get("status")
78
+ in ("stale", "deprecated", "superseded")]
79
+ if stale:
80
+ problems.append("stale evidence cited: " + ", ".join(sorted(stale)))
81
+
82
+ verdict = "confirmed"
83
+ if problems:
84
+ verdict = "unresolved"
85
+ elif record.verdict in ("refuted", "unsupported"):
86
+ verdict = record.verdict # never upgrade a refuted producer output
87
+ elif not evidence and record.evidence:
88
+ verdict = "unsupported"
89
+ elif not evidence:
90
+ verdict = "unresolved"
91
+ receipt_id = stable_id("PF-VRF", record.run_id, verdict)
92
+ out = {"verdict": verdict, "receipt": {
93
+ "receipt_id": receipt_id, "run_id": record.run_id,
94
+ "task_spec_hash": record.task_spec_hash,
95
+ "verifier": verifier,
96
+ "producers": list(producers),
97
+ "evidence_count": len(evidence),
98
+ "missing_evidence_refs": missing_ev,
99
+ "problems": problems}}
100
+ if verdict == "unresolved" and not evidence:
101
+ out.update(refusal(AgentRefusal.NO_EVIDENCE,
102
+ "run closed with no verifiable evidence",
103
+ "collect evidence for the declared criteria "
104
+ "and re-verify"))
105
+ out["receipt"]["problems"] = problems
106
+ return out
@@ -0,0 +1,4 @@
1
+ """Cycle 5 — AI Platform Awareness: GPU/accelerator/model-serving
2
+ platform concerns (§187–201). Detection + capacity + cost awareness;
3
+ unit economics only with a real denominator; never terminates anything.
4
+ """