Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/dependabot-automerge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,14 @@ jobs:
contents: write # needed to enable auto-merge
pull-requests: write # needed to approve
# Only run for PRs actually authored by Dependabot.
if: github.actor == 'dependabot[bot]' && github.event.pull_request.user.login == 'dependabot[bot]'
# NB: gate on the PR author only. The dispatch-actor conjunct that used to
# sit here has been removed deliberately: that context is the user who
# *triggered the run*, which a fork, branch or rerun event can set without
# the PR being Dependabot's, and Hypatia's research_extensions RE008 flags
# exactly that shape of identity check as spoofable (it scans workflow text
# verbatim, which is also why this comment describes the pattern instead of
# quoting it). The PR-author check below is the real authorisation test.
if: github.event.pull_request.user.login == 'dependabot[bot]'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/instant-sync.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# SPDX-License-Identifier: MPL-2.0
# This workflow is managed by gh actions-lock.
# Instant Forge Sync - Triggers propagation to all forges on push/release
#
# STATE: DISABLED at the repository settings level (Settings → Actions →
# Workflows), so it never runs on pushes or releases even though the triggers
# below are still declared. Repository-level workflow disabling is not visible
# from the repository contents, so it is recorded here.
#
# It is kept in the tree because the propagation mechanism is still the
# intended distribution path for the estate (see mirror.yml, which publishes to
# one mirror). Re-enable only with a `FARM_DISPATCH_TOKEN` secret present on the
# destination farm; without the secret the credential check below no-ops with a
# notice, so re-enabling before the secret exists is safe but useless.
name: Instant Sync
on:
push:
Expand Down
10 changes: 5 additions & 5 deletions .machine_readable/descriptiles/STATE.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
[metadata]
project = "oikosbot"
version = "0.1.0-dev"
last-updated = "2026-08-07"
last-updated = "2026-09-26"
status = "active"
session = "2026-08-07 documentation + debt audit: DEBT.adoc written (licence/docs/code/proof/CI-CD, every item evidenced); removed an UNEARNED OpenSSF Best Practices badge (API returns empty — never registered); deleted ARCHITECTURE.md and GOVERNANCE.md (generic boilerplate describing separate src/ and tests/ directories this repo does not have, shadowing the real .adoc versions); deleted orphaned LICENSES/AGPL-3.0-or-later.txt (no file declares it); fixed docs/README.adoc's DUPLICATED SPDX header (MPL-2.0 on line 1 shadowing CC-BY-SA-4.0 on line 2 — a doc licensed as code, and a class of defect that passes the presence check while asserting the wrong licence); ARCHITECTURE.adoc banner-flagged as TARGET design with each unbuilt component named; tech-debt-2026-05-26.adoc marked superseded; wiki built out from a one-line stub; repo description and topics set. Prior session 2026-08-03/04 estate economics round one: #60 merged (oikosbot-telemetry/-capability/-dea + estate CLI), oikosbot-estate snapshot repo created, #65 in review (path-keyed gate detection). Prior: 2026-07-28 generation-1 go-live: Pareto engine made executable (#42 — crates/oikosbot-pareto: ε-tolerant dominance, normalized weighted frontier, base-vs-head verdicts with confidence gating, oikosbot compare, SARIF pareto_* properties, EconScore composition per ARCHITECTURE); .oikos.yml --config + auto-discovery (estate configs + governance flag now real); push-email-notify removed (dual-use ruling); publish-image root-caused to GHCR package access (permission_denied: write_package — owner grant, Containerfile verified sound via podman); composite action.yml + docs/COMPARISON-climate-warrior.adoc. Rulings: Action-mode first then App; NO interim listener (upstream AffineScript Http::Server instead); advisor + machine-checked trade-offs; Scallop replaces DeepProbLog. Prior session: 2026-06-21 close-out of the post-extraction work: fleet bridge → BotId::Oikosbot + ReScript-era containers removed (#5); finding taxonomy in NEUROSYM.a2ml [finding-taxonomy] + policies/finding_taxonomy.ecl (#9); robot-repo-automaton build fix + Rust build/test/clippy CI gate (gitbot-fleet); stale-identity sweep across SECURITY/CLAUDE/META (#11); standards reusable-workflow pin refresh (#13); LICENSE dual-SPDX MPL-2.0 + CC-BY-SA-4.0, SECURITY.md finalized (reporting → j.d.a.jewell@open.ac.uk), redundant trufflehog job dropped (#14); added docs/README.adoc documentation map. Open follow-ups: #12 (taxonomy vocab reconciliation), #16 (developer+maintainer docs + README split), #17 (end-user docs), #18 (taxonomy tags through Finding types)."
session = "2026-08-07 documentation + debt audit: DEBT.adoc written (licence/docs/code/proof/CI-CD, every item evidenced); removed an UNEARNED OpenSSF Best Practices badge (API returns empty — never registered); deleted ARCHITECTURE.md and GOVERNANCE.md (generic boilerplate describing separate src/ and tests/ directories this repo does not have, shadowing the real .adoc versions); deleted orphaned LICENSES/AGPL-3.0-or-later.txt (no file declares it); fixed docs/README.adoc's DUPLICATED SPDX header (MPL-2.0 on line 1 shadowing CC-BY-SA-4.0 on line 2 — a doc licensed as code, and a class of defect that passes the presence check while asserting the wrong licence); ARCHITECTURE.adoc banner-flagged as TARGET design with each unbuilt component named; tech-debt-2026-05-26.adoc marked superseded; wiki built out from a one-line stub; repo description and topics set. Prior session 2026-08-03/04 estate economics round one: #60 merged (oikosbot-telemetry/-capability/-dea + estate CLI), oikosbot-estate snapshot repo created, #65 in review (path-keyed gate detection). Prior: 2026-07-28 generation-1 go-live: Pareto engine made executable (#42 — crates/oikosbot-pareto: ε-tolerant dominance, normalized weighted frontier, base-vs-head verdicts with confidence gating, oikosbot compare, SARIF pareto_* properties, EconScore composition per ARCHITECTURE); .oikos.yml --config + auto-discovery (estate configs + governance flag now real); push-email-notify removed (dual-use ruling); publish-image root-caused to GHCR package access (permission_denied: write_package — owner grant, Containerfile verified sound via podman); composite action.yml + docs/COMPARISON-climate-warrior.adoc. Rulings: Action-mode first then App; NO interim listener (upstream AffineScript Http::Server instead); advisor + machine-checked trade-offs; Scallop replaces DeepProbLog. Prior session: 2026-06-21 close-out of the post-extraction work: fleet bridge → BotId::Oikosbot + ReScript-era containers removed (#5); finding taxonomy in NEUROSYM.a2ml [finding-taxonomy] + policies/finding_taxonomy.ecl (#9); robot-repo-automaton build fix + Rust build/test/clippy CI gate (gitbot-fleet); stale-identity sweep across SECURITY/CLAUDE/META (#11); standards reusable-workflow pin refresh (#13); LICENSE dual-SPDX MPL-2.0 + CC-BY-SA-4.0, SECURITY.md finalized (reporting → j.d.a.jewell@open.ac.uk), redundant trufflehog job dropped (#14); added docs/README.adoc documentation map. Open follow-ups: #12 (taxonomy vocab reconciliation), #16 (developer+maintainer docs + README split), #17 (end-user docs), #18 (taxonomy tags through Finding types). Session 2026-09-26 (branch arena/01a0dad6-oikosbot): two long-standing red checks root-caused and fixed — Hypatia's single high/critical was research_extensions RE008 on dependabot-automerge.yml (github.actor identity check; PR-author gate retained), and Publish Image's exit 101 was an MSRV drift (tree-sitter 0.27.0 needs Rust 1.90/edition 2024 vs rust:1.88-slim; builder now rust:1-slim). #48 calibration wiring landed (see calibration-wiring and enforcement-inert). Debt register updated for the resolved items; docs delivered: docs/usage.adoc, docs/ci-runbook.adoc, per-crate READMEs, analyzers/code-haskell/README.adoc. NOT verified in CI by the author (no Rust/Haskell/Elixir toolchain in the sandbox): verification means the PR's own CI run plus, for the image, a successful Publish Image on main."

[project-context]
name = "OikosBot"
Expand Down Expand Up @@ -36,16 +36,16 @@ milestones = [
issues = [
{ id = "github-actions-budget", severity = "operational", summary = "Actions spending limit exhausted intermittently across the estate. Signature: job conclusion 'failure' with ZERO steps and the annotation 'job was not started because recent account payments have failed'. Hit 2 of 15 swept consumer repos (chronicles-of-slavia, canonical-ums — the latter private). NOT a workflow defect; do not debug the workflow when steps==0." },
{ id = "actions-lockfile-enforcement", severity = "resolved", summary = "RESOLVED for this repo. GitHub's Actions workflow-lockfile enforcement killed every workflow estate-wide at startup (0s startup_failure, error visible only on the run's HTML page). Cured by shipping .github/workflows/actions.lock in #61; reusable-caller permissions fixed in #63. CI now runs green (Hypatia, Secret Scanner, Governance, Language Policy, CodeQL). Consumers still need their own lockfiles — see consumer-fleet-dark." },
{ id = "enforcement-inert", severity = "design", summary = "PER-FILE path only: `--check` cannot block a merge, since only Measured/Calibrated inputs may fail a run and the analyzer emits only Estimated (calibration.rs exists but has ZERO callers; estimate_resources() is still naive complexity*0.1 J). Refusal is LOUD (::warning::) as of #47, never silent. Real fix tracked in issue #48. NOTE the ESTATE path is now the exception: oikosbot-telemetry derive.rs assigns Confidence::Measured to wall_minutes from the GitHub API — the first genuinely Measured quantity in the system." },
{ id = "per-file-collinearity", severity = "design", summary = "estimate_resources() derives energy, duration, carbon and memory from ONE integer (complexity = raw AST node count), so four of five Pareto objectives are scalar multiples of each other and the frontier collapses to a 1-D sort. The dominance maths in oikosbot-pareto is correct; the inputs make it near-vacuous. SOLVED at estate level (telemetry axes measured independent: wall_minutes~size_kb = -0.049 across 381 repos). UNSOLVED at file level. See DEBT.adoc." },
{ id = "enforcement-inert", severity = "resolved-per-file", summary = "RESOLVED for the per-file path on 2026-09-26 (#48): calibration is wired. estimate_resources() maps a detected pattern onto an OperationKind (calibration::operation_for_pattern) and prices it with estimate_operation(), which returns the min/typical/max band AND the confidence that row has earned — Calibrated for HashLookup/Sort/Allocation/MathCompute, Estimated for the host-dependent FileIO/StringOp rows, Estimated on the naive complexity path. So assess().actionable is now true for calibrated drivers and `compare --check` exits 1 on an undocumented calibrated regression; proven by crates/oikosbot-cli/tests/check_gate.rs. Heuristic findings still cannot block, and the refusal stays LOUD (::warning::, #47). STILL OPEN: absolute figures are unvalidated against profiling data, and the eco score's log scale (anchored at 1 J) saturates near 100 under calibrated microjoule-scale estimates, so the eco THRESHOLD discriminates far less than before while the Pareto verdicts (base vs head) are unaffected. ESTATE path remains the genuinely Measured exception: oikosbot-telemetry derive.rs assigns Confidence::Measured to wall_minutes from the GitHub API." },
{ id = "per-file-collinearity", severity = "design", summary = "PARTIALLY SOLVED 2026-09-26 (#48). Units with a recognised pattern are now priced from per-kind calibration rows whose energy/duration/memory formulae are NOT the same function of complexity (Sort is n*log2(n) on energy and duration but linear on memory; Allocation is linear on bytes; MathCompute has no memory term), so those units no longer collapse the frontier. Units with NO recognised pattern still go through the naive path, where energy, duration, carbon and memory all derive from ONE integer (complexity = raw AST node count) and four of five objectives remain scalar multiples of each other. The dominance maths in oikosbot-pareto is correct; the naive inputs make it near-vacuous. SOLVED at estate level (telemetry axes measured independent: wall_minutes~size_kb = -0.049 across 381 repos). See DEBT.adoc." },
{ id = "policy-engines-never-execute", severity = "design", summary = "TWO fake gates. (1) policy-engine/datalog/eco_rules.dl has never executed — Souffle is DECLARED in guix/manifest.scm and guix/oikos.scm but invoked nowhere (no match in Justfile, *.just or any workflow); its allocation-waste and debt rules have no Rust counterpart. (2) oikosbot-eclexia's default backend dispatches on the .ecl FILE STEM and never reads file contents; its hardcoded thresholds contradict the files (energy_threshold.ecl says >50 J per function, builtin fires >1000 J total). Mitigated by a loud ::warning:: in #59; still fake." },
{ id = "consumer-fleet-dark", severity = "operational", summary = "15 estate repos carry .github/workflows/oikosbot.yml pinned to oikosbot@bb95ab50 (v0.1.0), all merged — but each needs its OWN Actions lockfile before its workflows can start. OikosBot is installed everywhere and running nowhere. Highest-value follow-up." },
{ id = "idaptik-ums-repo-wide-startup-failure", severity = "external", summary = "metadatastician/idaptik-ums fails ALL workflows at startup on main (OikosBot, Licence hygiene, CodeQL), with two workflows displayed as PATHS not names — the estate tell for never-parsed. Repo-level, pre-existing, not caused by the OikosBot sweep (the same file succeeded on a branch there)." }
]

[critical-next-actions]
actions = [
{ id = "calibration-wiring", priority = "P1", summary = "Issue #48: map detected patterns to calibration OperationKinds so confidence is EARNED per finding, unlocking real enforcement. Changes every resource figure and every downstream score — needs before/after numbers." },
{ id = "calibration-wiring", priority = "P1", status = "landed-2026-09-26", summary = "Issue #48 DONE (pending CI verification): patterns.rs detections mapped onto OperationKind via calibration::operation_for_pattern; estimate_operation() prices recognised units and returns a ResourceRange carrying that row's confidence; naive path retained for unrecognised code and labelled Estimated; ResourceRange propagated on AnalysisResult and emitted in SARIF properties.resource_range; falsifier tests added (calibration confidence ladder, pattern mapping, analyzer Calibrated-vs-Estimated, and CLI tests/check_gate.rs proving --check can exit 1). BEFORE/AFTER (derived by reasoning, NOT measured — no toolchain in the authoring sandbox): a depth-3 nested-loop unit of ~30 AST nodes went from naive 0.1 J/node (~3 J, eco ~89) to the calibrated Sort row (~0.007 J, eco clamped 100); every downstream figure moves with it. The eco-score saturation is documented in STATUS.adoc/QUICKSTART.adoc/README.adoc and flagged for an owner ruling on the score scale." },
{ id = "rsr-julia-template-phantom-sha", priority = "P1", summary = "hyperpolymath/rsr-julia-library-template-repo .github/workflows/codeql.yml pins phantom SHA 29b1f65c1f735799893313399435a59f54045865 (no such commit). It is a TEMPLATE, so every minted repo inherits a dead CodeQL gate. Valid replacement: 4187e74d05793876e9989daffde9c3e66b4acd07." },
{ id = "bot-affine-webhook-handler", priority = "P2", summary = "Wire the AS-side webhook receiver in bot-integration-affine/ using Http server + Json stdlib externs (ruled: do the upstream AffineScript work, no interim listener)" },
{ id = "hpm-json-object-keys", priority = "P3", summary = "Add hpm_json_object_keys export to hpm-json-rsr Zig FFI to close the JObject materialisation gap in stdlib/json.affine to_json" },
Expand Down
Loading
Loading