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
6 changes: 3 additions & 3 deletions .machine_readable/6a2/STATE.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
[metadata]
project = "oikosbot"
version = "0.1.0-dev"
last-updated = "2026-06-21"
last-updated = "2026-07-28"
status = "active"
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-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)."

[project-context]
name = "OikosBot"
purpose = "OikosBot — an ecological & economic code-analysis GitHub/GitLab App. NB: the similarly-named 'oikos' DSL (separate repo hyperpolymath/oikos-economics-accounting-dsl) and the 'sustainabot' gitbot-fleet slot are SEPARATE projects — see DISAMBIGUATION.adoc."
completion-percentage = 40
completion-percentage = 50

[position]
phase = "implementation" # design | implementation | testing | maintenance | archived
Expand Down
22 changes: 22 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,28 @@ link:DISAMBIGUATION.adoc[`DISAMBIGUATION.adoc`].
`just affine-check` expects an AffineScript compiler. Override the compiler path
with `AS_BIN=/path/to/main.exe` when needed.

== GitHub Action

OikosBot runs in CI as a composite action wrapping the published container
(`ghcr.io/hyperpolymath/oikos`):

[source,yaml]
----
- uses: hyperpolymath/oikosbot@main # pin a tag/SHA in production
with:
mode: report # report | check | compare
path: .
output: results.sarif # upload with github/codeql-action/upload-sarif
----

`compare` mode issues a Pareto verdict against a base checkout (see
link:QUICKSTART.adoc[QUICKSTART]). A repo-local `.oikos.yml` is honored
automatically. Full workflow example:
link:examples/oikosbot-ci.yml[`examples/oikosbot-ci.yml`].

How OikosBot relates to the nearest Marketplace neighbour:
link:docs/COMPARISON-climate-warrior.adoc[OikosBot vs Climate Warrior].

== GitHub App

The app manifest lives at link:.github/app.yml[`.github/app.yml`]. The setup
Expand Down
6 changes: 6 additions & 0 deletions ROADMAP.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ Status legend: `done` | `in-progress` | `blocked` | `planned`
* [x] `.oikos.yml` config support in the CLI (`--config` + auto-discovery):
mode, thresholds, exclude globs, languages — makes the estate consumer
configs and the governance workflow's `--config` flag real
* [x] Composite GitHub Action (`action.yml`, container-based) — OikosBot
consumable as `uses: hyperpolymath/oikosbot@<ref>`; Marketplace-shaped
* [x] Marketplace positioning doc: `docs/COMPARISON-climate-warrior.adoc`
* [x] publish-image root-caused: GHCR `oikos` package lacked Actions write
access for this repo (`permission_denied: write_package`); fixed by owner
grant, not by code — the Containerfile was verified sound via local podman

=== Remaining

Expand Down
106 changes: 106 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# SPDX-License-Identifier: MPL-2.0
# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
#
# OikosBot composite action — ecological & economic code analysis with
# Pareto verdicts. Runs the published CLI container (ENTRYPOINT oikosbot),
# so consumers need no Rust toolchain. See examples/oikosbot-ci.yml for a
# full workflow and docs/ for interpretation guidance.
name: 'OikosBot Sustainability Analysis'
description: >-
Ecological & economic code analysis: carbon/energy estimates, Pareto
verdicts on pull requests (improvement / regression / trade-off), and
SARIF output for GitHub code scanning. Honors the repo's .oikos.yml.
author: 'Jonathan D.A. Jewell'
branding:
icon: 'trending-down'
color: 'green'

inputs:
mode:
description: 'Subcommand: report (SARIF, default), check (threshold gate), compare (Pareto verdict vs base)'
required: false
default: 'report'
path:
description: 'Directory to analyze (or head directory for compare)'
required: false
default: '.'
base:
description: 'Base directory for compare mode (e.g. a checkout of the target branch)'
required: false
default: ''
format:
description: 'Output format: sarif | json | text'
required: false
default: 'sarif'
output:
description: 'Output file path (empty = stdout)'
required: false
default: 'results.sarif'
Comment thread
hyperpolymath marked this conversation as resolved.
config:
description: 'Path to .oikos.yml (empty = auto-discover in path)'
required: false
default: ''
eco-threshold:
description: 'Eco-score floor 0-100 (empty = config value, else 50)'
required: false
default: ''
pr-body:
description: 'File with the PR description, for the Pareto trade-off documentation check (compare mode)'
required: false
default: ''
check:
description: 'compare mode: fail on an undocumented, measured Pareto regression/trade-off (true/false)'
required: false
default: 'false'
image:
description: 'Container image to run'
required: false
default: 'ghcr.io/hyperpolymath/oikos:latest'

outputs:
output-file:
description: 'Path of the written output file (when output is set)'
value: ${{ inputs.output }}
Comment thread
hyperpolymath marked this conversation as resolved.

runs:
using: 'composite'
steps:
- name: Run oikosbot
shell: bash
env:
MODE: ${{ inputs.mode }}
TARGET: ${{ inputs.path }}
BASE: ${{ inputs.base }}
FORMAT: ${{ inputs.format }}
OUTFILE: ${{ inputs.output }}
CONFIG: ${{ inputs.config }}
THRESHOLD: ${{ inputs.eco-threshold }}
PR_BODY: ${{ inputs.pr-body }}
DO_CHECK: ${{ inputs.check }}
IMAGE: ${{ inputs.image }}
run: |
set -euo pipefail
args=("$MODE")
case "$MODE" in
compare)
[ -n "$BASE" ] || { echo "::error::compare mode requires the 'base' input"; exit 1; }
args+=("$BASE" "$TARGET")
[ "$DO_CHECK" = "true" ] && args+=(--check)
[ -n "$PR_BODY" ] && args+=(--pr-body "$PR_BODY")
[ "$FORMAT" = "json" ] && args+=(--format json)
;;
report|check)
args+=("$TARGET" --format "$FORMAT")
;;
*)
echo "::error::unknown mode '$MODE' (report | check | compare)"; exit 1
;;
esac
[ -n "$OUTFILE" ] && args+=(--output "$OUTFILE")
[ -n "$CONFIG" ] && args+=(--config "$CONFIG")
Comment thread
hyperpolymath marked this conversation as resolved.
[ -n "$THRESHOLD" ] && args+=(--eco-threshold "$THRESHOLD")
docker run --rm \
--user "$(id -u):$(id -g)" \
-v "$GITHUB_WORKSPACE:$GITHUB_WORKSPACE" \
-w "$GITHUB_WORKSPACE" \
"$IMAGE" "${args[@]}"
110 changes: 110 additions & 0 deletions docs/COMPARISON-climate-warrior.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// SPDX-License-Identifier: CC-BY-SA-4.0
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
= OikosBot vs Climate Warrior: positioning
:toc: macro
:icons: font

_A point-in-time comparison (2026-07-28) against
https://github.com/marketplace/climate-warrior-official[Climate Warrior Official],
the closest sustainability-branded product on the GitHub Marketplace. Facts
about Climate Warrior are taken from its Marketplace listing and
https://github.com/rollthecloudinc/climatewarrior/wiki/Github-App-Docs[App docs]
as of that date; corrections welcome._

toc::[]

== Short version

The two products share the Software Carbon Intensity (SCI) vocabulary and
almost nothing else. **Climate Warrior is a storage product with carbon
telemetry** — a GitHub App (category: API Management) that turns repositories
into versioned JSON document stores ("energy-efficient databases") and records
SCI for its own operations, mainly lambda executions. **OikosBot is a code
analyzer with an economics engine** — it reads your source, estimates
per-function carbon/energy/time/memory, and renders a *Pareto verdict* on
every change: improvement, regression, or a trade-off that must be documented.

They are not substitutes. A team could run both without overlap: Climate
Warrior to store documents with an SCI ledger, OikosBot to review code.

== Matrix

[cols="1,2,2",options="header"]
|===
| Dimension | OikosBot | Climate Warrior

| What it is
| Code-analysis CLI + GitHub Action (GitHub App planned; AffineScript
receiver in flight)
| GitHub App

| Marketplace category fit
| Code quality / code scanning (SARIF into the Security tab)
| API Management (its actual listing category)

| Unit of analysis
| Functions and files in your source (tree-sitter AST; Rust, JavaScript,
Python today)
| Its own storage/API operations (JSON documents, lambda executions)

| Metrics
| Per-function energy (J), carbon (gCO2e), time (ms), memory (bytes);
Eco/Econ/Quality scores; composite health index
| Software Carbon Intensity of service operations; historical SCI

| The economics layer
| **Pareto engine**: ε-tolerant dominance over weighted, normalized
objectives; frontier membership + ParetoScore per unit; base-vs-head
verdicts (improvement / regression / trade-off / neutral);
EconScore = 0.5·Pareto + 0.3·allocation (shadow prices) + 0.2·debt
| None (no notion of trade-offs or optimality)

| PR workflow
| Verdict per change; trade-offs and regressions ask for a documented
justification (`Pareto-Trade-off:` trailer, machine-checked); advisor by
default, regulator opt-in per repo
| None (not a review tool)

| Output formats
| SARIF 2.1.0 (GitHub code scanning, with `pareto_*` properties), JSON, text
| App-internal; repository documents

| Configuration
| `.oikos.yml` per repo: mode, thresholds, excludes, languages
| App installation settings

| Methodology transparency
| Open source (MPL-2.0); estimation model in-tree and SCI-spec-referenced
(ISO/IEC 21031:2024); every figure carries a confidence label
(Measured / Calibrated / Estimated / Unknown), and heuristic figures are
barred from blocking decisions by construction
| Not disclosed on the listing

| Pricing / maturity
| Free, open source, v0.1.x (pre-1.0; App mode not yet live)
| Free tier ("Squire"); ~16 installs at time of writing
|===

== What OikosBot does not do (honesty section)

* Estimates are **static heuristics** today (`Confidence::Estimated`), not
measurements. Runtime calibration and the VeriSimDB-backed praxis loop are
roadmap items. This is exactly why the confidence gate exists: heuristics
advise; only measured or calibrated figures may ever block a merge.
* The GitHub **App** (webhook, PR comments without CI) is not yet live — CI
Action mode is the generation-1 surface. The App is gated on upstream
AffineScript stdlib work by deliberate ruling (no interim listener).
* Language coverage is Rust / JavaScript / Python; listed-but-unsupported
languages in `.oikos.yml` are ignored loudly, never silently.
* Climate Warrior's document-storage use case is entirely out of scope:
OikosBot stores nothing about your repository (until the optional
VeriSimDB layer lands, and then only where configured).

== Positioning takeaway

If a Marketplace listing is pursued, OikosBot belongs in **code quality /
security (code scanning)** next to linters and SAST tools — not in the
sustainability-storage niche where Climate Warrior sits. Its differentiator
is not "we mention carbon" but the **economics**: making every PR answer
"did this change move us toward or away from the efficient frontier, and if
it traded something away, did the author say so?"
Loading