Skip to content

Commit 2028e38

Browse files
hyperpolymathclaude
andcommitted
chore: post-Zig-migration housekeeping
.gitignore: - Add **/.zig-cache/ and **/zig-out/ patterns 0-AI-MANIFEST.a2ml: - Fill in [DATE] / [YOUR-NAME/ORG] placeholders - Replace generic template repo structure with actual kaldor-iiot layout .machine_readable/6a2/ — all six A2ML files substantially expanded: - STATE.a2ml: reflect actual subsystem state (firmware-zig 70%, backend-deno 40%, backend/api deprecated, frontend 50%, analytics 10%); list blockers and next actions for Claude vs Jonathan - META.a2ml: add four ADRs (Zig firmware rationale, Deno/ReScript decision, HAL freestanding split, ABI/FFI pending); add development practices table - ECOSYSTEM.a2ml: add full stack, hardware target, related-projects, compliance - PLAYBOOK.a2ml: flesh out firmware build+flash runbook, backend/frontend dev commands, full-stack docker-compose, incident response, release process - NEUROSYM.a2ml: fix stale report-format = "logtalk" (Logtalk removed from Hypatia 2026-04-12); note ESP-IDF extern fn stubs as legitimate FFI boundaries - AGENTIC.a2ml: update last-updated date CHANGELOG.md: - Add [0.2.0] 2026-04-12 entry for Zig 0.15.2 migration - Fix wrong-case GitHub URLs (Hyperpolymath/Kaldor-IIoT → hyperpolymath/kaldor-iiot) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e131a73 commit 2028e38

9 files changed

Lines changed: 367 additions & 45 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,7 @@ htmlcov/
7777
/tmp/
7878
*.tmp
7979
*.bak
80+
81+
# Zig
82+
**/.zig-cache/
83+
**/zig-out/

.machine_readable/6a2/AGENTIC.a2ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
[metadata]
88
version = "0.1.0"
9-
last-updated = "2026-03-16"
9+
last-updated = "2026-04-12"
1010

1111
[agent-permissions]
1212
can-edit-source = true
Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,51 @@
11
# SPDX-License-Identifier: PMPL-1.0-or-later
2-
# ECOSYSTEM.a2ml — Ecosystem position
3-
# Converted from ECOSYSTEM.scm on 2026-03-15
2+
# ECOSYSTEM.a2ml — Ecosystem position and relationships
3+
# Originally converted from ECOSYSTEM.scm on 2026-03-15
4+
# Updated 2026-04-12
45

56
[metadata]
67
project = "kaldor-iiot"
78
ecosystem = "hyperpolymath"
9+
last-updated = "2026-04-12"
810

911
[position]
1012
type = "component"
13+
domain = "industrial-iot"
14+
layer = "edge-device + platform"
15+
description = """
16+
IIoT implementation for the Kaldor loom's BBW (Back Beam Width) board.
17+
Provides real-time sensor acquisition (100Hz), local buffering, MQTT
18+
telemetry, OTA updates, and a Deno/ReScript cloud platform for fleet
19+
management, analytics, and community governance.
20+
"""
21+
22+
[hardware-target]
23+
primary = "ESP32 (Xtensa LX6)"
24+
secondary = "ESP32-C3/C6 (RISC-V) — see firmware-riscv/"
25+
firmware-language = "Zig 0.15.2"
26+
hal-abstraction = "src/hal.zig (freestanding + simulation dual mode)"
27+
28+
[platform-stack]
29+
firmware = "Zig (firmware-zig/)"
30+
backend = "Deno + ReScript (backend-deno/) [canonical]"
31+
backend-legacy = "Node.js/Express (backend/api/) [pending deprecation]"
32+
frontend = "ReScript + React 18 + Vite (frontend/)"
33+
analytics = "Julia (backend/analytics/)"
34+
database = "TimescaleDB + Automerge CRDTs (planned)"
35+
broker = "Mosquitto MQTT (infrastructure/mosquitto/)"
36+
protocols = ["MQTT", "OPC-UA", "Matter", "Modbus"]
37+
38+
[related-projects]
39+
items = [
40+
{ name = "boj-server", relationship = "potential-consumer", note = "BoJ cartridge for IIoT data queries" },
41+
{ name = "nextgen-databases/verisimdb", relationship = "infrastructure", note = "VeriSimDB instance for per-project persistence" },
42+
{ name = "gossamer", relationship = "potential-consumer", note = "PanLL panel for loom monitoring dashboard" },
43+
{ name = "standards/a2ml", relationship = "format-standard", note = "A2ML used for .machine_readable/ checkpoint files" },
44+
{ name = "idaptik", relationship = "sibling-application", note = "Shares Deno/ReScript + community governance patterns" },
45+
]
46+
47+
[compliance]
48+
rsr-level = "Bronze (achieved)"
49+
rsr-target = "Gold"
50+
abi-ffi-standard = "pending — HAL uses extern fn stubs; full Idris2-ABI + Zig-FFI layer planned"
51+
license = "PMPL-1.0-or-later (MPL-2.0 legal fallback)"

.machine_readable/6a2/META.a2ml

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,95 @@
11
# SPDX-License-Identifier: PMPL-1.0-or-later
2-
# META.a2ml — Project meta-information
3-
# Converted from META.scm on 2026-03-15
2+
# Copyright (c) 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
# META.a2ml — Architecture decisions and development practices
4+
# Originally converted from META.scm on 2026-03-15
5+
# Updated 2026-04-12
46

57
[metadata]
68
project = "kaldor-iiot"
79
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>"
810
license = "PMPL-1.0-or-later"
911
standard = "RSR 2026"
12+
last-updated = "2026-04-12"
13+
14+
# ------------------------------------------------------------------
15+
# ARCHITECTURE DECISIONS (ADRs)
16+
# ------------------------------------------------------------------
17+
18+
[[adr]]
19+
id = "ADR-001"
20+
title = "Zig for firmware instead of C++ or Rust"
21+
status = "accepted"
22+
date = "2025-11-22"
23+
rationale = """
24+
Zig 0.15+ provides zero-cost abstractions, comptime, and cross-compilation
25+
without a C++ toolchain. The freestanding target + builtin.os.tag pattern
26+
gives clean simulation/production bifurcation. Rust was considered but
27+
ESP32 Xtensa toolchain support is less mature than Zig's.
28+
"""
29+
30+
[[adr]]
31+
id = "ADR-002"
32+
title = "Deno + ReScript backend, not Node.js + TypeScript"
33+
status = "accepted"
34+
date = "2025-11-22"
35+
rationale = """
36+
Node.js and TypeScript are banned per Hyperpolymath RSR language policy.
37+
Deno provides a secure runtime with first-class TypeScript (via JSR),
38+
but we use ReScript for the application layer to get a sound type system
39+
without TypeScript. Oak replaces Express.
40+
"""
41+
migration-note = "Legacy backend/api (Node.js) pending decommission. ADR-002 is the canonical direction."
42+
43+
[[adr]]
44+
id = "ADR-003"
45+
title = "HAL layer uses builtin.os.tag for freestanding/simulation split"
46+
status = "accepted"
47+
date = "2025-11-22"
48+
rationale = """
49+
src/hal.zig compiles on host by branching on builtin.os.tag == .freestanding.
50+
This lets all unit tests run on the CI host without an ESP32 cross-compiler,
51+
while the same source file is used for the actual device firmware. The
52+
extern fn declarations are only resolved at link time on ESP32.
53+
"""
54+
55+
[[adr]]
56+
id = "ADR-004"
57+
title = "ABI/FFI standard pending — ESP-IDF bindings not yet structured"
58+
status = "proposed"
59+
date = "2026-04-12"
60+
rationale = """
61+
The Hyperpolymath estate standard requires Idris2 ABI + Zig FFI. The current
62+
hal.zig uses raw extern fn declarations inline (not in a separate ffi/ layer).
63+
Full ADR-004 implementation requires:
64+
- src/abi/*.idr — Idris2 definitions for ESP-IDF interface
65+
- ffi/zig/src/*.zig — C-compatible Zig bindings
66+
- generated/abi/*.h — auto-generated headers
67+
Blocked on: physical board availability + hardware strategy decision.
68+
"""
69+
70+
# ------------------------------------------------------------------
71+
# DEVELOPMENT PRACTICES
72+
# ------------------------------------------------------------------
73+
74+
[practices]
75+
test-command = "zig build test"
76+
test-root = "firmware-zig/src/all_tests.zig"
77+
test-note = "Host-side tests only. Freestanding HAL paths are excluded."
78+
pre-commit = "panic-attack assail ."
79+
build-tool = "zig build (firmware), deno task (backend), npm run build (frontend)"
80+
language-firmware = "Zig 0.15.2"
81+
language-backend = "ReScript + Deno"
82+
language-frontend = "ReScript + React 18 + Vite"
83+
language-analytics = "Julia"
84+
package-manager-backend = "deno.json (no node_modules)"
85+
package-manager-frontend = "npm (frontend only, ReScript compile step)"
86+
87+
[banned-patterns]
88+
items = [
89+
"believe_me / assert_total (Idris2 proof debt)",
90+
"unsafeCoerce / Obj.magic (ReScript)",
91+
"TypeScript files (use ReScript)",
92+
"npm for backend runtime deps (use Deno)",
93+
"Python anywhere except SaltStack",
94+
"Go anywhere",
95+
]
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
# SPDX-License-Identifier: PMPL-1.0-or-later
2-
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
2+
# Copyright (c) 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
33
#
44
# NEUROSYM.a2ml — Neurosymbolic integration metadata
55
# Configuration for Hypatia scanning and symbolic reasoning.
66

77
[metadata]
88
version = "0.1.0"
9-
last-updated = "2026-03-16"
9+
last-updated = "2026-04-12"
1010

1111
[hypatia-config]
1212
scan-enabled = true
1313
scan-depth = "standard"
14-
report-format = "logtalk"
14+
# report-format was "logtalk" — Logtalk removed from Hypatia 2026-04-12.
15+
# Hypatia now consumes JSON AssailReport from panic-attack via Elixir rules.
16+
report-format = "json-assail-report"
17+
18+
[panic-attack]
19+
pre-commit = true
20+
assail-target = "."
21+
# Firmware-Zig: unsafe_blocks category flags extern fn boundary points —
22+
# classify each hit rather than chasing the count (they are legitimate
23+
# ESP-IDF FFI boundaries, not unsafe Zig).
24+
unsafe-blocks-note = "ESP-IDF extern fn stubs are legitimate FFI boundaries, not unsafe code"
Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,87 @@
11
# SPDX-License-Identifier: PMPL-1.0-or-later
2-
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
2+
# Copyright (c) 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
33
#
4-
# PLAYBOOK.a2ml — Operational playbook
4+
# PLAYBOOK.a2ml — Operational runbook
55
# Runbooks, incident response, deployment procedures.
66

77
[metadata]
88
version = "0.1.0"
9-
last-updated = "2026-03-16"
9+
last-updated = "2026-04-12"
1010

11-
[deployment]
12-
# method = "gitops"
13-
# target = "container"
11+
# ------------------------------------------------------------------
12+
# FIRMWARE BUILD + FLASH
13+
# ------------------------------------------------------------------
14+
15+
[firmware.host-tests]
16+
command = "cd firmware-zig && zig build test"
17+
expected = "10/10 tests pass (buffer, sensors, mqtt, ota, wifi)"
18+
note = "all_tests.zig is the host-side root; main.zig excluded (freestanding externs)"
19+
20+
[firmware.esp32-flash]
21+
status = "pending — requires physical ESP32 board + ESP-IDF toolchain"
22+
steps = [
23+
"Install ESP-IDF (idf.py or Zig cross-compile toolchain)",
24+
"Set target: zig build -Dtarget=xtensa-freestanding-none",
25+
"Flash: esptool.py write_flash 0x10000 zig-out/bin/kaldor-bbw-firmware.bin",
26+
"Monitor: idf.py monitor",
27+
]
28+
29+
# ------------------------------------------------------------------
30+
# BACKEND DEVELOPMENT
31+
# ------------------------------------------------------------------
32+
33+
[backend-deno.dev]
34+
command = "cd backend-deno && deno task dev"
35+
note = "Canonical backend. Oak framework, ReScript compiled to JS."
36+
37+
[backend-deno.test]
38+
command = "cd backend-deno && deno task test"
39+
40+
[backend-api-legacy.note]
41+
status = "deprecated — do not develop further"
42+
decommission = "pending Jonathan's backend strategy decision"
43+
44+
# ------------------------------------------------------------------
45+
# FRONTEND
46+
# ------------------------------------------------------------------
47+
48+
[frontend.dev]
49+
command = "cd frontend && npm run dev"
50+
note = "ReScript → JS compiled by rescript, served by Vite"
51+
52+
[frontend.build]
53+
command = "cd frontend && npm run build"
54+
55+
# ------------------------------------------------------------------
56+
# FULL STACK (docker-compose)
57+
# ------------------------------------------------------------------
58+
59+
[full-stack]
60+
command = "docker-compose up"
61+
note = "Brings up Mosquitto, TimescaleDB, backend-deno, frontend. Legacy Node backend excluded."
62+
63+
# ------------------------------------------------------------------
64+
# INCIDENT RESPONSE
65+
# ------------------------------------------------------------------
1466

1567
[incident-response]
16-
# 1. Check .machine_readable/STATE.a2ml for current status
17-
# 2. Review recent commits and CI results
18-
# 3. Run just validate to check compliance
19-
20-
[release-process]
21-
# 1. Update version in STATE.a2ml, META.a2ml
22-
# 2. Run just quality (format, lint, test)
23-
# 3. Tag and push
68+
steps = [
69+
"Check .machine_readable/6a2/STATE.a2ml for current subsystem status",
70+
"Review recent commits: git log --oneline -10",
71+
"Run firmware tests: cd firmware-zig && zig build test",
72+
"Run pre-commit checks: panic-attack assail .",
73+
"Check CI status on GitHub Actions",
74+
]
75+
76+
# ------------------------------------------------------------------
77+
# RELEASE PROCESS
78+
# ------------------------------------------------------------------
79+
80+
[release]
81+
steps = [
82+
"Update version in STATE.a2ml and META.a2ml",
83+
"Update CHANGELOG.md (add dated release section)",
84+
"Run: just quality (format + lint + test)",
85+
"Tag: git tag -s v<version> -m 'Release v<version>'",
86+
"Push tag: git push origin v<version>",
87+
]

0 commit comments

Comments
 (0)