flaglock

Date: 2025 07-July 29

CG 3

Perfect — thanks for the updated CLI code. Based on what you’ve shared, we can now do the following:

---

## ✅ Final List of Flags to Track in `flags.lock`

From your updated `init()` and `workspace()` commands, here are the relevant flags:

### For `init`:

- `target_dir: Path`
    
- `enforce_mulch_folder: bool`
    
- `stealth: bool`
    

### For `workspace`:

- `target_dir: Path`
    
- `name: str`
    
- `here: bool`
    
- `set_default: bool`
    
- `enforce_mulch_folder: bool`
    
- `stealth: bool`
    

We **will not** include `target_dir` or `name` in the _flag comparison_ logic, but we’ll still record them for historical/debugging purposes.

---

## 🔒 `flags.lock.json` Format (Example)

```json
{
  "init": {
    "stealth": true,
    "enforce_mulch_folder": false,
    "target_dir": "/Users/alex/project",
    "timestamp": "2025-07-29T06:20:00Z"
  },
  "workspace": {
    "here": false,
    "set_default": true,
    "stealth": false,
    "enforce_mulch_folder": true,
    "target_dir": "/Users/alex/project",
    "name": "2025-07-29__morning_experiment",
    "timestamp": "2025-07-29T06:22:10Z"
  }
}

🧠 Full FlagsLockStatus Class

Here’s the full version that matches your actual CLI setup:

# pipeline/core/flags_lock_status.py

import json
from pathlib import Path
from datetime import datetime
from typing import Optional


class FlagsLockStatus:
    def __init__(self, workspace_root: Path):
        self.lock_path = workspace_root / ".mulch" / "flags.lock.json"
        self.flags = {
            "init": {},
            "workspace": {}
        }
        self._load()

    def _load(self):
        if self.lock_path.exists():
            try:
                with self.lock_path.open("r") as f:
                    self.flags = json.load(f)
            except Exception as e:
                print(f"[warn] Failed to load flags.lock.json: {e}")

    def update_init(self, *, stealth: bool, enforce_mulch_folder: bool, target_dir: Path):
        self.flags["init"] = {
            "stealth": stealth,
            "enforce_mulch_folder": enforce_mulch_folder,
            "target_dir": str(target_dir),
            "timestamp": self._now()
        }
        self._save()

    def update_workspace(self, *, here: bool, set_default: bool, stealth: bool, enforce_mulch_folder: bool, target_dir: Path, name: str):
        self.flags["workspace"] = {
            "here": here,
            "set_default": set_default,
            "stealth": stealth,
            "enforce_mulch_folder": enforce_mulch_folder,
            "target_dir": str(target_dir),
            "name": name,
            "timestamp": self._now()
        }
        self._save()

    def compare(self, command: str, **current_flags) -> bool:
        """Returns True if current flags match stored ones (excluding timestamp, name, target_dir)."""
        stored = self.flags.get(command, {})
        for key, value in current_flags.items():
            if key in {"timestamp", "target_dir", "name"}:
                continue
            if stored.get(key) != value:
                return False
        return True

    def _now(self) -> str:
        return datetime.utcnow().isoformat() + "Z"

    def _save(self):
        self.lock_path.parent.mkdir(parents=True, exist_ok=True)
        with self.lock_path.open("w") as f:
            json.dump(self.flags, f, indent=2)

    def get_flags(self, command: str) -> Optional[dict]:
        return self.flags.get(command)

🧩 Example Integration in cli.py

Add near the top:

from pipeline.core.flags_lock_status import FlagsLockStatus

Then inside init():

lock = FlagsLockStatus(target_dir)
lock.update_init(
    stealth=stealth,
    enforce_mulch_folder=enforce_mulch_folder,
    target_dir=target_dir
)

And in workspace():

lock = FlagsLockStatus(target_dir)
lock.update_workspace(
    here=here,
    set_default=set_default,
    stealth=stealth,
    enforce_mulch_folder=enforce_mulch_folder,
    target_dir=target_dir,
    name=name
)

🟨 Optional: Warn if flags change

You can compare and warn:

if not lock.compare("init", stealth=stealth, enforce_mulch_folder=enforce_mulch_folder):
    typer.secho("⚠️ Flags used for `init` differ from the last run.", fg=typer.colors.YELLOW)

Or allow --force to override.


✅ Summary

You now have a fully integrated flags.lock.json system that:

Would you like a TOML version instead? Or maybe a mulch flags show CLI command to inspect it?