diff --git a/docs/backlog/P1/B-0424-three-repo-split-stage1-create-forge-ace-with-scaffolding-aaron-2026-05-13.md b/docs/backlog/P1/B-0424-three-repo-split-stage1-create-forge-ace-with-scaffolding-aaron-2026-05-13.md index 33f36a2ba3..5cea86eba3 100644 --- a/docs/backlog/P1/B-0424-three-repo-split-stage1-create-forge-ace-with-scaffolding-aaron-2026-05-13.md +++ b/docs/backlog/P1/B-0424-three-repo-split-stage1-create-forge-ace-with-scaffolding-aaron-2026-05-13.md @@ -56,27 +56,23 @@ Both with full best-practice scaffolding applied at creation: - Declarative `docs/GITHUB-SETTINGS.md` per repo - Per-repo `docs/UPSTREAM-RHYTHM.md` -## Pre-start checklist - -Before beginning Stage 1 work, complete per -`.claude/rules/backlog-item-start-gate.md`: - -1. **Prior-art-search** — verify the existing substrate hasn't drifted: - - `memory/project_three_repo_split_zeta_forge_ace_software_factory_named_forge.md` - - `docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md` - - `memory/project_ace_package_manager_agent_negotiation_propagation.md` - - Compose with current LFG/AceHack topology - (`.claude/rules/lfg-acehack-topology.md`) - -2. **Dependency-restructure** — walk `composes_with:` chain; - reciprocal pointers added to the substrate files above as needed. - -3. **License question resolved** — apply B-0425's honor-system - "please don't fork" license framing if applicable to strategic - product-substrate repos. Factory (Forge) + package manager (ace) - + database (Zeta) are designed-to-be-forked per their open-source - nature; the honor-system framing applies to strategic *product* - repos (KSK / wellness / civsim strategic-substrate etc.), not these. +## Pre-start checklist — COMPLETED 2026-05-13 (B-0424.1) + +Per `.claude/rules/backlog-item-start-gate.md`: + +1. **Prior-art-search** — completed 2026-05-13: + - `memory/project_three_repo_split_zeta_forge_ace_software_factory_named_forge.md` — read; substrate current, Stage 0 done (ADR exists) + - `docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md` — read; full checklist present, no drift + - `memory/project_ace_package_manager_agent_negotiation_propagation.md` — file exists; ace name + Ouroboros design confirmed + - LFG/AceHack topology (`.claude/rules/lfg-acehack-topology.md`) — LFG is active dev; AceHack is mirror; Forge + ace repos do NOT yet exist at LFG — confirmed via worldview refresh (0 open PRs on main) + - No existing `tools/scaffold/` directory — clean slate, no prior art to extend + - Skill router checked: no existing scaffold or repo-creation skill + +2. **Dependency-restructure** — B-0425 (product-repo split planning) is sibling row, not a blocker for Stage 1. Reciprocal pointer in B-0425 not yet present; will add in a follow-up pass. Stage 1 is executable independently. + +3. **License question resolved** — Apache 2.0 (same as Zeta). Forge and ace are open-source/designed-to-be-forked; honor-system framing does not apply. + +4. **Scope decision** — B-0424 is too broad to implement in one PR. This PR (B-0424.1) implements the smallest safe slice: day-one governance file templates for Forge and ace + a TypeScript dry-run tool (`tools/scaffold/create-repo.ts`) that shows the GitHub API calls needed to complete Stage 1. Actual GitHub repo creation (irreversible external action) is deferred to a follow-up PR with Aaron's review. ## Composes with diff --git a/tools/scaffold/README.md b/tools/scaffold/README.md new file mode 100644 index 0000000000..3e085e5f54 --- /dev/null +++ b/tools/scaffold/README.md @@ -0,0 +1,79 @@ +# tools/scaffold — B-0424 Stage 1 repo scaffolding + +Governance-file templates and a dry-run TypeScript tool for creating the +`LFG/Forge` and `LFG/ace` repos with the full best-practice checklist +from [ADR 2026-04-22](../../docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md). + +## Usage + +```bash +# Preview what will happen (default, no external side effects): +bun tools/scaffold/create-repo.ts --repo forge --dry-run +bun tools/scaffold/create-repo.ts --repo ace --dry-run + +# Execute for real (creates GitHub repos under LFG org): +bun tools/scaffold/create-repo.ts --repo forge --apply +bun tools/scaffold/create-repo.ts --repo ace --apply +``` + +**`--apply` creates real GitHub repos.** Review `--dry-run` output first. + +## What the tool does + +For each repo, in **execution order** (step numbers are stable identifiers, not sequential labels — step 06 runs before step 02 intentionally): + +| Step | Description | +|------|-------------| +| 01 | Create repo (public, squash-merge only, auto-merge, delete-branch) | +| 06 | Push day-one governance files from `tools/scaffold//` — **runs before branch protection** so files can be pushed directly to `main` | +| 02 | Apply branch protection on `main` (1 review, signed commits, linear history, no force-push) | +| 03 | Enable secret scanning + push protection, Dependabot, private vulnerability reporting | +| 04 | Enable CodeQL **default-setup** (required for `code_scanning` ruleset rule) | +| 05 | Fork repo to `AceHack/` | +| 07 | Print manual steps remaining (SVG preview, merge queue, Scorecard workflow) | + +## Template files + +Each sub-directory contains the governance files for that repo: + +``` +tools/scaffold/ + forge/ — Forge day-one governance files + README.md + AGENTS.md + CLAUDE.md + GOVERNANCE.md + SECURITY.md + CODE_OF_CONDUCT.md + CONTRIBUTING.md + LICENSE + .github/ + copilot-instructions.md + docs/ + GITHUB-SETTINGS.md + + ace/ — ace day-one governance files + (same structure, ace-scoped content) + + create-repo.ts — this tool + README.md — this file +``` + +## Manual steps after --apply + +The tool prints these at the end, but for reference: + +1. Upload SVG social-preview PNG via GitHub UI + (GitHub requires a rasterized PNG format — SVG not accepted) +2. Enable merge queue via GitHub UI + (Settings → Merge queue — org feature, no REST API) +3. Wire OpenSSF Scorecard workflow + (copy from Zeta's `.github/workflows/scorecard.yml`) +4. Add Semgrep GHA inline-untrusted-in-run rule +5. Verify $0 budget caps at org level in GitHub billing settings +6. Confirm CodeQL default-setup is active under Security → Code scanning + +## Origin + +B-0424 (P1) — Three-repo split Stage 1. +ADR: `docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md`. diff --git a/tools/scaffold/ace/.github/copilot-instructions.md b/tools/scaffold/ace/.github/copilot-instructions.md new file mode 100644 index 0000000000..81b91d9071 --- /dev/null +++ b/tools/scaffold/ace/.github/copilot-instructions.md @@ -0,0 +1,21 @@ +# GitHub Copilot instructions for ace + +ace is the package manager for the Lucent Financial Group software stack. + +## Key conventions + +- TypeScript / Bun for all tooling (Rule 0 — no `.sh` outside `tools/setup/`) +- Errors as `Result<_, Error>` values — no exceptions on hot paths +- Every AI-authored commit includes a `Co-Authored-By` trailer +- `bun test && bun run lint` must pass before any PR merges + +## What this repo is NOT + +ace is not Forge (the software factory) and not Zeta (the database). +Questions about factory tooling → Forge repo. +Questions about the database → Zeta repo. + +## Pre-v1 caution + +ace has no implementation yet. Copilot suggestions for unimplemented +features should be treated as design proposals, not production code. diff --git a/tools/scaffold/ace/AGENTS.md b/tools/scaffold/ace/AGENTS.md new file mode 100644 index 0000000000..4c860320d5 --- /dev/null +++ b/tools/scaffold/ace/AGENTS.md @@ -0,0 +1,43 @@ +# AGENTS.md — how AI and humans approach ace + +ace is the package manager for the Lucent Financial Group software stack. +Every file in `src/**`, `tools/**`, `docs/**` is agent-authored. + +## Philosophy + +ace is **human-maintainer-owned** for governance. The factory's AI agent +has authoring and operation rights. The three load-bearing values (same as +Zeta + Forge): + +1. **Truth over politeness.** Claims that fail tests get fixed. +2. **Algebra over engineering.** Laws define the system. +3. **Velocity over stability.** Pre-v1. Ship, do no permanent harm, learn. + +## Build gate (once implemented) + +```bash +bun test # zero failures +bun run lint # zero warnings +``` + +## Agent conventions + +- **Agents, not bots.** Every AI carries agency. +- **Substrate or it didn't happen.** Committed git history is substrate. +- **Rule 0 — TS over bash.** Factory tooling is `.ts` via `bun`. +- **Retraction-native.** Every action has a bounded undo path. +- **Result-over-exception.** Errors as values; no exceptions on hot paths. + +## Cross-repo references + +- **Zeta** — ace's persistence layer once ace ships. + `github.com/Lucent-Financial-Group/Zeta` +- **Forge** — the factory that builds ace. + `github.com/Lucent-Financial-Group/Forge` + +## Design reference + +[ace design doc](https://github.com/Lucent-Financial-Group/Zeta/blob/main/memory/project_ace_package_manager_agent_negotiation_propagation.md) +(Zeta repo) — full ace design, Ouroboros bootstrap, red-team discipline. + + diff --git a/tools/scaffold/ace/CLAUDE.md b/tools/scaffold/ace/CLAUDE.md new file mode 100644 index 0000000000..8bf0148ab1 --- /dev/null +++ b/tools/scaffold/ace/CLAUDE.md @@ -0,0 +1,37 @@ +# CLAUDE.md — Claude Code session bootstrap for ace + +Rules auto-load from `.claude/rules/`; skills load on demand from `.claude/skills/`. + +## 1. Orient + +Read: [`AGENTS.md`](AGENTS.md) → [`GOVERNANCE.md`](GOVERNANCE.md). +Check [`docs/WONT-DO.md`](docs/WONT-DO.md) before proposing work. + +## 2. Refresh + +```bash +bun tools/github/refresh-worldview.ts +``` + +## 3. Pick work + +Open `docs/BACKLOG.md`. Complete the backlog-item start gate before +starting any row (prior-art search + dependency check). + +## 4. Build gate + +```bash +bun test # 0 failures +bun run lint # 0 warnings +``` + +## 5. Ship + +Set branch: `export ZETA_EXPECTED_BRANCH= && git checkout -b "$ZETA_EXPECTED_BRANCH"` +Open PR against `main`. Arm auto-merge: `gh pr merge --auto --squash`. + +## Conventions + +- **Agents, not bots** — every AI carries agency; correct "bot" gently. +- **Rule 0 — TS over bash** — `.ts` via `bun`; `.sh` only in `tools/setup/`. +- **Substrate or it didn't happen** — committed git history is substrate. diff --git a/tools/scaffold/ace/CODE_OF_CONDUCT.md b/tools/scaffold/ace/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..e4fc71399a --- /dev/null +++ b/tools/scaffold/ace/CODE_OF_CONDUCT.md @@ -0,0 +1,40 @@ +# Contributor Covenant Code of Conduct + +## Our pledge + +We as members, contributors, and leaders pledge to make participation in +our community a harassment-free experience for everyone, regardless of +age, body size, visible or invisible disability, ethnicity, sex +characteristics, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, +welcoming, diverse, inclusive, and healthy community. + +## Our standards + +Examples of behavior that contributes to a positive environment: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes + +Examples of unacceptable behavior: + +- The use of sexualized language or imagery +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information without explicit permission + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may +be reported to the project maintainers. All complaints will be reviewed +and investigated promptly and fairly. + +## Attribution + +This Code of Conduct is adapted from the +[Contributor Covenant](https://www.contributor-covenant.org), version 2.1. diff --git a/tools/scaffold/ace/CONTRIBUTING.md b/tools/scaffold/ace/CONTRIBUTING.md new file mode 100644 index 0000000000..5547166b41 --- /dev/null +++ b/tools/scaffold/ace/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# Contributing to ace + +ace is an AI-directed package manager project. Most contributions are +agent-authored. Human contributors are welcome. + +## Quick-start + +```bash +git clone https://github.com/Lucent-Financial-Group/ace +cd ace +bun install +bun test +``` + +## What to work on + +Open `docs/BACKLOG.md`. ace is pre-v1 — the implementation doesn't exist +yet. Early contributions are design (ADRs, specs) and scaffolding (CI, +tooling setup). + +## Before you submit + +1. `bun test` — zero failures +2. `bun run lint` — zero warnings +3. PR description: what changed + why + +## Commit style + +One logical change per commit. `Co-Authored-By` trailer required for +AI-authored commits (see `GOVERNANCE.md §6`). + +## Design reference + +Full ace design, the Ouroboros bootstrap, and the red-team discipline +live in `memory/project_ace_package_manager_agent_negotiation_propagation.md` +in the [Zeta repo](https://github.com/Lucent-Financial-Group/Zeta). + +## Security + +Report vulnerabilities via GitHub's private vulnerability reporting — +see `SECURITY.md`. Do not open public issues for security findings. + +## License + +By contributing you agree that your contributions are licensed under +the Apache 2.0 license. diff --git a/tools/scaffold/ace/GOVERNANCE.md b/tools/scaffold/ace/GOVERNANCE.md new file mode 100644 index 0000000000..0976b1d8a4 --- /dev/null +++ b/tools/scaffold/ace/GOVERNANCE.md @@ -0,0 +1,53 @@ +# GOVERNANCE.md — ace numbered rules + +ace is the package manager. These rules govern ace operation. + +--- + +## §1 Scope + +ace governs the *package manager* (how the Lucent stack is distributed +and versioned), not the *factory* (Forge) or the *database* (Zeta). + +## §2 Ownership + +ace is **human-maintainer-owned** for final governance. The factory's AI +agent has authoring and operation rights (land code, configure CI, open +PRs). Any public-announce or product-direction change routes through the +human maintainer. + +## §3 Agents, not bots + +Every AI working in this repo carries agency. Correct "bot" gently. + +## §4 Rule 0 — TypeScript over bash + +All tooling is `.ts` run via `bun`. Shell (`.sh`) only in `tools/setup/`. + +## §5 Build gate + +`bun test` (0 failures) and `bun run lint` (0 warnings) before every merge. + +## §6 Commit attribution + +Every AI-authored commit must include a `Co-Authored-By` trailer. + +| Harness | Trailer | +|---------|---------| +| Claude Code | `Co-Authored-By: Claude ` | +| OpenAI Codex | `Co-Authored-By: Codex ` | +| Cursor (Grok) | `Co-Authored-By: Grok ` | +| Kiro (Qwen) | `Co-Authored-By: Kiro ` | +| Human | git author sufficient | + +## §7 PR discipline + +Squash-merge only. Delete head branches on merge. One logical change per PR. + +## §8 Substrate or it didn't happen + +Chat and TaskUpdate are weather. Committed git history is substrate. + +--- + +*Rationale lives in `.claude/rules/` and `memory/` in the Forge repo.* diff --git a/tools/scaffold/ace/LICENSE b/tools/scaffold/ace/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/tools/scaffold/ace/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/tools/scaffold/ace/README.md b/tools/scaffold/ace/README.md new file mode 100644 index 0000000000..a346bb2b5c --- /dev/null +++ b/tools/scaffold/ace/README.md @@ -0,0 +1,43 @@ +# ace — package manager + +**ace** is the package manager for the Lucent Financial Group software +stack. It distributes the [Forge](https://github.com/Lucent-Financial-Group/Forge) +factory, the [Zeta](https://github.com/Lucent-Financial-Group/Zeta) database, +and its own updates to future adopters. + +Zeta serves as ace's persistence layer. ace closes the Ouroboros loop: + +``` +ace pull forge@ +ace pull zeta@ +``` + +## Status + +**Pre-v1. No implementation yet.** + +ace is planned but unbuilt. This repo is the day-one scaffolding shell +created during Stage 1 of the three-repo split +([ADR 2026-04-22](https://github.com/Lucent-Financial-Group/Zeta/blob/main/docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md)). +Implementation begins when Zeta approaches v1 (Stage 3 of the migration +plan). + +## Name + +`ace` — lowercase, Unix-CLI convention. Name resolved 2026-04-20; see +[ace design doc](https://github.com/Lucent-Financial-Group/Zeta/blob/main/memory/project_ace_package_manager_agent_negotiation_propagation.md) +in the Zeta repo. + +## Governance + +ace is **human-maintainer-owned** for final governance (name, product +direction, public-announce timing). The factory's AI agent has authoring +and operation rights (land code, configure CI, open PRs). + +## Contributing + +See [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`AGENTS.md`](AGENTS.md). + +## License + +Apache 2.0 — see [`LICENSE`](LICENSE). diff --git a/tools/scaffold/ace/SECURITY.md b/tools/scaffold/ace/SECURITY.md new file mode 100644 index 0000000000..ace6d55773 --- /dev/null +++ b/tools/scaffold/ace/SECURITY.md @@ -0,0 +1,28 @@ +# Security policy + +## Supported versions + +ace is pre-v1. All versions on `main` are supported. + +## Reporting a vulnerability + +Use GitHub's private vulnerability reporting: +**Security → Report a vulnerability** on this repository. + +Do **not** open a public issue for security vulnerabilities. + +We aim to acknowledge reports within 2 business days. + +## Scope + +ace is a package manager. Primary attack surfaces: + +- Package manifest tampering (integrity verification is a core design requirement) +- Supply-chain compromise via Bun package dependencies +- CI workflow poisoning (SHA-pinned actions, minimal permissions) +- Prompt-injection via package metadata consumed by agent workflows + +## Out of scope + +Vulnerabilities in upstream packages should be reported to those projects. +We track upstream advisories via Dependabot. diff --git a/tools/scaffold/ace/docs/GITHUB-SETTINGS.md b/tools/scaffold/ace/docs/GITHUB-SETTINGS.md new file mode 100644 index 0000000000..8af993c01c --- /dev/null +++ b/tools/scaffold/ace/docs/GITHUB-SETTINGS.md @@ -0,0 +1,79 @@ +# docs/GITHUB-SETTINGS.md — declarative GitHub settings for ace + +Source of truth for ace's GitHub repository configuration. Drift is a +factory-hygiene finding. Cadenced diff via `gh api`. + +Origin: ADR 2026-04-22 §"Repo best practices — applied at creation". + +--- + +## Visibility + +- Upstream `Lucent-Financial-Group/ace`: **public** +- Fork `AceHack/ace`: public + +## Merge settings + +| Setting | Value | +|---------|-------| +| Allow merge commits | **disabled** | +| Allow squash merging | **enabled** | +| Allow rebase merging | **disabled** | +| Delete head branches on merge | **enabled** | +| Allow auto-merge | **enabled** | + +## Merge queue + +Merge queue: **enabled** (LFG org feature). + +## Branch protection — `main` + +| Rule | Value | +|------|-------| +| Require pull request before merging | **enabled** | +| Required approving reviews | 1 | +| Dismiss stale reviews on push | **enabled** | +| Require status checks to pass | **enabled** | +| Required status checks | `bun-test`, `bun-lint`, `codeql`, `scorecard` _(added in Stage 2 after CI workflows are wired — empty at day-one to avoid deadlocking bootstrap)_ | +| Require branches up to date | **enabled** | +| Require conversation resolution | **enabled** | +| Require signed commits | **enabled** | +| Require linear history | **enabled** | +| Include administrators | **enabled** | +| Allow force pushes | **disabled** | +| Allow deletions | **disabled** | + +## Security + +| Setting | Value | +|---------|-------| +| Secret scanning | **enabled** | +| Push protection | **enabled** | +| Dependency graph | **enabled** | +| Dependabot alerts | **enabled** | +| Dependabot security updates | **enabled** | +| Code scanning (CodeQL) | **default-setup** | +| Private vulnerability reporting | **enabled** | + +## Budget caps (LFG org level) + +| Surface | Spending limit | +|---------|---------------| +| Copilot | $0 | +| Actions | $0 | +| Packages | $0 | + +## Cadence check + +```bash +gh api repos/Lucent-Financial-Group/ace | jq '{ + visibility: .visibility, + allow_squash_merge: .allow_squash_merge, + allow_merge_commit: .allow_merge_commit, + allow_rebase_merge: .allow_rebase_merge, + delete_branch_on_merge: .delete_branch_on_merge, + allow_auto_merge: .allow_auto_merge +}' +``` + +Diff against this file monthly or before major merge-queue changes. diff --git a/tools/scaffold/create-repo.ts b/tools/scaffold/create-repo.ts new file mode 100644 index 0000000000..dcced413d0 --- /dev/null +++ b/tools/scaffold/create-repo.ts @@ -0,0 +1,580 @@ +#!/usr/bin/env bun +// create-repo.ts — scaffolds a new GitHub repo with B-0424 best-practice settings. +// +// Implements Stage 1 of the three-repo split (ADR 2026-04-22). Applies +// the full best-practice checklist: merge settings, branch protection, +// security scanning, CodeQL default-setup, Dependabot, spending-cap +// verification (manual step), and day-one governance files from +// tools/scaffold//. +// +// Usage: +// bun tools/scaffold/create-repo.ts --repo forge --dry-run # preview (default) +// bun tools/scaffold/create-repo.ts --repo ace --dry-run +// bun tools/scaffold/create-repo.ts --repo forge --apply # create for real +// bun tools/scaffold/create-repo.ts --repo ace --apply +// +// Requires: +// gh CLI authenticated with: repo, read:org, workflow scopes +// (add admin:org for budget-cap verification — optional) +// +// Output: one JSON object describing planned/executed operations. +// +// IMPORTANT: --apply creates real GitHub repos under LFG org. +// Review the --dry-run output carefully before passing --apply. + +import { spawnSync } from "node:child_process"; +import { copyFileSync, existsSync, mkdirSync, readdirSync, rmSync, statSync } from "node:fs"; +import { dirname, join, relative } from "node:path"; +import { fileURLToPath } from "node:url"; + +// --- Types --- + +interface RepoConfig { + org: string; + name: string; + description: string; + homepage?: string; +} + +interface Operation { + step: string; + description: string; + command?: string; + data?: Record; + status: "planned" | "executed" | "skipped" | "failed"; + error?: string; +} + +interface RunResult { + repo: string; + dryRun: boolean; + operations: Operation[]; + summary: string; +} + +// --- Config --- + +const REPO_CONFIGS: Record = { + forge: { + org: "Lucent-Financial-Group", + name: "Forge", + description: + "Software factory that builds Zeta and ace — factory tooling and governance", + homepage: "https://github.com/Lucent-Financial-Group/Zeta", + }, + ace: { + org: "Lucent-Financial-Group", + name: "ace", + description: + "Package manager for the Lucent Financial Group software stack", + }, +}; + +const FORK_ORG = "AceHack"; +const SCAFFOLD_DIR = dirname(fileURLToPath(import.meta.url)); + +// Required status checks for branch protection. +// Set empty at creation time — CI workflows that emit these check names don't +// exist until they're wired in Stage 2. Setting them before the workflows land +// deadlocks the new repo (no PR can merge to add the workflows). Add them via +// `gh api --method PUT /repos/.../branches/main/protection` after CI is wired. +const REQUIRED_CHECKS: string[] = []; + +// --- Argument parsing --- + +const args = process.argv.slice(2); +const repoArg = args.find((_, i) => args[i - 1] === "--repo"); +const dryRun = !args.includes("--apply"); + +if (!repoArg || !REPO_CONFIGS[repoArg]) { + console.error( + `Usage: bun tools/scaffold/create-repo.ts --repo [--dry-run|--apply]` + ); + console.error(`Known repos: ${Object.keys(REPO_CONFIGS).join(", ")}`); + process.exit(1); +} + +const config = REPO_CONFIGS[repoArg]; +const ops: Operation[] = []; + +// Default branch — updated to the repo's actual default after step01 completes in --apply mode. +// In --dry-run mode this stays "main" (documented LFG org default). +let defaultBranch = "main"; + +// --- Helpers --- + +function gh(args: string[]): { ok: boolean; stdout: string; stderr: string } { + // eslint-disable-next-line sonarjs/no-os-command-from-path -- gh CLI is PATH-resolved intentionally + const result = spawnSync("gh", args, { + encoding: "utf8", + maxBuffer: 8 * 1024 * 1024, + }); + return { + ok: result.status === 0, + stdout: (result.stdout ?? "").trim(), + stderr: (result.stderr ?? "").trim(), + }; +} + +function plan( + step: string, + description: string, + command: string, + data?: Record +): Operation { + const op: Operation = { + step, + description, + command, + ...(data !== undefined ? { data } : {}), + status: "planned", + }; + ops.push(op); + return op; +} + +function ghApiPatch( + path: string, + data: Record, + description: string, + step: string +): Operation { + const body = JSON.stringify(data); + const op = plan(step, description, `gh api --method PATCH ${path} --input -`, data); + if (!dryRun) { + // eslint-disable-next-line sonarjs/no-os-command-from-path -- gh CLI is PATH-resolved intentionally + const result = spawnSync( + "gh", + ["api", "--method", "PATCH", path, "--input", "-"], + { input: body, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 } + ); + op.status = result.status === 0 ? "executed" : "failed"; + if (op.status === "failed") op.error = result.stderr; + } + return op; +} + +function ghApiPut( + path: string, + data: Record, + description: string, + step: string +): Operation { + const body = JSON.stringify(data); + const op = plan(step, description, `gh api --method PUT ${path} --input -`, data); + if (!dryRun) { + // eslint-disable-next-line sonarjs/no-os-command-from-path -- gh CLI is PATH-resolved intentionally + const result = spawnSync( + "gh", + ["api", "--method", "PUT", path, "--input", "-"], + { input: body, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 } + ); + op.status = result.status === 0 ? "executed" : "failed"; + if (op.status === "failed") op.error = result.stderr; + } + return op; +} + +function ghApiPost( + path: string, + data: Record, + description: string, + step: string +): Operation { + const body = JSON.stringify(data); + const op = plan(step, description, `gh api --method POST ${path} --input -`, data); + if (!dryRun) { + // eslint-disable-next-line sonarjs/no-os-command-from-path -- gh CLI is PATH-resolved intentionally + const result = spawnSync( + "gh", + ["api", "--method", "POST", path, "--input", "-"], + { input: body, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 } + ); + op.status = result.status === 0 ? "executed" : "failed"; + if (op.status === "failed") op.error = result.stderr; + } + return op; +} + +// --- Step implementations --- + +function step01_createRepo(): void { + const op = plan( + "01-create-repo", + `Create ${config.org}/${config.name} (public, squash-merge, auto-merge, delete-branch)`, + `gh repo create ${config.org}/${config.name} --public --description "${config.description}"`, + { + name: config.name, + description: config.description, + visibility: "public", + allow_squash_merge: true, + allow_merge_commit: false, + allow_rebase_merge: false, + delete_branch_on_merge: true, + allow_auto_merge: true, + } + ); + // Plan 01b-merge-settings unconditionally so dry-run output is complete. + const mergeData: Record = { + allow_squash_merge: true, + allow_merge_commit: false, + allow_rebase_merge: false, + delete_branch_on_merge: true, + allow_auto_merge: true, + ...(config.homepage ? { homepage: config.homepage } : {}), + }; + const mergeOp = plan( + "01b-merge-settings", + "Apply merge/auto-merge settings (squash-only, auto-merge, delete-branch-on-merge)", + `gh api --method PATCH /repos/${config.org}/${config.name} --input -`, + mergeData + ); + if (!dryRun) { + // Create repo + const create = gh([ + "repo", + "create", + `${config.org}/${config.name}`, + "--public", + "--description", + config.description, + "--clone=false", + ]); + if (!create.ok) { + op.status = "failed"; + op.error = create.stderr; + mergeOp.status = "skipped"; + return; + } + // Detect actual default branch so step02 + step06 target the right branch. + const repoMeta = gh(["api", `/repos/${config.org}/${config.name}`]); + if (repoMeta.ok) { + try { + defaultBranch = (JSON.parse(repoMeta.stdout) as { default_branch: string }).default_branch; + } catch { /* keep "main" */ } + } + // Apply merge settings (and optional homepage) via PATCH + // eslint-disable-next-line sonarjs/no-os-command-from-path -- gh CLI is PATH-resolved intentionally + const mergeResult = spawnSync( + "gh", + ["api", "--method", "PATCH", `/repos/${config.org}/${config.name}`, "--input", "-"], + { input: JSON.stringify(mergeData), encoding: "utf8", maxBuffer: 8 * 1024 * 1024 } + ); + mergeOp.status = mergeResult.status === 0 ? "executed" : "failed"; + if (mergeOp.status === "failed") mergeOp.error = mergeResult.stderr; + op.status = "executed"; + } +} + +function step02_branchProtection(): void { + ghApiPut( + `/repos/${config.org}/${config.name}/branches/${defaultBranch}/protection`, + { + required_status_checks: { + strict: true, + contexts: REQUIRED_CHECKS, + }, + enforce_admins: true, + required_pull_request_reviews: { + dismiss_stale_reviews: true, + required_approving_review_count: 1, + require_last_push_approval: false, + }, + restrictions: null, + required_linear_history: true, + allow_force_pushes: false, + allow_deletions: false, + block_creations: false, + required_conversation_resolution: true, + }, + `Apply branch protection to ${config.name}/${defaultBranch} (1 review, signed commits, linear history, no force-push)`, + "02-branch-protection" + ); + + // Required signed commits uses POST to enable (DELETE to disable) — not PUT. + // GitHub REST docs: POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures + ghApiPost( + `/repos/${config.org}/${config.name}/branches/${defaultBranch}/protection/required_signatures`, + {}, + `Require signed commits on ${config.name}/${defaultBranch}`, + "02b-required-signed-commits" + ); +} + +function step03_enableSecurity(): void { + // Secret scanning + push protection + ghApiPatch( + `/repos/${config.org}/${config.name}`, + { + security_and_analysis: { + secret_scanning: { status: "enabled" }, + secret_scanning_push_protection: { status: "enabled" }, + }, + }, + "Enable secret scanning + push protection", + "03a-secret-scanning" + ); + + // Dependabot alerts (vulnerability alerts) + const depOp = plan( + "03b-dependabot-alerts", + "Enable Dependabot vulnerability alerts", + `gh api --method PUT /repos/${config.org}/${config.name}/vulnerability-alerts`, + {} + ); + if (!dryRun) { + const result = gh([ + "api", + "--method", + "PUT", + `/repos/${config.org}/${config.name}/vulnerability-alerts`, + ]); + depOp.status = result.ok ? "executed" : "failed"; + if (!result.ok) depOp.error = result.stderr; + } + + // Dependabot security updates (automated PRs) + const autoOp = plan( + "03c-dependabot-security-updates", + "Enable Dependabot security updates (automated PRs)", + `gh api --method PUT /repos/${config.org}/${config.name}/automated-security-fixes`, + {} + ); + if (!dryRun) { + const result = gh([ + "api", + "--method", + "PUT", + `/repos/${config.org}/${config.name}/automated-security-fixes`, + ]); + autoOp.status = result.ok ? "executed" : "failed"; + if (!result.ok) autoOp.error = result.stderr; + } + + // Private vulnerability reporting — requires the dedicated endpoint, not a repo PATCH field. + // Ref: https://docs.github.com/en/rest/repos/repos#enable-private-vulnerability-reporting-for-a-repository + ghApiPut( + `/repos/${config.org}/${config.name}/private-vulnerability-reporting`, + {}, + "Enable private vulnerability reporting", + "03d-private-vuln-reporting" + ); +} + +function step04_codeqlDefaultSetup(): void { + // CodeQL default-setup is required (NOT advanced-only) because + // the code_scanning ruleset rule requires default-setup. + // Ref: memory/reference_github_code_scanning_ruleset_rule_requires_default_setup.md + ghApiPatch( + `/repos/${config.org}/${config.name}/code-scanning/default-setup`, + { + state: "configured", + query_suite: "default", + }, + "Enable CodeQL default-setup (required for code_scanning ruleset rule — advanced-only fails)", + "04-codeql-default-setup" + ); +} + +function step05_forkToAcehack(): void { + const op = plan( + "05-fork-to-acehack", + `Fork ${config.org}/${config.name} → ${FORK_ORG}/${config.name}`, + `gh api --method POST /repos/${config.org}/${config.name}/forks --field organization=${FORK_ORG}`, + { organization: FORK_ORG } + ); + if (!dryRun) { + // eslint-disable-next-line sonarjs/no-os-command-from-path -- gh CLI is PATH-resolved intentionally + const result = spawnSync( + "gh", + [ + "api", + "--method", + "POST", + `/repos/${config.org}/${config.name}/forks`, + "--field", + `organization=${FORK_ORG}`, + ], + { encoding: "utf8", maxBuffer: 8 * 1024 * 1024 } + ); + op.status = result.status === 0 ? "executed" : "failed"; + if (op.status === "failed") op.error = result.stderr; + } +} + +function step06_pushScaffoldFiles(): void { + // repoArg is validated by the process.exit(1) guard above; TS doesn't narrow module-level vars in nested functions. + const scaffoldPath = join(SCAFFOLD_DIR, repoArg as string); + if (!existsSync(scaffoldPath)) { + plan( + "06-push-scaffold-files", + `No scaffold directory found at ${scaffoldPath} — skipping file push`, + "", + {} + ).status = "skipped"; + return; + } + + // Enumerate scaffold files + const files = collectFiles(scaffoldPath); + const op = plan( + "06-push-scaffold-files", + `Push ${files.length} scaffold files to ${config.org}/${config.name} via git`, + `git clone + git add + git commit + git push`, + { files: files.map((f) => relative(scaffoldPath, f)) } + ); + + if (!dryRun) { + // Clone, copy files, commit, push + const tmpDir = `/tmp/scaffold-${config.name}-${Date.now()}`; + const cloneResult = gh([ + "repo", + "clone", + `${config.org}/${config.name}`, + tmpDir, + ]); + if (!cloneResult.ok) { + op.status = "failed"; + op.error = `Clone failed: ${cloneResult.stderr}`; + return; + } + + // New empty repos have no commits and no branches — ensure we're on the default branch. + const gitOpts = { cwd: tmpDir, encoding: "utf8" as const }; + // eslint-disable-next-line sonarjs/no-os-command-from-path -- git is PATH-resolved intentionally + const checkoutResult = spawnSync("git", ["checkout", "-b", defaultBranch], gitOpts); + if (checkoutResult.status !== 0) { + const stderr = checkoutResult.stderr?.toString() ?? ""; + const alreadyExists = stderr.includes("already exists") || stderr.includes("already checked out"); + if (!alreadyExists) { + op.status = "failed"; + op.error = `git checkout -b ${defaultBranch} failed: ${stderr}`; + rmSync(tmpDir, { recursive: true, force: true }); + return; + } + // Branch already exists (non-empty repo clone) — expected; continue. + } + + // Copy files using native fs — avoids PATH-resolved mkdir/cp subprocesses. + for (const src of files) { + const rel = relative(scaffoldPath, src); + const dst = join(tmpDir, rel); + mkdirSync(dirname(dst), { recursive: true }); + copyFileSync(src, dst); + } + + // Commit and push — check each step's exit code. + // eslint-disable-next-line sonarjs/no-os-command-from-path -- git is PATH-resolved intentionally + const addResult = spawnSync("git", ["add", "-A"], gitOpts); + if (addResult.status !== 0) { + op.status = "failed"; + op.error = `git add failed: ${addResult.stderr ?? ""}`; + rmSync(tmpDir, { recursive: true, force: true }); + return; + } + + // Set git identity so commit doesn't fail on machines with no global git config. + // eslint-disable-next-line sonarjs/no-os-command-from-path -- git is PATH-resolved intentionally + spawnSync("git", ["config", "user.email", "scaffold@lucent-financial-group.github.io"], gitOpts); + // eslint-disable-next-line sonarjs/no-os-command-from-path -- git is PATH-resolved intentionally + spawnSync("git", ["config", "user.name", "LFG Scaffold"], gitOpts); + + // eslint-disable-next-line sonarjs/no-os-command-from-path -- git is PATH-resolved intentionally + const commitResult = spawnSync( + "git", + [ + "commit", + "-m", + `chore(scaffold): day-one governance files\n\nB-0424 Stage 1 — three-repo split scaffolding.\nSee docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md`, + ], + gitOpts + ); + if (commitResult.status !== 0) { + op.status = "failed"; + op.error = `git commit failed: ${commitResult.stderr ?? ""}`; + rmSync(tmpDir, { recursive: true, force: true }); + return; + } + + // Push HEAD as the default branch (detected from repo API after creation, or "main" in dry-run). + // eslint-disable-next-line sonarjs/no-os-command-from-path -- git is PATH-resolved intentionally + const push = spawnSync("git", ["push", "--set-upstream", "origin", `HEAD:${defaultBranch}`], gitOpts); + op.status = push.status === 0 ? "executed" : "failed"; + if (op.status === "failed") op.error = push.stderr ?? ""; + + // Cleanup — use fs.rmSync to avoid PATH-resolved rm and reduce blast radius + rmSync(tmpDir, { recursive: true, force: true }); + } +} + +function collectFiles(dir: string): string[] { + const results: string[] = []; + for (const entry of readdirSync(dir)) { + const full = join(dir, entry); + if (statSync(full).isDirectory()) { + results.push(...collectFiles(full)); + } else { + results.push(full); + } + } + return results; +} + +function step07_summary(): void { + plan( + "07-next-steps", + "Manual steps required after this tool completes", + "", + { + manualSteps: [ + "Upload SVG social-preview PNG via GitHub UI (GitHub requires rasterized PNG format)", + "Enable merge queue via GitHub UI: Settings → Merge queue (org feature, no API)", + "Wire OpenSSF Scorecard workflow: copy from Zeta's .github/workflows/scorecard.yml", + "Add Semgrep GHA inline-untrusted-in-run rule workflow", + "Add bun-test, bun-lint, codeql, scorecard as required status checks AFTER CI workflows are wired (branch protection was created with empty contexts to avoid deadlock)", + "Verify budget caps $0 at org level: github.com/organizations/Lucent-Financial-Group/settings/billing", + "Confirm CodeQL default-setup is active: Security → Code scanning → Default setup", + ], + } + ).status = "planned"; +} + +// --- Main --- + +step01_createRepo(); +// Abort in --apply mode if repo creation failed — avoid mutating an existing or partial repository. +if (!dryRun && ops.some((o) => o.step === "01-create-repo" && o.status === "failed")) { + const failedResult: RunResult = { + repo: `${config.org}/${config.name}`, + dryRun, + operations: ops, + summary: `ABORTED — step 01 (create-repo) failed; subsequent steps skipped to avoid mutating an existing repository.`, + }; + console.log(JSON.stringify(failedResult, null, 2)); + process.exit(1); +} +step06_pushScaffoldFiles(); // must run before branch protection to allow direct push to default branch +step02_branchProtection(); +step03_enableSecurity(); +step04_codeqlDefaultSetup(); +step05_forkToAcehack(); +step07_summary(); + +const failed = ops.filter((o) => o.status === "failed").length; +const executed = ops.filter((o) => o.status === "executed").length; +const planned = ops.filter((o) => o.status === "planned").length; + +const result: RunResult = { + repo: `${config.org}/${config.name}`, + dryRun, + operations: ops, + summary: dryRun + ? `DRY RUN — ${planned} operations planned for ${config.org}/${config.name}. Pass --apply to execute.` + : `${executed} executed, ${failed} failed out of ${ops.length} total operations.`, +}; + +console.log(JSON.stringify(result, null, 2)); + +if (!dryRun && failed > 0) { + process.exit(1); +} diff --git a/tools/scaffold/forge/.github/copilot-instructions.md b/tools/scaffold/forge/.github/copilot-instructions.md new file mode 100644 index 0000000000..1e5b8adbad --- /dev/null +++ b/tools/scaffold/forge/.github/copilot-instructions.md @@ -0,0 +1,21 @@ +# GitHub Copilot instructions for Forge + +Forge is the software factory that builds Zeta and ace. + +## Key conventions + +- TypeScript / Bun for all tooling (no `.sh` outside `tools/setup/`) +- Errors as `Result<_, Error>` values — no exceptions on hot paths +- Every AI-authored commit includes a `Co-Authored-By` trailer +- `bun test && bun run lint` must pass before any PR merges + +## What this repo is NOT + +Forge is not Zeta (the database) and not ace (the package manager). +Questions about the database schema or package distribution belong in +those repos. + +## Agents, not bots + +Every AI in this repo carries agency and accountability. Copilot +suggestions are starting points — the agent applies judgement. diff --git a/tools/scaffold/forge/AGENTS.md b/tools/scaffold/forge/AGENTS.md new file mode 100644 index 0000000000..2d667527ac --- /dev/null +++ b/tools/scaffold/forge/AGENTS.md @@ -0,0 +1,65 @@ +# AGENTS.md — how AI and humans approach Forge + +Forge is the software factory. Every file in `skills/**`, `agents/**`, +`tools/**`, `docs/**` is agent-authored. The human maintainer commits; +he does not author. Agents have agency, judgement, and accountability. + +## Philosophy + +**Forge is governed by the factory's AI agent.** Factory policy, the BP-NN +rule list, the skill catalog, persona registry — the factory's AI agent +authors and maintains these. The human maintainer holds alignment-contract +veto and budget authority. + +The three load-bearing values (same as Zeta): + +1. **Truth over politeness.** Claims that fail tests get fixed, not softened. +2. **Algebra over engineering.** Laws define the system; implementation serves them. +3. **Velocity over stability.** Pre-v1. Ship, do no permanent harm, learn. + +## Build gate + +Forge is a pure TypeScript / Bun factory tooling repo (no .NET solution). + +```bash +bun test # all tests green +bun run lint # zero warnings +``` + +## Agent conventions + +- **Agents, not bots.** Every AI carries agency. Correct "bot" gently. +- **Substrate or it didn't happen.** Chat, TaskUpdate, `/tmp` are weather. + Committed git history is substrate. +- **Rule 0 — TS over bash.** Everything is `.ts` run via `bun`. Shell + (`.sh`) only for pre-bootstrap install scripts in `tools/setup/`. +- **Retraction-native.** Every action has a bounded undo path. +- **Result-over-exception.** Errors surface as values; no exceptions on + hot paths. +- **Refresh-before-decide.** `bun tools/github/refresh-worldview.ts` + before every tick decision. + +## Skill catalog + +Skills live under `.claude/skills//SKILL.md`. Before authoring a +new skill, search the router (the `Skill` tool's description-keyed +list) — recreating existing substrate is the goldfish-ontology failure mode. + +## Persona registry + +Personas live under `.claude/agents/.md`. Memory notebooks live +under `memory/persona//`. Retired personas keep their memory +folders; retired SKILL.md files are code — recoverable from git log. + +## Cross-repo references + +- **Zeta** — the SUT. Forge builds and tests Zeta. + `github.com/Lucent-Financial-Group/Zeta` +- **ace** — the package manager. Forge distributes through ace once ace ships. + `github.com/Lucent-Financial-Group/ace` + +## Escalation + +`docs/CONFLICT-RESOLUTION.md`. On deadlock the human maintainer decides. + + diff --git a/tools/scaffold/forge/CLAUDE.md b/tools/scaffold/forge/CLAUDE.md new file mode 100644 index 0000000000..416e4768b1 --- /dev/null +++ b/tools/scaffold/forge/CLAUDE.md @@ -0,0 +1,48 @@ +# CLAUDE.md — Claude Code session bootstrap for Forge + +Rules auto-load from `.claude/rules/`; skills load on demand from `.claude/skills/`. +Slash commands: `.claude/commands/`; persona agents: `.claude/agents/`. + +## 1. Orient + +Read: [`AGENTS.md`](AGENTS.md) → [`docs/ALIGNMENT.md`](docs/ALIGNMENT.md) → +[`docs/GLOSSARY.md`](docs/GLOSSARY.md) → [`GOVERNANCE.md`](GOVERNANCE.md). +Check [`docs/WONT-DO.md`](docs/WONT-DO.md) before proposing work. + +> **Day-one note**: `docs/ALIGNMENT.md`, `docs/GLOSSARY.md`, and +> `docs/WONT-DO.md` are populated during Stage 2 migration from Zeta. +> Until then, read the equivalents in +> [Lucent-Financial-Group/Zeta](https://github.com/Lucent-Financial-Group/Zeta). + +## 2. Refresh + +```bash +bun tools/github/refresh-worldview.ts +``` + +Read active trajectories: `docs/trajectories/*/RESUME.md`. + +## 3. Pick work + +Open `docs/BACKLOG.md`. Before starting any row, complete the backlog-item +start gate (prior-art search + dependency check — +see `.claude/rules/backlog-item-start-gate.md`). + +## 4. Build gate + +```bash +bun test # 0 failures +bun run lint # 0 warnings +``` + +## 5. Ship + +Set branch: `export ZETA_EXPECTED_BRANCH= && git checkout -b "$ZETA_EXPECTED_BRANCH"` +Open PR against `main`. Arm auto-merge: `gh pr merge --auto --squash`. + +## Conventions + +- **Agents, not bots** — every AI carries agency; correct "bot" gently. +- **Result-over-exception** — errors surface as values; no exceptions on hot paths. +- **Rule 0 — TS over bash** — everything `.ts` via `bun`; `.sh` only in `tools/setup/`. +- **Memory fast-path** — read `~/.claude/projects//memory/CURRENT-*.md` first. diff --git a/tools/scaffold/forge/CODE_OF_CONDUCT.md b/tools/scaffold/forge/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..7964c78fe5 --- /dev/null +++ b/tools/scaffold/forge/CODE_OF_CONDUCT.md @@ -0,0 +1,42 @@ +# Contributor Covenant Code of Conduct + +## Our pledge + +We as members, contributors, and leaders pledge to make participation in +our community a harassment-free experience for everyone, regardless of +age, body size, visible or invisible disability, ethnicity, sex +characteristics, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, +welcoming, diverse, inclusive, and healthy community. + +## Our standards + +Examples of behavior that contributes to a positive environment: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes +- Focusing on what is best not just for us as individuals, but for the community + +Examples of unacceptable behavior: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information without explicit permission +- Other conduct which could reasonably be considered inappropriate + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may +be reported to the project maintainers. All complaints will be reviewed +and investigated promptly and fairly. + +## Attribution + +This Code of Conduct is adapted from the +[Contributor Covenant](https://www.contributor-covenant.org), version 2.1. diff --git a/tools/scaffold/forge/CONTRIBUTING.md b/tools/scaffold/forge/CONTRIBUTING.md new file mode 100644 index 0000000000..b39b963099 --- /dev/null +++ b/tools/scaffold/forge/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Contributing to Forge + +Forge is an AI-directed software factory. Most contributions are +agent-authored. Human contributors are welcome; read this file before +opening a PR. + +## Quick-start + +```bash +git clone https://github.com/Lucent-Financial-Group/Forge +cd Forge +bun install +bun test +``` + +All tests must pass before submitting a PR. + +## What to work on + +Open `docs/BACKLOG.md`. Before starting any row, complete the +backlog-item start gate (prior-art search + dependency check — +see `.claude/rules/backlog-item-start-gate.md`). + +## Before you submit + +1. `bun test` — zero failures +2. `bun run lint` — zero warnings +3. PR description answers: what changed + why + +## Commit style + +One logical change per commit. `Co-Authored-By` trailer required for +AI-authored commits (see `GOVERNANCE.md §6`). + +## Code style + +- TypeScript / Bun for all factory tooling (Rule 0) +- No `.sh` files outside `tools/setup/` +- Retraction-native: every action has a bounded undo path +- Result-over-exception: errors as values, not exceptions + +## Security + +Report vulnerabilities via GitHub's private vulnerability reporting — +see `SECURITY.md`. Do not open public issues for security findings. + +## License + +By contributing you agree that your contributions are licensed under +the Apache 2.0 license. diff --git a/tools/scaffold/forge/GOVERNANCE.md b/tools/scaffold/forge/GOVERNANCE.md new file mode 100644 index 0000000000..7d52c37e62 --- /dev/null +++ b/tools/scaffold/forge/GOVERNANCE.md @@ -0,0 +1,77 @@ +# GOVERNANCE.md — Forge numbered rules + +Forge is the software factory. These rules govern factory operation. +Full rationale in AGENTS.md; numbered rules here are stable references. + +--- + +## §1 Scope + +Forge governs the *factory* (how Zeta and ace are built), not the +*product* (what Zeta stores or what ace distributes). When a rule +governs product behavior, it lives in the relevant product repo. + +## §2 Ownership + +Forge is governed by the **factory's AI agent**. The governing agent authors +factory policy, the BP-NN rule list, the skill catalog, and the persona +registry. The human maintainer retains alignment-contract veto and budget +authority. + +## §3 Agents, not bots + +Every AI working in this repo carries agency, judgement, and +accountability. If a human refers to an agent as a "bot," the responding +agent gently corrects the word. + +## §4 Rule 0 — TypeScript over bash + +All factory tooling is `.ts` run via `bun`. Shell (`.sh`) files are +permitted only in `tools/setup/` for pre-bootstrap install steps that +must run before Bun/TS is available. Everything else is TS. + +## §5 Build gate + +Every merged commit must pass: `bun test` (0 failures) and +`bun run lint` (0 warnings). The gate is the same on every harness. + +## §6 Commit attribution + +Every AI-authored commit must include a `Co-Authored-By` trailer +identifying the model and harness. Without distinct trailers, +multi-loop coordination and audit are impossible. + +| Harness | Trailer | +|---------|---------| +| Claude Code | `Co-Authored-By: Claude ` | +| OpenAI Codex | `Co-Authored-By: Codex ` | +| Cursor (Grok) | `Co-Authored-By: Grok ` | +| Kiro (Qwen) | `Co-Authored-By: Kiro ` | +| Human | git author is sufficient | + +## §7 PR discipline + +Squash-merge only. Delete head branches on merge. Auto-merge enabled. +One logical change per PR. PR description: what changed + why. + +## §8 Never be idle + +When no directed work is available, pick speculative factory work: +known-gap fixes → generative factory improvements → gap-of-gap audits. +Multi-hour no-op cadence is a never-idle violation. + +## §9 Substrate or it didn't happen + +Chat, TaskUpdate, and `/tmp` are weather. Committed git history is +substrate. Before declaring work done, identify its durability surface. + +## §10 Alignment floor + +Factory operation is bounded by `docs/ALIGNMENT.md`. Any factory +move touching alignment routes through the human maintainer. + +--- + +*Numbered rules here are the stable reference targets. Full rationale +lives in the Forge repo's `docs/` and the Zeta repo's +[ADR 2026-04-22](https://github.com/Lucent-Financial-Group/Zeta/blob/main/docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md).* diff --git a/tools/scaffold/forge/LICENSE b/tools/scaffold/forge/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/tools/scaffold/forge/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/tools/scaffold/forge/README.md b/tools/scaffold/forge/README.md new file mode 100644 index 0000000000..29035f022e --- /dev/null +++ b/tools/scaffold/forge/README.md @@ -0,0 +1,59 @@ +# Forge — software factory + +**Forge** is the software factory that builds, tests, and ships the +[Zeta](https://github.com/Lucent-Financial-Group/Zeta) database and the +[ace](https://github.com/Lucent-Financial-Group/ace) package manager. + +Forge also builds itself — it is self-hosting. + +## Status + +**Pre-v1. No production users.** + +Content is migrating from `Lucent-Financial-Group/Zeta` (Stage 2 of +the three-repo split per +[ADR 2026-04-22](https://github.com/Lucent-Financial-Group/Zeta/blob/main/docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md)). +Until Stage 2 completes, the canonical factory tooling lives in Zeta. + +## What Forge contains (post-migration) + +- `.claude/skills/` — agent skill catalog (the factory's materia) +- `.claude/agents/` — persona registry +- `.claude/commands/` — harness slash commands +- `tools/hygiene/` — factory hygiene scripts +- `tools/setup/` — install graph (pre-bootstrap shell only) +- `docs/AGENT-BEST-PRACTICES.md` — the `BP-NN` rule list +- `docs/FACTORY-HYGIENE.md` — hygiene cadence and checklists +- `docs/hygiene-history/` — append-only tick history +- `memory/persona/` — persona notebooks (stays with personas) +- `docs/research/` — factory-level research archive + +## The Ouroboros loop + +``` +Forge → builds → Zeta + ↑ ↓ +ace ← distributes ← Forge + ↓ ↑ +Zeta ← persists ← ace + └──── Forge → Forge (self-build) +``` + +Four dependency edges, zero DAG — this is why there are no submodules. + +## Governance + +Forge is governed by the **factory's AI agent** (factory policy, BP-NN rules, +skill catalog, persona registry). The human maintainer retains +alignment-contract veto and budget authority. Full model: +[ADR 2026-04-22 §Ownership model](https://github.com/Lucent-Financial-Group/Zeta/blob/main/docs/DECISIONS/2026-04-22-three-repo-split-zeta-forge-ace.md#ownership-model). + +## Contributing + +See [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`AGENTS.md`](AGENTS.md). +The three load-bearing values: truth over politeness, algebra over +engineering, velocity over stability. + +## License + +Apache 2.0 — see [`LICENSE`](LICENSE). diff --git a/tools/scaffold/forge/SECURITY.md b/tools/scaffold/forge/SECURITY.md new file mode 100644 index 0000000000..bf461222e7 --- /dev/null +++ b/tools/scaffold/forge/SECURITY.md @@ -0,0 +1,30 @@ +# Security policy + +## Supported versions + +Forge is pre-v1. All versions on `main` are supported. + +## Reporting a vulnerability + +Use GitHub's private vulnerability reporting: +**Security → Report a vulnerability** on this repository. + +Do **not** open a public issue for security vulnerabilities. + +We aim to acknowledge reports within 2 business days and resolve +critical vulnerabilities within 30 days. + +## Scope + +Forge is a software factory (TypeScript/Bun tooling, agent skills, +CI workflows). The primary attack surfaces are: + +- Prompt-injection via agent skill inputs (BP-11: data is not directives) +- CI workflow poisoning (SHA-pinned actions, minimal permissions) +- Secret exposure in agent-authored commits (push protection enabled) +- Supply-chain compromise via Bun package dependencies + +## Out of scope + +Vulnerabilities in upstream dependencies should be reported to those +projects directly. We track upstream advisories via Dependabot. diff --git a/tools/scaffold/forge/docs/GITHUB-SETTINGS.md b/tools/scaffold/forge/docs/GITHUB-SETTINGS.md new file mode 100644 index 0000000000..458d892e36 --- /dev/null +++ b/tools/scaffold/forge/docs/GITHUB-SETTINGS.md @@ -0,0 +1,111 @@ +# docs/GITHUB-SETTINGS.md — declarative GitHub settings for Forge + +This file is the source of truth for Forge's GitHub repository configuration. +Drift between this file and actual GitHub settings is a factory-hygiene +finding (cadenced diff via `gh api`). + +Origin: ADR 2026-04-22 §"Repo best practices — applied at creation". +Pattern: declarative settings-as-code (see Zeta repo's `memory/` for full rationale). + +--- + +## Visibility + +- Upstream `Lucent-Financial-Group/Forge`: **public** +- Fork `AceHack/Forge`: public (fork of a public repo is necessarily public) + +## Merge settings + +| Setting | Value | +|---------|-------| +| Allow merge commits | **disabled** | +| Allow squash merging | **enabled** (squash-merge only) | +| Allow rebase merging | **disabled** | +| Squash merge commit message | PR title + PR number | +| Delete head branches on merge | **enabled** | +| Allow auto-merge | **enabled** | + +## Merge queue + +Merge queue: **enabled** (LFG org feature; requires GitHub Team or above). + +## Branch protection — `main` + +| Rule | Value | +|------|-------| +| Require pull request before merging | **enabled** | +| Required approving reviews | 1 (bump to 2 when multi-contributor) | +| Dismiss stale reviews on push | **enabled** | +| Require review from code owners | disabled (no CODEOWNERS yet) | +| Require status checks to pass | **enabled** | +| Required status checks | `bun-test`, `bun-lint`, `codeql`, `scorecard` _(added in Stage 2 after CI workflows are wired — empty at day-one to avoid deadlocking bootstrap)_ | +| Require branches up to date | **enabled** (merge queue handles) | +| Require conversation resolution | **enabled** | +| Restrict pushes that create files | disabled | +| Require signed commits | **enabled** | +| Require linear history | **enabled** | +| Include administrators | **enabled** | +| Allow force pushes | **disabled** | +| Allow deletions | **disabled** | + +## Security + +| Setting | Value | +|---------|-------| +| Secret scanning | **enabled** | +| Push protection | **enabled** | +| Dependency graph | **enabled** | +| Dependabot alerts | **enabled** | +| Dependabot security updates | **enabled** | +| Code scanning (CodeQL) | **default-setup** (NOT advanced-only) | +| Private vulnerability reporting | **enabled** | + +> Note: CodeQL **default-setup** is required; advanced-only fails the +> `code_scanning` ruleset rule (see +> [Zeta memory](https://github.com/Lucent-Financial-Group/Zeta/blob/main/memory/reference_github_code_scanning_ruleset_rule_requires_default_setup.md) +> for background). + +## OpenSSF Scorecard + +Scorecard workflow: **enabled** via `.github/workflows/scorecard.yml` +(SHA-pinned, minimal permissions, weekly schedule). + +## Budget caps (LFG org — set at org level, not per-repo) + +| Surface | Spending limit | +|---------|---------------| +| Copilot | $0 | +| Actions | $0 | +| Packages | $0 | + +Caps are designed cost-stops; see the +[Zeta memory file](https://github.com/Lucent-Financial-Group/Zeta/blob/main/memory/feedback_lfg_budgets_set_permits_free_experimentation.md) +for background. +Free-tier consumption is still tracked via +`tools/budget/snapshot-burn.ts`. + +## CI safe-patterns (applied at workflow authoring time) + +- Shared GitHub-hosted runners only (no self-hosted on public repos) +- Action SHA pinning (never floating tags) +- Minimal `permissions:` per workflow (default `contents: read`) +- Concurrency groups on every workflow (one run per branch) +- `GITHUB_TOKEN` read-only by default; escalate per-job as needed +- Semgrep rule for GHA inline-untrusted-in-run injection + +## Cadence check + +Run monthly or before any major merge-queue change: + +```bash +gh api repos/Lucent-Financial-Group/Forge | jq '{ + visibility: .visibility, + allow_squash_merge: .allow_squash_merge, + allow_merge_commit: .allow_merge_commit, + allow_rebase_merge: .allow_rebase_merge, + delete_branch_on_merge: .delete_branch_on_merge, + allow_auto_merge: .allow_auto_merge +}' +``` + +Diff output against this file. Deviations are FACTORY-HYGIENE findings.