← Files note Workspace|ROGNALIAARCHIVED FILE
skills/note-workspace-setup/scripts/update_standing_instructions.py
5.5 KB · Oct 2, 2026 · 00:33 UTC
#!/usr/bin/env python3
"""Replace the approved current standing instruction set with history."""
from __future__ import annotations
import argparse
import json
import sys
from typing import Optional
from standing_instruction_common import (
SCHEMA_VERSION,
StandingInstructionError,
atomic_replace_many,
canonical_hash,
exclusive_lock,
json_text,
load_json,
normalize_config,
parse_timestamp,
render_history,
resolve_workspace,
validate_data,
)
from workspace_common import render_standing_instructions
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Update approved standing instructions in one local workspace."
)
parser.add_argument("workspace", help="Absolute path to the user workspace")
parser.add_argument("--config", required=True, help="Approved JSON path, or -")
parser.add_argument("--timestamp", help="ISO 8601 change timestamp override")
return parser
def main(argv: Optional[list[str]] = None) -> int:
args = _parser().parse_args(argv)
try:
workspace, manifest = resolve_workspace(args.workspace)
config = normalize_config(load_json(args.config))
changed_at, moment = parse_timestamp(args.timestamp)
payload_sha256 = canonical_hash(config)
with exclusive_lock(
workspace / "profile/.standing-instructions.lock", changed_at
):
state, events = validate_data(workspace, manifest)
for event in events:
if event["request_id"] != config["request_id"]:
continue
if event["payload_sha256"] != payload_sha256:
raise StandingInstructionError(
"request_id is already used for a different standing instruction update"
)
print(
json.dumps(
{
"status": "duplicate",
"revision": event["revision"],
"instruction_count": len(event["after"]),
"validation": "pass",
"external_actions": [],
},
ensure_ascii=False,
indent=2,
)
)
return 0
if config["instructions"] == state["instructions"]:
raise StandingInstructionError("standing instructions have no effective change")
_, latest_moment = parse_timestamp(state["updated_at"])
if moment < latest_moment:
raise StandingInstructionError(
"changed_at must not be earlier than the current state"
)
revision = state["revision"] + 1
event_id = (
"standing-"
+ moment.strftime("%Y%m%d")
+ "-"
+ canonical_hash(
{
"workspace_id": manifest["workspace_id"],
"revision": revision,
"changed_at": changed_at,
"config": config,
}
)[:12]
)
event = {
"schema_version": SCHEMA_VERSION,
"event_id": event_id,
"request_id": config["request_id"],
"revision": revision,
"changed_at": changed_at,
"reason": config["reason"],
"approved_by_user": True,
"before": state["instructions"],
"after": config["instructions"],
"before_sha256": canonical_hash(state["instructions"]),
"after_sha256": canonical_hash(config["instructions"]),
"payload_sha256": payload_sha256,
}
new_state = {
"schema_version": SCHEMA_VERSION,
"workspace_id": manifest["workspace_id"],
"revision": revision,
"updated_at": changed_at,
"latest_event_id": event_id,
"instructions": config["instructions"],
}
atomic_replace_many(
{
workspace / "profile/standing-instructions.md": (
render_standing_instructions(config["instructions"]).rstrip()
+ "\n"
).encode("utf-8"),
workspace / "profile/standing-instructions.json": json_text(
new_state
).encode("utf-8"),
workspace
/ "profile/standing-instructions-history.jsonl": render_history(
events + [event]
),
}
)
validate_data(workspace, manifest)
print(
json.dumps(
{
"status": "updated",
"revision": revision,
"instruction_count": len(config["instructions"]),
"validation": "pass",
"external_actions": [],
},
ensure_ascii=False,
indent=2,
)
)
return 0
except (OSError, ValueError, json.JSONDecodeError) as exc:
print(
json.dumps({"status": "error", "error": str(exc)}, ensure_ascii=False),
file=sys.stderr,
)
return 2
if __name__ == "__main__":
raise SystemExit(main())
SHA-256: 55d70c4ef5bc0c116f82a8de4cb5513d71d35485d43e004b232e26a42270cf57