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
28 changes: 26 additions & 2 deletions .machine_readable/6a2/NEUROSYM.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#
# NEUROSYM.a2ml — Neurosymbolic integration metadata
[metadata]
version = "0.1.1"
last-updated = "2026-06-20"
version = "0.1.2"
last-updated = "2026-06-21"

[hypatia-config]
scan-enabled = true
Expand All @@ -19,3 +19,27 @@ report-format = "logtalk"
# Neural pattern detection settings
# confidence-threshold = 0.85
# model = "hypatia-v2"

[finding-taxonomy]
# Every OikosBot finding is classified on three orthogonal axes, layered
# intent -> action -> outcome. The intent axis is executable Eclexia
# (policies/finding_taxonomy.ecl); see policies/README.adoc for the prose.
axes = ["intent", "maintenance", "locus"]

[finding-taxonomy.intent]
# Deontic force. DERIVED from the finding's confidence score (not hand-tagged),
# and identical to the gitbot-fleet Safety Triangle and its thresholds.
values = ["must", "intend", "wish"]
must = { triangle = "eliminate", confidence = ">=0.95", disposition = "auto-fix" }
intend = { triangle = "substitute", confidence = ">=0.85", disposition = "review" }
wish = { triangle = "control", confidence = "<0.85", disposition = "human" }

[finding-taxonomy.maintenance]
# Why the change is made (Swanson 1976 / ISO/IEC 14764). Hand-tagged per rule.
values = ["corrective", "adaptive", "perfective", "preventive"]

[finding-taxonomy.locus]
# What the finding bears on. "externalities" is the oikos eco/econ sense
# (energy / carbon / resource impact) realised by the sustainability policies.
values = ["systems", "compliance", "externalities"]
externalities-policies = ["energy_threshold", "carbon_budget", "memory_efficiency"]
2 changes: 1 addition & 1 deletion .machine_readable/6a2/STATE.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ project = "oikosbot"
version = "0.1.0-dev"
last-updated = "2026-06-21"
status = "active"
session = "2026-06-21 follow-ups to #7: finish SPDX/licence drift cleanup (MPL-2.0-or-later → MPL-2.0 estate-wide; guix agpl3+ fix + dead-component prune; QUICKSTART → .adoc); scaffold the deferred VeriSimDB client (docs/verisimdb-client.adoc + VeriSimClient.affine); wire bot-integration-affine webhook→analyse→comment orchestration (Payload.affine + Main handler) — listener binding still gated on stdlib Http::Server; AS unverified (no toolchain)"
session = "2026-06-21 post-extraction follow-ups: oikosbot-fleet bridge now publishes as BotId::Oikosbot + stale ReScript-era containers/ removed (oikosbot#5, merged); add the OikosBot finding taxonomy — intent/maintenance/locus axes defined canonically in NEUROSYM.a2ml [finding-taxonomy], with the confidence-derived intent axis executable in policies/finding_taxonomy.ecl (≡ gitbot-fleet Safety Triangle 0.95/0.85 thresholds), plus policies/README.adoc"

[project-context]
name = "OikosBot"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ this project aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- feat(policies): add the OikosBot **finding taxonomy** — three orthogonal axes (`intent` / `maintenance` / `locus`) defined canonically in `NEUROSYM.a2ml [finding-taxonomy]`. The confidence-derived `intent` axis (≡ the gitbot-fleet Safety Triangle's 0.95 / 0.85 thresholds) is made executable in `policies/finding_taxonomy.ecl`; `locus=externalities` is the eco/econ sense realised by the sustainability policies. Adds `policies/README.adoc`.
- feat(crates): extract the Rust analysis workspace from `gitbot-fleet/bots/sustainabot/` into this repo, renamed `sustainabot-*` → `oikosbot-*` (`oikosbot-cli`/`-analysis`/`-metrics`/`-sarif`/`-eclexia`, plus the optional `oikosbot-fleet` bridge). Adds `policies/`, `fuzz/`, `examples/`, and `QUICKSTART.md`. Builds and tests green (35 tests).
- docs: `DISAMBIGUATION.adoc` — canonical breakdown of **oikos** (the DSL) vs **OikosBot** (this App) vs **sustainabot** (a reserved gitbot-fleet slot), with guardrails to prevent the misfiling recurring.
- ci(rust): add a `rust` job (fmt-check + build + test, informational clippy) to `ci.yml` and a `cargo` dependabot ecosystem. New `just rust-build` / `rust-test` targets.
Expand Down
51 changes: 51 additions & 0 deletions policies/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
= OikosBot Policies (Eclexia)

OikosBot's policies are written in *Eclexia* (`.ecl`) — a resource-bounded
policy DSL whose evaluator has provable energy/carbon budgets, so the analyser
is cheaper to run than the code it analyses. They are evaluated by
link:../crates/oikosbot-eclexia[`crates/oikosbot-eclexia`].

== Sustainability thresholds

[cols="1,3"]
|===
| `energy_threshold.ecl` | Warn when a function's estimated energy exceeds budget.
| `carbon_budget.ecl` | Per-function and per-project carbon (gCO2e) budgets.
| `memory_efficiency.ecl` | Memory-pressure thresholds.
| `security_sustainability.ecl` | Security checks weighted by resource impact.
|===

== Finding taxonomy (meta-policy)

`finding_taxonomy.ecl` is not a sustainability threshold; it classifies *every*
finding on three orthogonal axes, layered intent -> action -> outcome. The
canonical, machine-readable definition is
link:../.machine_readable/6a2/NEUROSYM.a2ml[`NEUROSYM.a2ml` `[finding-taxonomy]`].

[cols="1,2,4"]
|===
| Axis | Values | Meaning

| `intent`
| `must` / `intend` / `wish`
| Deontic force, *derived from confidence*. Identical to the gitbot-fleet
Safety Triangle: `must` ≡ eliminate (≥ 0.95, auto-fix), `intend` ≡ substitute
(≥ 0.85, review), `wish` ≡ control (< 0.85, human). **This axis is executable.**

| `maintenance`
| `corrective` / `adaptive` / `perfective` / `preventive`
| Why the change is made (Swanson 1976 / ISO 14764). Tagged per rule.

| `locus`
| `systems` / `compliance` / `externalities`
| What the finding bears on. `externalities` is the eco/econ sense
(energy / carbon / resource impact) realised by the sustainability policies
above.
|===

Because only `intent` is numerically derivable, only it is executable in
Eclexia; `maintenance` and `locus` are categorical tags set when a rule is
authored. A natural next step is to carry all three tags on the Rust `Finding`
types (`crates/oikosbot-metrics`) so emitted SARIF/reports are tagged end to end.
49 changes: 49 additions & 0 deletions policies/finding_taxonomy.ecl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MPL-2.0
// OikosBot Policy: Finding Taxonomy (intent axis)
//
// OikosBot classifies every finding on three orthogonal axes, layered
// intent -> action -> outcome. The canonical definition (all three axes and
// their allowed values) lives in
// .machine_readable/6a2/NEUROSYM.a2ml [finding-taxonomy]:
//
// 1. intent must | intend | wish
// 2. maintenance corrective | adaptive | perfective | preventive
// 3. locus systems | compliance | externalities
//
// Only the INTENT axis is numerically derivable: it is a pure function of the
// finding's confidence score, and is identical to the gitbot-fleet Safety
// Triangle (eliminate / substitute / control) and its 0.95 / 0.85 thresholds.
// `maintenance` and `locus` are categorical tags attached when a rule is
// authored, so they are not computed here.
//
// Written in Eclexia (dogfooding): classifying a finding is provably cheaper
// than producing it.

// intent = MUST <=> Safety-Triangle "eliminate" <=> auto-fix, no review.
def intent_is_must(confidence: Float) -> Bool
@requires: energy < 0.01J, carbon < 0.001gCO2e
@optimize: minimize energy
{
confidence >= 0.95
}

// intent = INTEND <=> "substitute" <=> proven replacement, needs review.
def intent_is_intend(confidence: Float) -> Bool
@requires: energy < 0.01J
{
confidence >= 0.85 && confidence < 0.95
}

// intent = WISH <=> "control" <=> human judgement required.
def intent_is_wish(confidence: Float) -> Bool
@requires: energy < 0.01J
{
confidence < 0.85
}

// A finding may be auto-actioned iff its intent is MUST.
def is_auto_actionable(confidence: Float) -> Bool
@requires: energy < 0.01J, latency < 1ms
{
intent_is_must(confidence)
}
Loading