Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/hooks/guard-main-checkout-bash.selftest.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@7c2c5aedd94d7b0d94c91432bc607862e9c83c6c
# Self-test for guard-main-checkout-bash.sh — run it after touching that hook:
#
# .claude/hooks/guard-main-checkout-bash.selftest.sh
Expand Down
1 change: 1 addition & 0 deletions .claude/hooks/guard-main-checkout-bash.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@7c2c5aedd94d7b0d94c91432bc607862e9c83c6c
# guard-main-checkout-bash.sh — PreToolUse guard: the SAME worktree-first rule as
# guard-main-checkout.sh, applied to file writes that arrive through Bash instead of
# through the Edit / Write / NotebookEdit tools.
Expand Down
1 change: 1 addition & 0 deletions .claude/hooks/guard-main-checkout.selftest.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@70e77ec3b566b92d7c6551637d6bc746fb840bb6
# Self-test for guard-main-checkout.sh — run it after touching that hook:
#
# .claude/hooks/guard-main-checkout.selftest.sh
Expand Down
1 change: 1 addition & 0 deletions .claude/hooks/guard-main-checkout.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@c2520416cff04575dd3def789dd04a5745e3912b
# guard-main-checkout.sh — PreToolUse guard enforcing AGENTS.md worktree-first rule.
# Blocks Edit / Write / NotebookEdit unless the file being edited lives in a dedicated
# git WORKTREE — not the shared primary checkout.
Expand Down
1 change: 1 addition & 0 deletions .claude/hooks/guard-shared-stash.selftest.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@7c2c5aedd94d7b0d94c91432bc607862e9c83c6c
# Self-test for guard-shared-stash.sh — run it after touching that hook:
#
# .claude/hooks/guard-shared-stash.selftest.sh
Expand Down
1 change: 1 addition & 0 deletions .claude/hooks/guard-shared-stash.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@7c2c5aedd94d7b0d94c91432bc607862e9c83c6c
# guard-shared-stash.sh — PreToolUse guard: the stash stack is SHARED across worktrees.
# Blocks Bash commands that push to / pop from / drop the shared stash stack, and lets
# the read-only and SHA-pinned forms through.
Expand Down
1 change: 1 addition & 0 deletions .claude/hooks/guard-tree-enum.selftest.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@7c2c5aedd94d7b0d94c91432bc607862e9c83c6c
# Self-test for guard-tree-enum.sh — run it after touching that hook:
#
# .claude/hooks/guard-tree-enum.selftest.sh
Expand Down
1 change: 1 addition & 0 deletions .claude/hooks/guard-tree-enum.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# copied from objectstack@7c2c5aedd94d7b0d94c91432bc607862e9c83c6c
# guard-tree-enum.sh — PreToolUse guard: the `origin/main` reading rule covers file
# CONTENTS but not file ENUMERATION. Blocks a Bash command that takes its file LIST from
# the working tree and its file CONTENTS from `origin/main`, and lets either half alone —
Expand Down
64 changes: 35 additions & 29 deletions .github/workflows/board-snapshot.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Board Snapshot

# The standing caller for `scripts/pm/board-snapshot.mjs` (objectstack#17390).
# The standing caller for objectstack's `scripts/pm/board-snapshot.mjs`
# (objectstack#17390), run from an objectstack checkout: this repository holds
# NO copy of the archiver or of the modules it imports (objectui#10208). The
# checkout is not pinned to a sha, so each run executes objectstack's `main` as
# of that run — the same archiver a seat runs from its own objectstack checkout.
#
# ## Why a scheduled backup, and why it lands on a branch
#
Expand Down Expand Up @@ -120,26 +124,19 @@ name: Board Snapshot
#
# ⚠️ Upstream holds the offline half for free beside it: a `check:*` script runs
# the archiver's `--self-test` inside the required lint job, which has no paths
# filter, and a second gate is what requires that step to exist. NEITHER exists
# in this repository. ⇒ here the self-test is reachable ONLY through this file's
# own steps, behind this file's `paths:` filter, so a change that breaks the
# archiver while touching none of the four paths below merges unexercised.
# Wiring the self-test into the `Lint` workflow is a change to a file this
# adoption does not own; the gap is named here rather than assumed away.
# filter. That is where a change to the archiver is exercised before it merges,
# because the archiver no longer lives in this repository (objectui#10208); what
# a change HERE can break is this file's wiring, and this file is the one path
# below.
#
# The step below runs the self-test again before it touches the archive, so a
# broken tool fails loudly instead of committing a broken backup. ⛔ Its case
# count is not written down here — the run log prints it.
#
# ## Adopting this in a sibling repo
#
# Copy FOUR files, unchanged: `scripts/pm/board-snapshot.mjs`,
# `scripts/pm/check-half-states.mjs` (the archiver imports its proxy-re-exec plan
# and its repo resolver), `scripts/invoked-as.mjs` (imported by both) and this
# file. A repo that has already adopted the half-state patrol has the middle two.
# ⛔ Do not shorten this list from memory — the imports decide it, not this
# comment, and the patrol's own adopt list was wrong for months in exactly that
# way, which installed a dead sweeper that failed before its first predicate.
# Copy this file. It checks the archiver out of objectstack and runs it from
# there, so no script is copied (objectui#10208).
#
# There is nothing to configure. The board archived is `github.repository`,
# passed explicitly below, and the script REFUSES its resolver's default rather
Expand Down Expand Up @@ -191,17 +188,12 @@ on:
# closes that, which is a different card.
- cron: '14 2,8,14,20 * * *'
workflow_dispatch: {}
# Changes to the archiver itself get exercised before they merge. The paths
# name every file the run actually loads — the archiver, the module it imports
# its proxy plan and repo resolver from, the entry-guard helper both import,
# and this file. An undeclared dependency is one a change can break without
# this trigger firing, which is the same defect the adopt list above warns
# about, one layer along.
# Changes to the archiver's wiring get exercised before they merge. The run
# loads nothing else from this repository: the archiver and the modules it
# imports come from the objectstack checkout below (objectui#10208), so this
# file is the only path a change here can break it through.
pull_request:
paths:
- 'scripts/pm/board-snapshot.mjs'
- 'scripts/pm/check-half-states.mjs'
- 'scripts/invoked-as.mjs'
- '.github/workflows/board-snapshot.yml'

# Least privilege. `contents: write` is for the archive BRANCH and nothing else;
Expand Down Expand Up @@ -229,17 +221,31 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v7

# The archiver, from objectstack (objectui#10208). A public repository, so
# the default token reads it; `persist-credentials: false` because nothing
# here writes to it. Sparse: `scripts/pm` in cone mode also brings the
# files directly under `scripts/`, which is where the entry-guard helper
# the archiver and its sweeper module import (`scripts/invoked-as.mjs`)
# lives.
- name: Check out the objectstack archiver
uses: actions/checkout@v7
with:
repository: objectstack-ai/objectstack
path: objectstack-tooling
sparse-checkout: scripts/pm
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '22'

# No `pnpm install`: the archiver imports only `node:` builtins, global
# `fetch`, and two repo-local modules — no npm dependency, so installing
# the workspace here would buy nothing and would give a scheduled backup a
# lockfile it could fail on.
# `fetch`, and two modules from its own checkout — no npm dependency, so
# installing the workspace here would buy nothing and would give a
# scheduled backup a lockfile it could fail on.
- name: The tool's own cases, before it touches the archive
run: node scripts/pm/board-snapshot.mjs --self-test
run: node objectstack-tooling/scripts/pm/board-snapshot.mjs --self-test

# The archive branch is an ORPHAN: it shares no history with `main`, so a
# checkout of it carries the archive and nothing else. First run creates it
Expand Down Expand Up @@ -283,7 +289,7 @@ jobs:
SNAPSHOT_ARGS: ${{ github.event_name == 'pull_request' && '--out=board --dry-run --limit=5 --max-requests=25' || '--out=archive/board' }}
run: |
set +e
node scripts/pm/board-snapshot.mjs $SNAPSHOT_ARGS \
node objectstack-tooling/scripts/pm/board-snapshot.mjs $SNAPSHOT_ARGS \
> "$RUNNER_TEMP/snapshot.md" 2> "$RUNNER_TEMP/snapshot.err"
code=$?
set -e
Expand Down Expand Up @@ -393,7 +399,7 @@ jobs:
# alternate between two boards under one key — a complete,
# well-formed, green archive of a board that is half missing, which is
# the same footgun the header's adopt section warns about, one layer
# out. ⛔ Do not restore the upstream literal when re-syncing this file.
# out. ⛔ Do not restore the upstream literal.
mirror="s3://${R2_BUCKET}/objectui/board/"

# The SOURCE is the snapshot directory, NOT the worktree root that
Expand Down
Loading
Loading