diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3a3b7f2..4714ad5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,34 +1,4 @@ # SPDX-License-Identifier: MPL-2.0 -# CODEOWNERS - Define code review assignments for GitHub -# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners - -# Default: sole maintainer for all files -* @hyperpolymath - -# Security-sensitive files require explicit ownership -SECURITY.md @hyperpolymath -.github/workflows/ @hyperpolymath -.machine_readable/ @hyperpolymath -contractiles/ @hyperpolymath - -# License files -LICENSE @hyperpolymath -LICENSES/ @hyperpolymath - -# Configuration -.gitignore @hyperpolymath -.github/ @hyperpolymath - -# Documentation -README* @hyperpolymath -CONTRIBUTING* @hyperpolymath -CODE_OF_CONDUCT* @hyperpolymath -GOVERNANCE* @hyperpolymath -MAINTAINERS* @hyperpolymath -CHANGELOG* @hyperpolymath -ROADMAP* @hyperpolymath - -# Build and CI -Justfile @hyperpolymath -Makefile @hyperpolymath -*.sh @hyperpolymath +# Solo-maintained hyperpolymath repo: no owner lines by policy. +# See hyperpolymath/standards CODEOWNERS-POLICY.adoc (Rule 1). +# Sole-maintainer review is moot; SPDX headers carry attribution. diff --git a/.github/workflows/scorecard-enforcer.yml b/.github/workflows/scorecard-enforcer.yml new file mode 100644 index 0000000..b0766a8 --- /dev/null +++ b/.github/workflows/scorecard-enforcer.yml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: MPL-2.0 +# Prevention workflow - runs OpenSSF Scorecard and fails on low scores +name: OpenSSF Scorecard Enforcer + +on: + push: + branches: [main] + schedule: + - cron: '0 6 * * 1' # Weekly on Monday + workflow_dispatch: + +# Estate guardrail: cancel superseded runs so re-pushes / rebased PR +# updates do not pile up queued runs against the shared account-wide +# Actions concurrency pool. Applied only to read-only check workflows +# (no publish/mutation), so cancelling a superseded run is always safe. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + scorecard: + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + security-events: write + id-token: write # For OIDC + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Run Scorecard + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4 + with: + sarif_file: results.sarif + + - name: Check minimum score + run: | + # Parse score from results + SCORE=$(jq -r '.runs[0].tool.driver.properties.score // 0' results.sarif 2>/dev/null || echo "0") + + echo "OpenSSF Scorecard Score: $SCORE" + + # Minimum acceptable score (0-10 scale) + MIN_SCORE=5 + + if [ "$(echo "$SCORE < $MIN_SCORE" | bc -l)" = "1" ]; then + echo "::error::Scorecard score $SCORE is below minimum $MIN_SCORE" + exit 1 + fi + + # Check specific high-priority items + check-critical: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Check SECURITY.md exists + run: | + if [ ! -f "SECURITY.md" ]; then + echo "::error::SECURITY.md is required" + exit 1 + fi + + - name: Check for pinned dependencies + run: | + # Check workflows for unpinned actions + unpinned=$(grep -r "uses:.*@v[0-9]" .github/workflows/*.yml 2>/dev/null | grep -v "#" | head -5 || true) + if [ -n "$unpinned" ]; then + echo "::warning::Found unpinned actions:" + echo "$unpinned" + fi diff --git a/0-AI-MANIFEST.a2ml b/0-AI-MANIFEST.a2ml index 60e3acd..0fd65a3 100644 --- a/0-AI-MANIFEST.a2ml +++ b/0-AI-MANIFEST.a2ml @@ -17,3 +17,20 @@ AI manifest for MacroPower.jl. Read this file first before any other work. ;; - No believe_me, assert_total, sorry, Admitted, unsafeCoerce, Obj.magic ;; - SCM files ONLY in .machine_readable/ (never root) ;; - Author: Jonathan D.A. Jewell + + + +## PRIORITY ACTION — this repository is not fully initialised + +1 substitution token(s) still have no value. **Read +`REQUIRES_INITIALISATION.md` in the repository root before doing anything +else here** — it lists every outstanding token, what it means, and which +files it belongs in. + +Do not fabricate values for them, and do not delete the sections that +contain them to quiet a gate. They are unfilled because they need a +decision, not because they were overlooked. Resolve what you legitimately +can, leave the rest, and delete `REQUIRES_INITIALISATION.md` only when +nothing outstanding remains. + + diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md deleted file mode 100644 index 607e3d8..0000000 --- a/ARCHITECTURE.md +++ /dev/null @@ -1,47 +0,0 @@ -# Architecture - -## Overview - -This repository follows a modular, maintainable architecture designed for clarity, scalability, and long-term sustainability. - -## Directory Structure - -``` -. -├── src/ # Source code -├── tests/ # Test suites -├── docs/ # Documentation -├── scripts/ # Utility scripts -├── config/ # Configuration files -├── LICENSE # License file -├── LICENSES/ # Full license texts -└── README.adoc # Project documentation -``` - -## Design Principles - -- **Separation of Concerns**: Each module has a single responsibility -- **Testability**: Code is written to be easily testable -- **Documentation**: All public APIs are documented -- **Configuration**: Environment-specific settings are externalized - -## Dependencies - -- External dependencies are minimized and clearly declared -- Version pinning is used for reproducibility - -## Security Considerations - -- Sensitive data is never committed to the repository -- Secrets are managed through environment variables or secure vaults -- Regular dependency audits are performed - -## Maintainability - -- Code follows consistent style guidelines -- Pull requests require review and CI checks -- Issues and discussions are tracked transparently - ---- - -*Last updated: 2026-07-18* diff --git a/FUNDING b/FUNDING new file mode 100644 index 0000000..7e58d67 --- /dev/null +++ b/FUNDING @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MPL-2.0 for code +// SPDX-License-Identifier: CC-BY-SA-4.0 for documentation +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell + += Funding +:toc: macro +:toclevels: 2 + +This document lists the supported funding platforms for the hyperpolymath and metadatastician estates. + +== Supported Funding Platforms + +[cols="1,1",options="header"] +|=== +| Platform | Username +| Buy Me a Coffee | jonathan.jewell +| Community Bridge | jonathan-jewell +| GitHub Sponsors | hyperpolymath +| IndieWeb | +| IssueHunt | hyperpolymath +| Ko-fi | hyperpolymath +| LFX Crowdfunding | hyperpolymath +| LiberaPay | hyperpolymath +| Open Collective | jonathan-jewell +| Patreon | cc_studio +| Polar | hyperpolymath +| Thanks Dev | hyperpolymath +|=== + +== Usage + +These platforms provide financial support mechanisms for the projects within the hyperpolymath and metadatastician estates. Contributions through any of these platforms help sustain development, maintenance, and governance of the open source projects. + +For more information about contributing or sponsoring specific projects, please refer to the project's README file or contact the maintainers directly. diff --git a/PROOF-PROGRESS.adoc b/PROOF-PROGRESS.adoc new file mode 100644 index 0000000..5721cb0 --- /dev/null +++ b/PROOF-PROGRESS.adoc @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell +// +// Proof Progress Snapshot — MacroPower.jl +// Generated: 2026-08-14 + += MacroPower.jl — Proof/Verification Guarantee Progress Snapshot +:toc: +:icons: font + +This document provides an indicative state of progress on formal guarantees for +the MacroPower.jl Julia package as of 2026-08-14. It consolidates information from: + +- `README.md` — Project overview and automation tool claims +- `EXPLAINME.adoc` — Verification receipts and honest caveats +- `src/MacroPower.jl` — Core workflow implementation +- `test/runtests.jl` — Test suite + +== Headline Status + +[cols="1,2,3",options="header"] +|=== +| Component | Status | Details + +| Low-code automation tool | 🟡 PARTIAL | Define Flows connecting events to actions — struct-based API works + +| Trigger type | ✅ COMPLETE | `Trigger(name::String, check::Function)` with Bool predicate + +| Action type | ✅ COMPLETE | `Action(name::String, execute::Function)` with side-effecting closure + +| Workflow type | ✅ COMPLETE | `Workflow(name, triggers, actions)` — top-level execution unit + +| run_workflow | ✅ COMPLETE | Iterates triggers, executes actions on true check + +| @workflow macro | ⚠️ STUB | Prints message, returns empty Workflow — does NOT parse block + +| File System events | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| HTTP events | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| Time triggers | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| Run Script action | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| Send Alert action | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| Database Write action | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| when(...) -> ... DSL | ❌ NOT IMPLEMENTED | Macro does not parse DSL syntax + +| time_is() function | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| file_changed() function | ❌ NOT IMPLEMENTED | Described in README but not implemented + +| Concurrency | ❌ NOT IMPLEMENTED | Simple eager evaluation loop — no concurrency + +| Event loop | ❌ NOT IMPLEMENTED | No event loop implemented + +| Macro body parser | ❌ NOT IMPLEMENTED | Listed as "to do" in macro comment +|=== + +**Overall:** MacroPower.jl provides a **partially implemented** low-code automation +tool. The struct-based API (directly constructing `Trigger`, `Action`, and `Workflow`) +is fully working. The `@workflow` macro exists but is a stub that does not parse the +DSL syntax shown in the README. Much of the README's event source and action +descriptions are aspirational. + +**Honest Assessment:** At 20% completion (per TOPOLOGY badge), MacroPower.jl is an +early prototype with the core data structures and execution loop working, but the +declarative DSL and built-in event sources/actions are not yet implemented. + +== Current Implementation + +=== Core Data Structures + +`src/MacroPower.jl` defines three composable structs: + +**Trigger:** +- Fields: `name::String`, `check::Function` +- The `check` field is a zero-argument function returning `Bool` +- Used to define boolean predicates that determine when actions should execute + +**Action:** +- Fields: `name::String`, `execute::Function` +- The `execute` field is a side-effecting closure +- Used to define operations to perform when triggers fire + +**Workflow:** +- Fields: `name::String`, `triggers::Vector{Trigger}`, `actions::Vector{Action}` +- The top-level execution unit +- Contains collections of triggers and actions + +=== Execution Model + +`run_workflow(wf)` implements a simple eager evaluation loop: + +1. Iterates over `wf.triggers` +2. Calls `t.check()` on each trigger +3. When `check()` returns `true`, iterates over `wf.actions` +4. Calls `a.execute()` on each action + +**Characteristics:** +- No concurrency — sequential execution +- No event loop — direct function calls +- Eager evaluation — all triggers checked on each run + +=== The @workflow Macro + +The `@workflow` macro provides a declarative surface syntax: + +[source,julia] +---- +flow = @workflow "Nightly Backup" begin + when(time_is("02:00")) -> backup_database() + when(file_changed("/tmp/data")) -> process_data() +end +---- + +**Current Implementation:** +- Accepts a name expression and a block +- Ignores the block contents +- Returns a `Workflow` with the given name and empty `Trigger[]`/`Action[]` vectors +- Does NOT parse `when(...) -> ...` syntax + +**Status:** Stub implementation — the README syntax compiles without error because +`when`, `time_is`, and `file_changed` are not called at compile time, but the +resulting workflow has no triggers or actions. + +== Test Evidence + +From EXPLAINME.adoc lines 72-80: + +Tests in `test/runtests.jl` verify: + +[cols="1,3,1",options="header"] +|=== +| Test | Description | Status + +| Trigger construction | name is a String, check is a Function | ✅ PASS + +| Trigger execution | Calling check() returns expected Bool | ✅ PASS + +| Action construction | name is a String, execute is a Function | ✅ PASS + +| Action execution | Calling execute() returns expected value | ✅ PASS + +| Workflow construction | One trigger and one action | ✅ PASS + +| Empty workflow | Workflow with empty triggers and actions | ✅ PASS + +| Multiple triggers/actions | Lengths are correct | ✅ PASS + +| run_workflow | Executes actions when triggers fire | ✅ PASS +|=== + +== Formal Verification Status + +=== Current Formal Content + +[cols="1,3,1,1",options="header"] +|=== +| Area | Formal Verification | Status | Evidence + +| Trigger construction | Type and field correctness | ✅ TESTED | Tests pass + +| Action construction | Type and field correctness | ✅ TESTED | Tests pass + +| Workflow construction | Type and field correctness | ✅ TESTED | Tests pass + +| run_workflow logic | Trigger check and action execution | ✅ TESTED | Tests pass + +| Multiple triggers | Correct iteration and execution | ✅ TESTED | Tests pass + +| Multiple actions | Correct iteration and execution | ✅ TESTED | Tests pass + +| DSL parsing | when(...) -> ... syntax | ❌ NOT IMPLEMENTED | Stub only + +| Event sources | File System, HTTP, Time | ❌ NOT IMPLEMENTED | Not implemented + +| Actions | Run Script, Send Alert, Database Write | ❌ NOT IMPLEMENTED | Not implemented +|==== + +=== Planned Formal Proofs + +Integration with Axiom.jl would enable: + +[source,julia] +---- +using Axiom +using MacroPower + +# Trigger properties +@prove forall(t::Trigger) do isa(t.name, String) end +@prove forall(t::Trigger) do isa(t.check, Function) end + +# Action properties +@prove forall(a::Action) do isa(a.name, String) end +@prove forall(a::Action) do isa(a.execute, Function) end + +# Workflow properties +@prove forall(w::Workflow) do length(w.triggers) >= 0 end +@prove forall(w::Workflow) do length(w.actions) >= 0 end + +# Execution properties +@prove forall(w::Workflow) do + # If no triggers fire, no actions execute + all(t -> !t.check(), w.triggers) => + run_workflow(w) == nothing end + +@prove forall(w::Workflow) do + # If a trigger fires, its corresponding actions execute + any(t -> t.check(), w.triggers) => + # At least one action executes + true end # Placeholder — actual proof needs execution tracking +---- + +== Aspirational Features + +The README describes features that are **not yet implemented**: + +=== Described but Not Implemented + +[cols="1,2,1",options="header"] +|=== +| Feature | Description | Status + +| File System events | File watching for changes | ❌ NOT IMPLEMENTED + +| HTTP events | HTTP client for webhook triggers | ❌ NOT IMPLEMENTED + +| Time triggers | Scheduler for time-based triggers | ❌ NOT IMPLEMENTED + +| Run Script action | Script execution action | ❌ NOT IMPLEMENTED + +| Send Alert action | Alert notification action | ❌ NOT IMPLEMENTED + +| Database Write action | Database write action | ❌ NOT IMPLEMENTED + +| when(...) -> ... DSL | Declarative workflow syntax | ❌ NOT IMPLEMENTED + +| time_is() | Time checking function | ❌ NOT IMPLEMENTED + +| file_changed() | File change detection function | ❌ NOT IMPLEMENTED + +| Concurrency | Concurrent trigger checking | ❌ NOT IMPLEMENTED + +| Event loop | Asynchronous event processing | ❌ NOT IMPLEMENTED + +| Macro body parser | Parse when(...) -> ... syntax | ❌ NOT IMPLEMENTED +|=== + +=== Honest Caveats + +From EXPLAINME.adoc: + +. The event source descriptions in the README (File System, HTTP, Time triggers; + Send Alert, Database Write actions) are aspirational. + +. The current implementation has no file-watching, no HTTP client, no scheduler, + and no database connector. + +. All triggers and actions must be supplied as plain Julia closures by the caller. + +. The `@workflow` macro does not parse `when(...) -> ...` syntax from the block — + that parsing is listed as a "to do" in the macro comment. + +. At 20% completion (per the TOPOLOGY badge), the macro body parser is the + primary missing piece. + +. The README syntax compiles without error because `when`, `time_is`, and + `file_changed` are not called at compile time — but the resulting workflow has + no triggers or actions. + +. The struct-based API (constructing `Trigger` and `Action` directly and passing + them to `Workflow(name, triggers, actions)`) is the fully working path today. + +== Ecosystem Integration + +MacroPower.jl is designed to integrate with the Hyperpolymath automation ecosystem: + +[cols="1,2,1",options="header"] +|=== +| Project | Connection | Status + +| Hyperpolymath ecosystem | Automation engine for the ecosystem | ✅ DESIGNED + +| Other Julia packages | Can use MacroPower for automation | 🟡 POTENTIAL + +| Axiom.jl | Formal verification framework | 🟡 PLANNED +|=== + +**Design Philosophy:** + +MacroPower.jl is the **Automation Engine for the Hyperpolymath Ecosystem**, designed +to provide low-code/no-code automation capabilities. The current implementation +is a foundation upon which the full automation suite will be built. + +== Current Status Summary + +[cols="1,2,1",options="header"] +|=== +| Category | Description | Count/Status + +| Core data structures | Trigger, Action, Workflow | 3 types + +| Working API | Struct-based construction | ✅ COMPLETE + +| Macro DSL | @workflow macro | ⚠️ STUB + +| Event sources | File System, HTTP, Time | 0/3 implemented + +| Actions | Run Script, Send Alert, Database Write | 0/3 implemented + +| Passing tests | Core functionality tests | 8+ tests + +| Completion | Per TOPOLOGY badge | 20% + +| Completion | Actual functionality | ~30% +|=== + +== Outstanding Work + +=== Immediate Next Steps + +1. **Implement macro body parser**: Parse `when(...) -> ...` DSL syntax +2. **Implement time_is()**: Add time checking function +3. **Implement file_changed()**: Add file change detection +4. **Implement event loop**: Add asynchronous event processing +5. **Implement concurrency**: Add concurrent trigger checking +6. **Implement Run Script action**: Add script execution capability +7. **Implement Send Alert action**: Add alert notification +8. **Implement Database Write action**: Add database write capability + +=== Medium-term Goals + +1. **File System events**: Add file watching for change detection +2. **HTTP events**: Add HTTP client for webhook triggers +3. **Time triggers**: Add scheduler for time-based automation +4. **Complete DSL**: Full declarative workflow syntax +5. **Error handling**: Robust error handling for actions +6. **Logging**: Action execution logging + +=== Long-term Vision + +1. **Full automation engine**: Complete low-code/no-code automation tool +2. **Ecosystem integration**: Integrated with all Hyperpolymath packages +3. **Enterprise automation**: Production-ready automation capabilities +4. **Safety-critical automation**: Certified automation for critical applications + +== References + +* https://github.com/hyperpolymath/Axiom.jl[Axiom.jl] — Formal verification framework + +== Document Information + +[cols="1,2"] +|=== +| Generated | 2026-08-14 | +| Author | Mistral Vibe (on behalf of Jonathan D.A. Jewell) | +| Source | README.md, EXPLAINME.adoc, src/MacroPower.jl, test/runtests.jl | +| Status | Snapshot — subject to change as implementation progresses | +|=== diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..de4f2f4 --- /dev/null +++ b/README.adoc @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) Jonathan D.A. Jewell += MacroPower.jl +:toc: macro + +image:https://img.shields.io/badge/Project-Topology-9558B2[Topology,link="TOPOLOGY.md"] +image:https://img.shields.io/badge/Completion-20%25-red[20%,link="TOPOLOGY.md"] +image:https://img.shields.io/badge/OpenSSF-Best_Practices-green?logo=opensourcesecurity[OpenSSF Best Practices,link="https://www.bestpractices.dev/en/projects/new?repo_url=https://github.com/hyperpolymath/MacroPower.jl"] +image:https://img.shields.io/badge/License-PMPL--1.0-blue.svg[License: PMPL-1.0] +image:https://api.thegreenwebfoundation.org/greencheckimage/github.com[Green Web,link="https://www.thegreenwebfoundation.org/green-web-check/?url=github.com"] + +*The Automation Engine for the Hyperpolymath Ecosystem.* + +MacroPower.jl is a low-code/no-code style automation tool for Julia. It allows you to define "Flows" that connect events (File System, HTTP, Time) to actions (Run Script, Send Alert, Database Write). + +== Quick Start + +[source,julia] +---- +using MacroPower + +# Define a flow +flow = @workflow "Nightly Backup" begin + when(time_is("02:00")) -> backup_database() + when(file_changed("/tmp/data")) -> process_data() +end + +run_workflow(flow) +---- diff --git a/REQUIRES_INITIALISATION.md b/REQUIRES_INITIALISATION.md new file mode 100644 index 0000000..9f1a17e --- /dev/null +++ b/REQUIRES_INITIALISATION.md @@ -0,0 +1,54 @@ + + +# REQUIRES INITIALISATION + +**This repository is not finished being set up.** 1 substitution token(s) across 1 file(s) still have no value. + +## Why this is not already done + +This repo was created from `hyperpolymath/rsr-template-repo`. The mint +(`just repo-init`) fills every token that has a single mechanical answer — +owner, repo, author, dates, licence, branch — and it has done so here. + +The tokens below are the ones it *deliberately cannot* answer. They need a +decision or a fact that exists only in your head: what this project is for, +what command builds it, which port the service listens on, whether a PGP key +is held at all. The template's own token vocabulary says as much — you cannot +sensibly answer "required invariants" in a thirty-second bootstrap. + +They were left **visibly unfilled on purpose**. The alternatives were both +worse: inventing plausible values would put confident falsehoods into a +security policy and an architecture document, and silently deleting the +sections would hide the fact that a decision is owed. A visible gap is +honest; a fabricated answer is not. + +## Do not delete this file until every item below is resolved + +This file is the only marker that the work is outstanding. Deleting it early +does not finish the setup, it just conceals it — and the next person or agent +to arrive will reasonably assume the repo is complete. + +- **If you are a person:** delete this file yourself once the last item is done. +- **If you are an agent:** resolve what you legitimately can, leave the rest, + and delete this file only when no token below remains anywhere in the tree. + Do not delete it to make a gate go green. + +Re-running the estate top-up tool will remove this file automatically once +nothing is outstanding, so the safest way to finish is to fix the tokens and +let the check confirm it. + +## What is needed, and where it goes + +### `{{PROJECT_UNIQUE_STRENGTH}}` + +What this does that its alternatives do not. + +Appears in: + +- `.machine_readable/bot_directives/methodology.a2ml` + +--- + +Generated by the estate top-up pass. Rationale and the governing rulings are +in `hyperpolymath/standards`; the token vocabulary is +`.machine_readable/ai/PLACEHOLDERS.adoc` in `rsr-template-repo`. diff --git a/guix.scm b/guix.scm deleted file mode 100644 index 7538f14..0000000 --- a/guix.scm +++ /dev/null @@ -1,18 +0,0 @@ -; SPDX-License-Identifier: MPL-2.0 -;; guix.scm — GNU Guix package definition for MacroPower.jl -;; Usage: guix shell -f guix.scm - -(use-modules (guix packages) - (guix build-system gnu) - (guix licenses)) - -(package - (name "MacroPower.jl") - (version "0.1.0") - (source #f) - (build-system gnu-build-system) - (synopsis "MacroPower.jl") - (description "MacroPower.jl — part of the hyperpolymath ecosystem.") - (home-page "https://github.com/hyperpolymath/MacroPower.jl") - (license ((@@ (guix licenses) license) "MPL-2.0" - "https://github.com/hyperpolymath/palimpsest-license")))