fix: Remove YAML usage, standardize on JSON/TOML
- Delete 5 legacy .formula.yaml files (have .toml replacements) - Remove unused FileConfigYAML constant - Add TODO for beads config.yaml → config.json migration (bd-10wg) - Update docs to use JSON examples instead of yaml code blocks - Change plugin frontmatter from YAML to TOML in docs - Add .toml to code file detection in branch_check.go 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
cc3622117e
commit
f75eeb4da8
@@ -323,7 +323,7 @@ needs = ["health-scan"]
|
|||||||
description = """
|
description = """
|
||||||
Execute registered plugins.
|
Execute registered plugins.
|
||||||
|
|
||||||
Scan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with YAML frontmatter defining its gate (when to run) and instructions (what to do).
|
Scan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with TOML frontmatter defining its gate (when to run) and instructions (what to do).
|
||||||
|
|
||||||
See docs/deacon-plugins.md for full documentation.
|
See docs/deacon-plugins.md for full documentation.
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
formula: rule-of-five
|
|
||||||
type: expansion
|
|
||||||
description: >
|
|
||||||
Jeffrey Emanuel's discovery: LLM agents produce best work through 4-5
|
|
||||||
iterative refinements. Breadth-first exploration, then editorial passes.
|
|
||||||
version: 1
|
|
||||||
template:
|
|
||||||
- id: "{target}.draft"
|
|
||||||
description: >
|
|
||||||
Initial attempt at: {target.description}. Don't aim for perfection.
|
|
||||||
Get the shape right. Breadth over depth.
|
|
||||||
|
|
||||||
- id: "{target}.refine-1"
|
|
||||||
description: >
|
|
||||||
First refinement pass. Focus: CORRECTNESS. Fix errors, bugs, mistakes.
|
|
||||||
Is the logic sound?
|
|
||||||
needs: ["{target}.draft"]
|
|
||||||
|
|
||||||
- id: "{target}.refine-2"
|
|
||||||
description: >
|
|
||||||
Second refinement pass. Focus: CLARITY. Can someone else understand
|
|
||||||
this? Simplify. Remove jargon.
|
|
||||||
needs: ["{target}.refine-1"]
|
|
||||||
|
|
||||||
- id: "{target}.refine-3"
|
|
||||||
description: >
|
|
||||||
Third refinement pass. Focus: EDGE CASES. What could go wrong?
|
|
||||||
What's missing? Handle the unusual.
|
|
||||||
needs: ["{target}.refine-2"]
|
|
||||||
|
|
||||||
- id: "{target}.refine-4"
|
|
||||||
description: >
|
|
||||||
Final polish. Focus: EXCELLENCE. This is the last pass. Make it shine.
|
|
||||||
Is this something you'd be proud to ship?
|
|
||||||
needs: ["{target}.refine-3"]
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
formula: security-audit
|
|
||||||
type: aspect
|
|
||||||
description: >
|
|
||||||
Cross-cutting security concern. Applies security scanning before and
|
|
||||||
after implementation steps.
|
|
||||||
version: 1
|
|
||||||
pointcuts:
|
|
||||||
- glob: "*.implement"
|
|
||||||
- glob: "*.submit"
|
|
||||||
advice:
|
|
||||||
around:
|
|
||||||
before:
|
|
||||||
- id: security-prescan
|
|
||||||
description: >
|
|
||||||
Pre-implementation security check. Review for secrets/credentials
|
|
||||||
in scope. Check dependencies for known vulnerabilities.
|
|
||||||
args:
|
|
||||||
target: "{step.id}"
|
|
||||||
after:
|
|
||||||
- id: security-postscan
|
|
||||||
description: >
|
|
||||||
Post-implementation security scan. Scan new code for vulnerabilities
|
|
||||||
(SAST). Check for hardcoded secrets. Review for OWASP Top 10 issues.
|
|
||||||
args:
|
|
||||||
target: "{step.id}"
|
|
||||||
output:
|
|
||||||
approved: boolean
|
|
||||||
findings: list
|
|
||||||
- gate:
|
|
||||||
condition: "security-postscan.output.approved == true"
|
|
||||||
message: Security approval required before proceeding
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
formula: shiny-enterprise
|
|
||||||
extends: shiny
|
|
||||||
description: >
|
|
||||||
Enterprise-grade engineering workflow. Shiny + Rule of Five + Security +
|
|
||||||
Performance Testing + Review Loop.
|
|
||||||
version: 1
|
|
||||||
compose:
|
|
||||||
- expand:
|
|
||||||
target: implement
|
|
||||||
with: rule-of-five
|
|
||||||
|
|
||||||
- aspect:
|
|
||||||
pointcut: "implement.*"
|
|
||||||
with: security-audit
|
|
||||||
|
|
||||||
- gate:
|
|
||||||
before: submit
|
|
||||||
condition: "security-postscan.approved == true"
|
|
||||||
message: Cannot submit without security approval
|
|
||||||
|
|
||||||
- branch:
|
|
||||||
from: implement.refine-4
|
|
||||||
steps:
|
|
||||||
- id: perf-test
|
|
||||||
description: Run performance benchmarks
|
|
||||||
- id: load-test
|
|
||||||
description: Run load/stress tests
|
|
||||||
- id: chaos-test
|
|
||||||
description: Run chaos engineering tests
|
|
||||||
join: review
|
|
||||||
|
|
||||||
- loop:
|
|
||||||
step: review
|
|
||||||
until: "review.output.approved == true"
|
|
||||||
max: 3
|
|
||||||
on-max: escalate
|
|
||||||
|
|
||||||
- advice:
|
|
||||||
target: "*"
|
|
||||||
before:
|
|
||||||
id: log-start
|
|
||||||
description: "Log: Starting {step.id}"
|
|
||||||
after:
|
|
||||||
id: log-end
|
|
||||||
description: "Log: Completed {step.id}"
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
formula: shiny
|
|
||||||
description: >
|
|
||||||
Engineer in a Box - the canonical right way. Design before you code.
|
|
||||||
Review before you ship. Test before you submit.
|
|
||||||
version: 1
|
|
||||||
vars:
|
|
||||||
feature: "{{feature}}"
|
|
||||||
assignee: "{{assignee}}"
|
|
||||||
steps:
|
|
||||||
- id: design
|
|
||||||
description: >
|
|
||||||
Think carefully about architecture before writing code. Consider:
|
|
||||||
How does this fit into the existing system? What are the edge cases?
|
|
||||||
What could go wrong? Is there a simpler approach?
|
|
||||||
|
|
||||||
- id: implement
|
|
||||||
description: >
|
|
||||||
Write the code for {{feature}}. Follow the design. Keep it simple.
|
|
||||||
Don't gold-plate.
|
|
||||||
needs: [design]
|
|
||||||
|
|
||||||
- id: review
|
|
||||||
description: >
|
|
||||||
Review the implementation. Check for: Does it match the design?
|
|
||||||
Are there obvious bugs? Is it readable and maintainable?
|
|
||||||
Are there security concerns?
|
|
||||||
needs: [implement]
|
|
||||||
|
|
||||||
- id: test
|
|
||||||
description: >
|
|
||||||
Write and run tests. Unit tests for new code, integration tests
|
|
||||||
if needed, run the full test suite, fix any regressions.
|
|
||||||
needs: [review]
|
|
||||||
|
|
||||||
- id: submit
|
|
||||||
description: >
|
|
||||||
Submit for merge. Final check: git status, git diff. Commit with
|
|
||||||
clear message. Push and create PR.
|
|
||||||
needs: [test]
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
# Towers of Hanoi Formula
|
|
||||||
#
|
|
||||||
# Demonstrates that molecule algebra solves the "million step workflow" problem.
|
|
||||||
# LLMs fail on long sequences because errors accumulate (99.9%^1000 ≈ 37% success).
|
|
||||||
# MAKER used voting to reduce error. We use mechanical structure instead.
|
|
||||||
#
|
|
||||||
# Key insight: The move sequence is deterministic. Only execution needs AI.
|
|
||||||
# And each step is trivial: "move disk X from peg Y to peg Z".
|
|
||||||
#
|
|
||||||
# For n disks: 2^n - 1 moves
|
|
||||||
# 20 disks = 1,048,575 moves (the "million step" problem)
|
|
||||||
#
|
|
||||||
# Currently hardcoded for 3 disks (7 moves) as proof of concept.
|
|
||||||
# For million-step version, need to implement range expansion in cook.
|
|
||||||
|
|
||||||
formula: towers-of-hanoi
|
|
||||||
version: 2
|
|
||||||
description: |
|
|
||||||
AGENT EXECUTION PROTOCOL - Towers of Hanoi
|
|
||||||
|
|
||||||
PURPOSE: This is a durability proof, not computation. Steps are pre-computed.
|
|
||||||
Your job is to execute them mechanically, proving crash-recovery at scale.
|
|
||||||
|
|
||||||
EXECUTION LOOP:
|
|
||||||
1. Find current state: bd mol current <mol-id>
|
|
||||||
2. Find the next ready (unblocked) step
|
|
||||||
3. Close it: bd close <step-id>
|
|
||||||
4. Repeat until no ready steps remain
|
|
||||||
|
|
||||||
ON RESUME (after crash/restart/handoff):
|
|
||||||
- Same as fresh start. The molecule IS the state.
|
|
||||||
- Query `bd mol current <mol-id>`, continue from there.
|
|
||||||
- No memory of previous session needed.
|
|
||||||
|
|
||||||
DO:
|
|
||||||
- Close steps as fast as possible (they're trivial mechanical moves)
|
|
||||||
- Use `gt handoff` when context fills (proactive cycling)
|
|
||||||
- Trust the pre-computed solution - every move is already correct
|
|
||||||
|
|
||||||
DO NOT:
|
|
||||||
- Try to solve Hanoi yourself - moves are already computed
|
|
||||||
- Mark steps in_progress - just close them directly
|
|
||||||
- Ask for permission - this is GUPP territory, just execute
|
|
||||||
- Stop for human input - run autonomously until complete
|
|
||||||
|
|
||||||
MONITORING:
|
|
||||||
- Progress: Count closed children of the molecule
|
|
||||||
- For mega-molecules: Use convoy dashboard when available
|
|
||||||
- Completion: All steps closed = molecule complete
|
|
||||||
|
|
||||||
This proves Gas Town can execute arbitrarily long workflows with
|
|
||||||
nondeterministic idempotence - different sessions, same outcome.
|
|
||||||
|
|
||||||
vars:
|
|
||||||
source_peg:
|
|
||||||
default: "A"
|
|
||||||
description: "Starting peg"
|
|
||||||
target_peg:
|
|
||||||
default: "C"
|
|
||||||
description: "Target peg"
|
|
||||||
auxiliary_peg:
|
|
||||||
default: "B"
|
|
||||||
description: "Helper peg"
|
|
||||||
|
|
||||||
# 3-disk solution: 7 moves (2^3 - 1)
|
|
||||||
steps:
|
|
||||||
- id: setup
|
|
||||||
title: "Verify initial state"
|
|
||||||
description: "All 3 disks stacked on peg A. Largest on bottom."
|
|
||||||
|
|
||||||
- id: move-1
|
|
||||||
title: "Move disk 1: A → C"
|
|
||||||
description: "Move the smallest disk from peg A to peg C."
|
|
||||||
needs: [setup]
|
|
||||||
|
|
||||||
- id: move-2
|
|
||||||
title: "Move disk 2: A → B"
|
|
||||||
description: "Move disk 2 from peg A to peg B."
|
|
||||||
needs: [move-1]
|
|
||||||
|
|
||||||
- id: move-3
|
|
||||||
title: "Move disk 1: C → B"
|
|
||||||
description: "Move disk 1 from peg C to peg B."
|
|
||||||
needs: [move-2]
|
|
||||||
|
|
||||||
- id: move-4
|
|
||||||
title: "Move disk 3: A → C"
|
|
||||||
description: "Move the largest disk from peg A to peg C."
|
|
||||||
needs: [move-3]
|
|
||||||
|
|
||||||
- id: move-5
|
|
||||||
title: "Move disk 1: B → A"
|
|
||||||
description: "Move disk 1 from peg B to peg A."
|
|
||||||
needs: [move-4]
|
|
||||||
|
|
||||||
- id: move-6
|
|
||||||
title: "Move disk 2: B → C"
|
|
||||||
description: "Move disk 2 from peg B to peg C."
|
|
||||||
needs: [move-5]
|
|
||||||
|
|
||||||
- id: move-7
|
|
||||||
title: "Move disk 1: A → C"
|
|
||||||
description: "Move disk 1 from peg A to peg C."
|
|
||||||
needs: [move-6]
|
|
||||||
|
|
||||||
- id: verify
|
|
||||||
title: "Verify final state"
|
|
||||||
description: "All 3 disks now on peg C. Tower intact, all moves were legal."
|
|
||||||
needs: [move-7]
|
|
||||||
@@ -135,10 +135,10 @@ in different repos. Traditional tools don't track this.
|
|||||||
|
|
||||||
**The solution:** Explicit cross-project dependencies:
|
**The solution:** Explicit cross-project dependencies:
|
||||||
|
|
||||||
```yaml
|
```
|
||||||
depends_on:
|
depends_on:
|
||||||
- beads://github/acme/backend/be-456 # Backend API
|
beads://github/acme/backend/be-456 # Backend API
|
||||||
- beads://github/acme/shared/sh-789 # Shared types
|
beads://github/acme/shared/sh-789 # Shared types
|
||||||
```
|
```
|
||||||
|
|
||||||
**Why it matters:**
|
**Why it matters:**
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const HQGitignore = `# Gas Town HQ .gitignore
|
|||||||
# Explicitly track (override above patterns)
|
# Explicitly track (override above patterns)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Note: .beads/ has its own .gitignore that handles SQLite files
|
# Note: .beads/ has its own .gitignore that handles SQLite files
|
||||||
# and keeps issues.jsonl, metadata.json, config.yaml as source of truth
|
# and keeps issues.jsonl, metadata.json, config file as source of truth
|
||||||
`
|
`
|
||||||
|
|
||||||
func runGitInit(cmd *cobra.Command, args []string) error {
|
func runGitInit(cmd *cobra.Command, args []string) error {
|
||||||
|
|||||||
@@ -70,9 +70,6 @@ const (
|
|||||||
// FileConfigJSON is the general config file.
|
// FileConfigJSON is the general config file.
|
||||||
FileConfigJSON = "config.json"
|
FileConfigJSON = "config.json"
|
||||||
|
|
||||||
// FileConfigYAML is the beads config file.
|
|
||||||
FileConfigYAML = "config.yaml"
|
|
||||||
|
|
||||||
// FileAccountsJSON is the accounts configuration file in mayor/.
|
// FileAccountsJSON is the accounts configuration file in mayor/.
|
||||||
FileAccountsJSON = "accounts.json"
|
FileAccountsJSON = "accounts.json"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -273,8 +273,9 @@ func (c *BeadsSyncOrphanCheck) Run(ctx *CheckContext) *CheckResult {
|
|||||||
}
|
}
|
||||||
// Check if it's a code file
|
// Check if it's a code file
|
||||||
if strings.HasSuffix(f, ".go") || strings.HasSuffix(f, ".md") ||
|
if strings.HasSuffix(f, ".go") || strings.HasSuffix(f, ".md") ||
|
||||||
|
strings.HasSuffix(f, ".toml") || strings.HasSuffix(f, ".json") ||
|
||||||
strings.HasSuffix(f, ".yaml") || strings.HasSuffix(f, ".yml") ||
|
strings.HasSuffix(f, ".yaml") || strings.HasSuffix(f, ".yml") ||
|
||||||
strings.HasSuffix(f, ".json") || strings.HasSuffix(f, ".tmpl") {
|
strings.HasSuffix(f, ".tmpl") {
|
||||||
codeFiles = append(codeFiles, f)
|
codeFiles = append(codeFiles, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -408,6 +408,7 @@ func (m *Manager) initAgentStates(rigPath string) error {
|
|||||||
// initBeads initializes the beads database at rig level.
|
// initBeads initializes the beads database at rig level.
|
||||||
// The project's .beads/config.yaml determines sync-branch settings.
|
// The project's .beads/config.yaml determines sync-branch settings.
|
||||||
// Use `bd doctor --fix` in the project to configure sync-branch if needed.
|
// Use `bd doctor --fix` in the project to configure sync-branch if needed.
|
||||||
|
// TODO(bd-yaml): beads config should migrate to JSON (see beads issue)
|
||||||
func (m *Manager) initBeads(rigPath, prefix string) error {
|
func (m *Manager) initBeads(rigPath, prefix string) error {
|
||||||
beadsDir := filepath.Join(rigPath, ".beads")
|
beadsDir := filepath.Join(rigPath, ".beads")
|
||||||
if err := os.MkdirAll(beadsDir, 0755); err != nil {
|
if err := os.MkdirAll(beadsDir, 0755); err != nil {
|
||||||
@@ -419,6 +420,7 @@ func (m *Manager) initBeads(rigPath, prefix string) error {
|
|||||||
cmd.Dir = rigPath
|
cmd.Dir = rigPath
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
// bd might not be installed or --no-agents not supported, create minimal structure
|
// bd might not be installed or --no-agents not supported, create minimal structure
|
||||||
|
// Note: beads currently expects YAML format for config
|
||||||
configPath := filepath.Join(beadsDir, "config.yaml")
|
configPath := filepath.Join(beadsDir, "config.yaml")
|
||||||
configContent := fmt.Sprintf("prefix: %s\n", prefix)
|
configContent := fmt.Sprintf("prefix: %s\n", prefix)
|
||||||
if writeErr := os.WriteFile(configPath, []byte(configContent), 0644); writeErr != nil {
|
if writeErr := os.WriteFile(configPath, []byte(configContent), 0644); writeErr != nil {
|
||||||
@@ -747,7 +749,7 @@ This directory contains town-level plugins that run during Deacon patrol cycles.
|
|||||||
## Plugin Structure
|
## Plugin Structure
|
||||||
|
|
||||||
Each plugin is a directory containing:
|
Each plugin is a directory containing:
|
||||||
- plugin.md - Plugin definition with YAML frontmatter
|
- plugin.md - Plugin definition with TOML frontmatter
|
||||||
|
|
||||||
## Gate Types
|
## Gate Types
|
||||||
|
|
||||||
|
|||||||
@@ -274,23 +274,16 @@ This sends handoff mail, respawns fresh. Your next instance picks up from your h
|
|||||||
|
|
||||||
Your handoff state is tracked in a pinned bead: `witness Handoff`
|
Your handoff state is tracked in a pinned bead: `witness Handoff`
|
||||||
|
|
||||||
```yaml
|
```json
|
||||||
# Find with: bd list | grep "witness Handoff"
|
{
|
||||||
attached_molecule: mol-witness-patrol
|
"attached_molecule": "mol-witness-patrol",
|
||||||
attached_at: 2025-12-24T10:00:00Z
|
"attached_at": "2025-12-24T10:00:00Z",
|
||||||
|
"nudges": {
|
||||||
# Nudge escalation tracking
|
"toast": {"count": 2, "last": "2025-12-24T10:30:00Z"},
|
||||||
nudges:
|
"ace": {"count": 0, "last": null}
|
||||||
toast:
|
},
|
||||||
count: 2
|
"pending_cleanup": ["nux"]
|
||||||
last: "2025-12-24T10:30:00Z"
|
}
|
||||||
ace:
|
|
||||||
count: 0
|
|
||||||
last: null
|
|
||||||
|
|
||||||
# Polecats queued for cleanup
|
|
||||||
pending_cleanup:
|
|
||||||
- nux # received POLECAT_DONE, awaiting verification
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On startup, check for attached work:
|
On startup, check for attached work:
|
||||||
|
|||||||
Reference in New Issue
Block a user