@vegastack/vegafactory 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +417 -0
- package/dist/dashboard-artifact.json +21240 -0
- package/dist/index.js +22752 -0
- package/dist/run-wrapper.js +377 -0
- package/package.json +46 -0
- package/skill/dev-architect/SKILL.md +106 -0
- package/skill/dev-architect/agents/openai.yaml +4 -0
- package/skill/dev-architect/references/ai-agents.md +96 -0
- package/skill/dev-architect/references/conventions.md +113 -0
- package/skill/dev-architect/references/data.md +89 -0
- package/skill/dev-architect/references/infra.md +99 -0
- package/skill/dev-architect/references/mobile.md +75 -0
- package/skill/dev-architect/references/pinned-facts.md +133 -0
- package/skill/dev-architect/references/principles.md +117 -0
- package/skill/dev-architect/references/security.md +90 -0
- package/skill/dev-architect/references/stack.md +38 -0
- package/skill/dev-architect/references/web.md +102 -0
- package/skill/dev-architect/refresh/REFRESH.md +31 -0
- package/skill/dev-architect/refresh/sources.json +239 -0
- package/skill/dev-chronicle/SKILL.md +52 -0
- package/skill/dev-chronicle/agents/openai.yaml +4 -0
- package/skill/dev-chronicle/references/conventions.md +113 -0
- package/skill/dev-chronicle/references/styles.md +75 -0
- package/skill/dev-chronicle/refresh/REFRESH.md +3 -0
- package/skill/dev-chronicle/refresh/sources.json +6 -0
- package/skill/dev-debug/SKILL.md +43 -0
- package/skill/dev-debug/agents/openai.yaml +4 -0
- package/skill/dev-debug/references/conventions.md +113 -0
- package/skill/dev-debug/references/loop-ladder.md +20 -0
- package/skill/dev-debug/refresh/REFRESH.md +3 -0
- package/skill/dev-debug/refresh/sources.json +6 -0
- package/skill/dev-implement/SKILL.md +81 -0
- package/skill/dev-implement/agents/openai.yaml +4 -0
- package/skill/dev-implement/assets/workflows/implement-children.js +12 -0
- package/skill/dev-implement/references/ask-route.md +80 -0
- package/skill/dev-implement/references/changelog-and-chronicle.md +21 -0
- package/skill/dev-implement/references/conventions.md +113 -0
- package/skill/dev-implement/references/ledger-and-resume.md +52 -0
- package/skill/dev-implement/references/parallel-children.md +35 -0
- package/skill/dev-implement/references/worktrees.md +63 -0
- package/skill/dev-implement/refresh/REFRESH.md +3 -0
- package/skill/dev-implement/refresh/sources.json +6 -0
- package/skill/dev-implement/scripts/children.mjs +479 -0
- package/skill/dev-implement/scripts/effective-policy.mjs +694 -0
- package/skill/dev-implement/scripts/evidence-check.mjs +107 -0
- package/skill/dev-implement/scripts/evidence-upload.mjs +181 -0
- package/skill/dev-implement/scripts/learning.mjs +41 -0
- package/skill/dev-implement/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-implement/scripts/lib/gh.mjs +101 -0
- package/skill/dev-implement/scripts/preflight.mjs +153 -0
- package/skill/dev-implement/scripts/questions.mjs +381 -0
- package/skill/dev-implement/scripts/reclaim.mjs +116 -0
- package/skill/dev-implement/scripts/recovery.mjs +213 -0
- package/skill/dev-implement/scripts/worktree.mjs +991 -0
- package/skill/dev-intake/SKILL.md +80 -0
- package/skill/dev-intake/agents/openai.yaml +4 -0
- package/skill/dev-intake/references/ask-route.md +80 -0
- package/skill/dev-intake/references/brief-template.md +89 -0
- package/skill/dev-intake/references/conventions.md +113 -0
- package/skill/dev-intake/refresh/REFRESH.md +3 -0
- package/skill/dev-intake/refresh/sources.json +6 -0
- package/skill/dev-intake/scripts/brief-lint.mjs +87 -0
- package/skill/dev-intake/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-intake/scripts/questions.mjs +381 -0
- package/skill/dev-plan/SKILL.md +54 -0
- package/skill/dev-plan/agents/openai.yaml +4 -0
- package/skill/dev-plan/references/ask-route.md +80 -0
- package/skill/dev-plan/references/conventions.md +113 -0
- package/skill/dev-plan/references/plan-format.md +82 -0
- package/skill/dev-plan/refresh/REFRESH.md +3 -0
- package/skill/dev-plan/refresh/sources.json +6 -0
- package/skill/dev-plan/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-plan/scripts/plan-lint.mjs +319 -0
- package/skill/dev-plan/scripts/questions.mjs +381 -0
- package/skill/dev-review/SKILL.md +76 -0
- package/skill/dev-review/agents/openai.yaml +4 -0
- package/skill/dev-review/assets/review-known-patterns.md.template +32 -0
- package/skill/dev-review/references/conventions.md +113 -0
- package/skill/dev-review/references/cross-agent.md +39 -0
- package/skill/dev-review/references/dispatch-prompts.md +121 -0
- package/skill/dev-review/references/security-axis.md +45 -0
- package/skill/dev-review/refresh/REFRESH.md +5 -0
- package/skill/dev-review/refresh/sources.json +6 -0
- package/skill/dev-setup/SKILL.md +113 -0
- package/skill/dev-setup/agents/openai.yaml +4 -0
- package/skill/dev-setup/assets/agents-section.md.template +24 -0
- package/skill/dev-setup/assets/dev-profile.md.template +102 -0
- package/skill/dev-setup/assets/factory-board.yml.template +162 -0
- package/skill/dev-setup/assets/hooks/decision-nudge.mjs +30 -0
- package/skill/dev-setup/assets/hooks/prompt-skill-mention.mjs +29 -0
- package/skill/dev-setup/assets/hooks/session-end.mjs +14 -0
- package/skill/dev-setup/assets/hooks/session-start.mjs +178 -0
- package/skill/dev-setup/assets/hooks/ship-guard.mjs +738 -0
- package/skill/dev-setup/assets/hooks/skill-activated.mjs +47 -0
- package/skill/dev-setup/assets/hooks/stop-heartbeat.mjs +14 -0
- package/skill/dev-setup/assets/workflows/implement-children.js +12 -0
- package/skill/dev-setup/references/ask-route.md +80 -0
- package/skill/dev-setup/references/conventions.md +113 -0
- package/skill/dev-setup/references/github-app.md +286 -0
- package/skill/dev-setup/references/harness-facts.md +169 -0
- package/skill/dev-setup/references/stack-playbooks.md +124 -0
- package/skill/dev-setup/refresh/REFRESH.md +13 -0
- package/skill/dev-setup/refresh/sources.json +602 -0
- package/skill/dev-setup/scripts/effective-policy.mjs +694 -0
- package/skill/dev-setup/scripts/questions.mjs +381 -0
- package/skill/dev-setup/scripts/ship-policy.mjs +195 -0
- package/skill/dev-ship/SKILL.md +56 -0
- package/skill/dev-ship/agents/openai.yaml +4 -0
- package/skill/dev-ship/references/conventions.md +113 -0
- package/skill/dev-ship/references/runbook.md +72 -0
- package/skill/dev-ship/refresh/REFRESH.md +3 -0
- package/skill/dev-ship/refresh/sources.json +6 -0
- package/skill/dev-ship/scripts/lib/approval.mjs +1182 -0
- package/skill/dev-ship/scripts/ship-gate.mjs +485 -0
- package/skill/dev-status/SKILL.md +56 -0
- package/skill/dev-status/agents/openai.yaml +4 -0
- package/skill/dev-status/references/conventions.md +113 -0
- package/skill/dev-status/refresh/REFRESH.md +3 -0
- package/skill/dev-status/refresh/sources.json +6 -0
- package/skill/dev-status/scripts/effective-policy.mjs +694 -0
- package/skill/dev-status/scripts/status.mjs +311 -0
- package/skill/skill-maintainer/SKILL.md +82 -0
- package/skill/skill-maintainer/agents/openai.yaml +4 -0
- package/skill/skill-maintainer/references/release-ops.md +61 -0
- package/skill/skill-maintainer/references/standards.md +137 -0
- package/skill/skill-maintainer/refresh/REFRESH.md +40 -0
- package/skill/skill-maintainer/refresh/sources.json +103 -0
- package/skill/skill-scan/SKILL.md +59 -0
- package/skill/skill-scan/agents/openai.yaml +4 -0
- package/skill/skill-scan/refresh/REFRESH.md +18 -0
- package/skill/skill-scan/refresh/sources.json +133 -0
- package/skill/skill-scan/scripts/lib/skillspector.mjs +226 -0
- package/skill/skill-scan/scripts/skill-scan.mjs +1002 -0
- package/skill/skillify/SKILL.md +108 -0
- package/skill/skillify/agents/openai.yaml +4 -0
- package/skill/skillify/assets/templates/README.md.template +26 -0
- package/skill/skillify/assets/templates/REFRESH.md.template +16 -0
- package/skill/skillify/assets/templates/SKILL.md.template +27 -0
- package/skill/skillify/assets/templates/evals.json.template +12 -0
- package/skill/skillify/assets/templates/openai.yaml.template +4 -0
- package/skill/skillify/assets/templates/skill.test.ts.template +27 -0
- package/skill/skillify/assets/templates/sources.json.template +6 -0
- package/skill/skillify/assets/templates/trigger-queries.json.template +1 -0
- package/skill/skillify/references/authoring.md +103 -0
- package/skill/skillify/references/eval-playbook.md +112 -0
- package/skill/skillify/refresh/REFRESH.md +23 -0
- package/skill/skillify/refresh/sources.json +6 -0
- package/skill/skillify/scripts/scaffold-skill.mjs +334 -0
- package/skill/skillify/scripts/trigger-check.mjs +209 -0
- package/skill/vegafactory-setup/SKILL.md +77 -0
- package/skill/vegafactory-setup/agents/openai.yaml +4 -0
- package/skill/vegafactory-setup/assets/control-room/boards.md.template +17 -0
- package/skill/vegafactory-setup/assets/control-room/decisions.md.template +5 -0
- package/skill/vegafactory-setup/assets/control-room/group.md.template +44 -0
- package/skill/vegafactory-setup/assets/control-room/onboarding/dispatcher-box.md.template +86 -0
- package/skill/vegafactory-setup/assets/control-room/onboarding/new-repo.md.template +13 -0
- package/skill/vegafactory-setup/assets/control-room/onboarding/new-teammate.md.template +12 -0
- package/skill/vegafactory-setup/assets/control-room/org.md.template +60 -0
- package/skill/vegafactory-setup/assets/control-room/people.csv.template +2 -0
- package/skill/vegafactory-setup/assets/control-room/repos.md.template +7 -0
- package/skill/vegafactory-setup/assets/control-room/rules/CODEOWNERS.template +6 -0
- package/skill/vegafactory-setup/assets/control-room/rules/README.md.template +9 -0
- package/skill/vegafactory-setup/assets/control-room/rules/stats-privacy.md.template +44 -0
- package/skill/vegafactory-setup/assets/control-room/templates/README.md.template +9 -0
- package/skill/vegafactory-setup/references/control-room.md +149 -0
- package/skill/vegafactory-setup/references/conventions.md +113 -0
- package/skill/vegafactory-setup/refresh/REFRESH.md +5 -0
- package/skill/vegafactory-setup/refresh/sources.json +6 -0
- package/skill-integrity.json +252 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# {{group}} — group defaults
|
|
2
|
+
|
|
3
|
+
One default for every knob a group can decide for a repo's `.vegastack/dev.md` — the per-repo facts (`repo:`, `skill-scan:`, `board:`, `control-room:`, the detected org types and fields) stay in the repo — so a repo that answers nothing else still gets a complete profile. Ordinary explicit repo values beat group defaults, which beat ordinary org defaults. Organization locks require exact org delegation; this file cannot grant it or appoint admins. Precedence and the read path: the vegafactory-setup skill's `references/control-room.md`.
|
|
4
|
+
|
|
5
|
+
policy-schema: 2
|
|
6
|
+
|
|
7
|
+
## Knobs
|
|
8
|
+
|
|
9
|
+
review: cross-agent-risky # subagent | cross-agent-risky | cross-agent
|
|
10
|
+
gates: 3 # 3 = approve/PR/merge · 2 = approve + one "ship it" · 1 = direct-to-main
|
|
11
|
+
merge: rebase # rebase | squash | merge
|
|
12
|
+
branch: <type>/<slug> # type: feat | fix | docs | chore | refactor
|
|
13
|
+
labels: needs-operator needs-plan ready working for-operator risky research quick-build full-plan epic
|
|
14
|
+
workflow-labels: {"needsOperator":"needs-operator","needsPlan":"needs-plan","ready":"ready","working":"working","forOperator":"for-operator"} # custom names need explicit mapping; if labels: remains, both must agree
|
|
15
|
+
tests: required # required | best-effort | none
|
|
16
|
+
ui-evidence: playwright # playwright | none
|
|
17
|
+
worktree-retention: 14d # how long a parked worktree survives with no session
|
|
18
|
+
skillspector-update: auto # off | notify | auto
|
|
19
|
+
sync-max-age: 30m # how stale the local control-room clone may be before a session refreshes it — <n>m or <n>h
|
|
20
|
+
changelog: changesets # changesets | keep-a-changelog | pubspec+changelog | none
|
|
21
|
+
release: on-request # on-request | per-merge
|
|
22
|
+
chronicle: on # on | off
|
|
23
|
+
chronicle-style: plain # plain | story | witty
|
|
24
|
+
emoji: none # none | sparing
|
|
25
|
+
evidence-repo: {{org}}/{{evidence-repo}} # where UI screenshots and run evidence are pushed
|
|
26
|
+
architect: {{architect}} # the architecture owner dev-architect speaks to
|
|
27
|
+
operators: {{operators}} # csv of logins from people.csv who own issues in this group
|
|
28
|
+
|
|
29
|
+
## Harness policy
|
|
30
|
+
|
|
31
|
+
harness-policy: intake {{intake-harness}} {{intake-model}} {{intake-effort}} · plan {{plan-harness}} {{plan-model}} {{plan-effort}} · implement {{implement-harness}} {{implement-model}} {{implement-effort}} · review {{review-harness}} {{review-model}} {{review-effort}} · status {{status-harness}} {{status-model}} {{status-effort}} · chronicle {{chronicle-harness}} {{chronicle-model}} {{chronicle-effort}} # confirm detected supported subscription choices for every stage; placeholders block execution
|
|
32
|
+
|
|
33
|
+
## Runtime
|
|
34
|
+
|
|
35
|
+
dispatcher: {{dispatcher-host}} # the always-on box that turns labels and reactions into headless runs
|
|
36
|
+
ship-environments: preview auto · staging auto · production ask
|
|
37
|
+
design-system: {{design-system}} # the design layer a repo in this group consumes by default, or `none`
|
|
38
|
+
secrets: {{secret-names}} # NAMES of the secrets a repo in this group expects — never values
|
|
39
|
+
gh-floor: 2.97 # the minimum gh CLI version this group's automation assumes
|
|
40
|
+
stats: inherit # inherit | on | off; an org lock needs explicit exact org delegation
|
|
41
|
+
|
|
42
|
+
## Delegated administration
|
|
43
|
+
|
|
44
|
+
Admin assignments and group capabilities resolve from org.md, independently of descriptive people.csv rows. A group admin may change only permitted ordinary/delegated defaults and already-authorized members/repositories. Machine settings additionally require previous org fleet.groupDelegations field/range permission; changing enrollment, machine group/repositories, host binding or coordination is org-admin-only. Keep local paths and credentials on the machine. Show the exact diff and verified requester before applying the existing Git delivery rules.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Provisioning the dispatcher box for {{org}}/{{repo}}
|
|
2
|
+
|
|
3
|
+
The always-on Mac mini runs two things: the GitHub Actions runner that executes CI and release, and the `vegafactory dispatch --watch` service that turns labels and 🚀 reactions into headless runs. Every step below is a human's own action on the box or on the org's settings; the skill positions the operator, it never reaches for the credential.
|
|
4
|
+
|
|
5
|
+
## Accounts
|
|
6
|
+
|
|
7
|
+
Two macOS accounts, neither an admin of the other:
|
|
8
|
+
|
|
9
|
+
- `{{runner-user}}` — runs the Actions runner and nothing else.
|
|
10
|
+
- `{{dispatcher-user}}` — runs `vegafactory dispatch`, and owns the `gh`, Claude, and Codex credentials.
|
|
11
|
+
|
|
12
|
+
The split is the whole point: a CI job runs as `{{runner-user}}` and so **cannot read** the tokens in `{{dispatcher-user}}`'s home — a workflow edited in a pull request gets a repository token and no more. The GitHub App private key is never on this box; it lives in org settings as the secret `VEGAFACTORY_APP_PRIVATE_KEY`.
|
|
13
|
+
|
|
14
|
+
## Toolchain
|
|
15
|
+
|
|
16
|
+
Installed system-wide so both accounts see the same versions:
|
|
17
|
+
|
|
18
|
+
- git and the Xcode command line tools — `xcode-select --install`.
|
|
19
|
+
- bun 1.3.14 — `bun --version` prints exactly `1.3.14`, matching the workspace `packageManager` pin.
|
|
20
|
+
- Node 24 — `node --version` prints a `v24.` line.
|
|
21
|
+
- gh 2.97 or newer — `gh --version`, first line; the board mirror needs that floor.
|
|
22
|
+
- SkillSpector for the dispatcher's review runs — `uv tool install git+https://github.com/NVIDIA/skillspector.git`, then `skillspector --version`.
|
|
23
|
+
|
|
24
|
+
CI jobs get their own bun and Node from `setup-bun` and `setup-node`, so these copies serve `{{dispatcher-user}}` and stand as the fallback.
|
|
25
|
+
|
|
26
|
+
## Power and login
|
|
27
|
+
|
|
28
|
+
- `sudo systemsetup -setcomputersleep Never`
|
|
29
|
+
- `sudo pmset -a sleep 0 disksleep 0 womp 1`
|
|
30
|
+
|
|
31
|
+
On macOS a per-user LaunchAgent loads only inside that account's GUI session, so exactly one account may rely on auto-login. Give it to `{{runner-user}}`. `{{dispatcher-user}}`'s service is installed by `vegafactory service install` with `RunAtLoad` and `KeepAlive`; its requirement is the reboot drill in `## Verify`, not any particular mechanism.
|
|
32
|
+
|
|
33
|
+
## Dispatcher ownership and offline recovery
|
|
34
|
+
|
|
35
|
+
Keep one non-root dispatcher account, `{{dispatcher-user}}`, and one confirmed absolute config path for the host. All service and manual invocations use that path and its single `lockRoot` (default `~/.vegastack/factory/locks`). Inspect the previous root with services stopped before changing it. Separate homes or copied machine configuration do not establish exclusion or enroll another machine.
|
|
36
|
+
|
|
37
|
+
Local claims have a random token, UID, boot identity and process start identity. Claim mutations use an exclusive directory guard and private owner records. Permission errors, corrupt JSON, symlinks, PID-only legacy files and unverifiable process inspection preserve evidence and refuse. A normal stale lease is replaced under the guard only after proving its process absent or its boot/start identity different. A guard without a valid owner record is never automatically stolen.
|
|
38
|
+
|
|
39
|
+
For offline recovery, stop all dispatchers under this account, preserve the exact claim and guard, verify the original process and retained runs have stopped, acquire exclusive offline recovery ownership, then re-read and reconcile only the inspected stale token. If stop or ownership is unknown, retain the claim and report the blocker. Never delete worktrees, run records or checkpoints to clear a lock. The two-second guard wait is a contention bound, not an execution deadline.
|
|
40
|
+
|
|
41
|
+
Shared ownership lives on the explicitly configured existing private state branch. Provisioning that branch and changing enrollment use the separately authorized administration workflow; dispatcher runtime cannot create, reset or repoint it. Machine host binding is a domain-separated digest of the platform OS identity; it detects accidental copied setup, not a malicious cloned OS. Raw platform identifiers and credentials do not belong in the control room.
|
|
42
|
+
|
|
43
|
+
Before another machine resumes work, verify stop evidence, remotely available checkpoint and original execution identity, current policy/approval, exact owner generation and reconciled effects. A stale heartbeat, unreachable machine or configured guard is insufficient. Independent work can continue while the affected task retains its reservation. Qualification of real macOS/Linux reboot behavior and the selected GitHub conditional provider remains part of the authorized live drill; local fixtures cannot mark it passed.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Grant the group
|
|
47
|
+
|
|
48
|
+
Org-admin commands, run in an admin's own session (`{{dispatcher-user}}`'s, or any admin's machine) — never as `{{runner-user}}`, whose account holds no `gh` credential by design. The group must exist before the runner registers into it (`config.sh` exits non-zero on an unknown group), and the repository must be granted to it before a job can land. Look the group up first; create it only when the lookup prints no such row:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
gh api orgs/{{org}}/actions/runner-groups -q '.runner_groups[] | "\(.id) \(.name) \(.visibility)"'
|
|
52
|
+
gh api -X POST orgs/{{org}}/actions/runner-groups -f name={{runner-group}} -f visibility=selected
|
|
53
|
+
gh api -X PUT orgs/{{org}}/actions/runner-groups/<GROUP_ID>/repositories/$(gh api repos/{{org}}/{{repo}} -q .id)
|
|
54
|
+
gh api -X POST orgs/{{org}}/actions/runners/registration-token -q .token # the registration token for the block below; it expires in an hour
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
An ungranted group **queues jobs forever with `runner: null` rather than failing** — that is how the 01-09-2026 probe presented, and it is indistinguishable from a slow runner until you read the group. A missing group is the louder failure: registration refuses it on the spot.
|
|
58
|
+
|
|
59
|
+
## Register the runner
|
|
60
|
+
|
|
61
|
+
As `{{runner-user}}`, with the registration token from the block above pasted into `RUNNER_TOKEN` — nothing here calls `gh`, because this account is the one that must never hold a credential:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
set -e
|
|
65
|
+
RUNNER_TOKEN=<paste the registration token here>
|
|
66
|
+
RUNNER_VERSION=$(curl -fsSL https://api.github.com/repos/actions/runner/releases/latest | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
|
|
67
|
+
test -n "$RUNNER_VERSION"
|
|
68
|
+
mkdir -p "$HOME/actions-runner" && cd "$HOME/actions-runner"
|
|
69
|
+
curl -fsSL -o runner.tar.gz \
|
|
70
|
+
"https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-osx-arm64-${RUNNER_VERSION}.tar.gz"
|
|
71
|
+
tar xzf runner.tar.gz && rm runner.tar.gz
|
|
72
|
+
./config.sh --url "https://github.com/{{org}}" --token "$RUNNER_TOKEN" \
|
|
73
|
+
--runnergroup {{runner-group}} --name {{runner-name}} --unattended --replace
|
|
74
|
+
./svc.sh install && ./svc.sh start && ./svc.sh status
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Verify
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
gh api orgs/{{org}}/actions/runner-groups/<GROUP_ID>/runners -q '.runners[] | "\(.name) \(.status)"'
|
|
81
|
+
ps -axo user,command | grep '[R]unner.Listener'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The first prints `{{runner-name}} online` — the org endpoint is the one that lists a group's runners, while `repos/{{org}}/{{repo}}/actions/runners` lists repository-level runners. The second prints `{{runner-user}}` and never `{{dispatcher-user}}`.
|
|
85
|
+
|
|
86
|
+
Then the reboot drill: `sudo reboot`, wait for the box, and run both checks again **without logging anything in by hand**. A box that needs a human at the keyboard after a power cut is not always-on.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Onboarding a repo into {{org}}
|
|
2
|
+
|
|
3
|
+
Run by `vegafactory-setup register <repo>`, then `dev-setup` inside the repo.
|
|
4
|
+
|
|
5
|
+
1. Confirm the repo's group. `groups/<g>/group.md` is the default set the repo layers on.
|
|
6
|
+
2. Run `dev-setup` in the repo. Every knob the control room already answers is stated as inherited, not asked.
|
|
7
|
+
3. Add the repo's row to `repos.md` — repo, group, board, owner.
|
|
8
|
+
4. Link the board if `boards.md` names one for this group, and add the board-mirror workflow from `templates/`.
|
|
9
|
+
5. Copy `rules/CODEOWNERS` into the repo's `.github/CODEOWNERS`, filled in for its owners.
|
|
10
|
+
6. Create the workflow labels and confirm branch protection on the default branch.
|
|
11
|
+
7. Confirm the repo's `control-room:` knob names this control room and the repo's group.
|
|
12
|
+
|
|
13
|
+
A step the operator declines is recorded as an unconfirmed line in `org.md`, never quietly skipped.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Onboarding a teammate into {{org}}
|
|
2
|
+
|
|
3
|
+
Run by `vegafactory-setup onboard <login>`. Every step below is the person's own action on their own machine; the skill positions them and verifies the result, it never reaches for their credentials.
|
|
4
|
+
|
|
5
|
+
1. `gh auth login` — GitHub CLI, at or above the group's `gh-floor:`.
|
|
6
|
+
2. Install the harnesses the group's `harness-policy:` line names, and sign each one in.
|
|
7
|
+
3. `vegafactory skills add --group dev --global`.
|
|
8
|
+
4. Control-room read access — the operator grants it; confirm with `gh repo view {{org}}/vegafactory-control-room`.
|
|
9
|
+
5. Subscribe to the org's Slack channel through the official GitHub Slack app; notifications are GitHub assignment plus Slack, nothing else.
|
|
10
|
+
6. Add the person's row to `people.csv` — `login,name,role,slack,timezone,groups`.
|
|
11
|
+
|
|
12
|
+
`role` is recorded only on the operator's word, never inferred from org membership: `lead` gates the people-level statistics views.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# {{org}} — org profile
|
|
2
|
+
|
|
3
|
+
The org's global answers. Everything here applies to everyone, in every group and every repo. Group defaults live in `groups/<g>/group.md`; org locks and administration stay here — layout, precedence, and the read path are the vegafactory-setup skill's `references/control-room.md`.
|
|
4
|
+
|
|
5
|
+
org: {{org}}
|
|
6
|
+
policy-schema: 2
|
|
7
|
+
|
|
8
|
+
## Goals
|
|
9
|
+
|
|
10
|
+
{{goals}} <!-- one paragraph: what this org is building and for whom -->
|
|
11
|
+
|
|
12
|
+
## What applies to everyone
|
|
13
|
+
|
|
14
|
+
- language: {{language}} # the language every artifact is written in
|
|
15
|
+
- dates: DD-MM-YYYY # the date format in every register, approval, and revision line
|
|
16
|
+
- Nothing ships without the operator's explicit instruction — no push to a default branch, merge, tag, publish, or deploy on green checks, schedules, or standing approvals alone. A repo's gates knob changes how many actions one instruction covers, never whether an instruction is needed.
|
|
17
|
+
- Secrets are named here, never written here. A runbook names `{{secret-name-example}}`; the value lives in the secret store that name points at.
|
|
18
|
+
|
|
19
|
+
## Statistics policy
|
|
20
|
+
|
|
21
|
+
Confirm reporting and quality choices for this organization. Ordinary values inherit; mandatory values and exact exceptions are authored in the organization authority object. The legacy stats-override line below remains readable but is not group delegation.
|
|
22
|
+
|
|
23
|
+
stats: on
|
|
24
|
+
stats-people: off
|
|
25
|
+
stats-override: allowed
|
|
26
|
+
|
|
27
|
+
## Automation identity
|
|
28
|
+
|
|
29
|
+
The names of the org's automation identity. Values live in GitHub org settings; nothing here is a secret.
|
|
30
|
+
|
|
31
|
+
app: VegaFactory # the public GitHub App every automated write uses; humans still own issues
|
|
32
|
+
app-slug: vegafactory # GitHub's slug for the App name — confirm it on the App settings page; a bot edit shows the actor <app-slug>[bot]
|
|
33
|
+
app-install: {{installation-id}} # gh api orgs/{{org}}/installations — filled after the operator installs the App
|
|
34
|
+
app-secrets: variable VEGAFACTORY_APP_ID · secret VEGAFACTORY_APP_PRIVATE_KEY # names only; the values live in GitHub org settings and nowhere else
|
|
35
|
+
app-permissions: Issues read/write · Projects (organization) read/write · Metadata read · Pull requests read/write · Contents read # widening any of these is a register line
|
|
36
|
+
|
|
37
|
+
## Unconfirmed
|
|
38
|
+
|
|
39
|
+
Lines the operator has not confirmed yet. Each is a question the next run asks again rather than an answer anyone may assume.
|
|
40
|
+
|
|
41
|
+
- (none)
|
|
42
|
+
|
|
43
|
+
## Explicit authority
|
|
44
|
+
|
|
45
|
+
Confirm the org admin login against people.csv and verified requester context before replacing the placeholder. Preserve existing assignments on rerun. The empty locks/delegations below make no hidden house-policy choice; render the organization's confirmed constraints and exact reporting exceptions here.
|
|
46
|
+
|
|
47
|
+
```vsk-policy
|
|
48
|
+
{
|
|
49
|
+
"schemaVersion": 2,
|
|
50
|
+
"locked": {},
|
|
51
|
+
"delegations": [],
|
|
52
|
+
"administration": {
|
|
53
|
+
"orgAdmins": ["{{confirmed-org-admin-login}}"],
|
|
54
|
+
"groupAdmins": {},
|
|
55
|
+
"groupAdminCapabilities": {}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Only org admins appoint/remove admins. Confirm optional group capabilities and machine enrollment through the control-room reference's capability/fleet contract. Render registry entries disabled until qualification, preserving other machines. Local bootstrap coordinates, OS accounts, paths and credentials do not belong in this authority object. Each required unknown field blocks completion; preserve explicit optional declines. Learning settings, if selected, are `learning: normal-work|off` and `learning-adoption: scoped-reversible|propose-only`; verified lessons cannot change approvals, quality/privacy rules or enable native vendor memory.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Repos
|
|
2
|
+
|
|
3
|
+
The registry vegafactory-setup writes when a repo is registered. One row per repo; the `group` cell names the `groups/<g>/` whose defaults that repo layers on.
|
|
4
|
+
|
|
5
|
+
| repo | group | board | owner |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| {{org}}/{{repo}} | dev | {{board}} | {{owner}} |
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Org CODEOWNERS pattern — copied into each repo's .github/CODEOWNERS at registration.
|
|
2
|
+
# Owners are GitHub logins or teams from people.csv; every path needs one owner who can approve.
|
|
3
|
+
|
|
4
|
+
* @{{org}}/{{default-team}}
|
|
5
|
+
/.vegastack/ @{{architect}}
|
|
6
|
+
/.github/workflows/ @{{architect}}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Org rules
|
|
2
|
+
|
|
3
|
+
Rules every repo in {{org}} inherits. A repo may add to these; it never silently weakens one.
|
|
4
|
+
|
|
5
|
+
- `CODEOWNERS` — the org's ownership pattern, copied into each repo's `.github/CODEOWNERS` at registration.
|
|
6
|
+
- `review-known-patterns.md` — review findings the org has dismissed, each with its mandatory "Still flag if:" clause. A repo's own `.vegastack/review-known-patterns.md` concatenates with this one.
|
|
7
|
+
- `security.md` — the org-wide security rules a review's security axis reads before a repo's own.
|
|
8
|
+
|
|
9
|
+
Add a file here only when the rule genuinely applies org-wide; a rule that fits one repo belongs in that repo.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Statistics — what stays local and what is shared
|
|
2
|
+
|
|
3
|
+
This rule applies to repositories registered in {{org}}. Confirm the organization's reporting policy before enabling exports. VegaStack's selected profile is mandatory private attributed reporting; other organizations choose their own confirmed profile. Repository exceptions require the exact organization delegation accepted by the policy validator. A machine preference or a descriptive `lead` role grants no exception or administration authority.
|
|
4
|
+
|
|
5
|
+
## Reporting modes and recipients
|
|
6
|
+
|
|
7
|
+
`stats-export: attributed` permits the closed task/person reporting schema below. `non-attributed` removes execution attribution and suppresses activity and rework snapshots. `off` suppresses every variant, including queued execution reports. `stats: off` also suppresses export. Unknown, stale or unconfirmed policy refuses export. Local recovery remains independent of these reporting modes.
|
|
8
|
+
|
|
9
|
+
The recipients are readers of the confirmed private control-room Git repository, including existing clones. Dashboard and CLI person views apply current organization/group/person scope before aggregation, but those filters do not restrict direct Git access. Repository/day/model combinations may permit inference; non-attributed is not a promise of anonymity. Git commit metadata uses a neutral transport identity. GitHub actors, access logs, existing Git history and historical copies remain separately visible to their platform/repository readers.
|
|
10
|
+
|
|
11
|
+
## The exact shared schema
|
|
12
|
+
|
|
13
|
+
All reports have `schemaVersion: 2`, `metricVersion: 2`, `recordKind`, a random opaque `eventId`, a validated `destination` and `utcDay`. Destination contains exactly `host`, `org`, `repo` and `controlRoom` and binds one registered code repository to its confirmed recipient. Unknown fields or variants refuse; nested objects are closed too.
|
|
14
|
+
|
|
15
|
+
- **Execution:** `stage`, `harness`, `model`, `mode`, `outcome`, `durationSeconds`, `turns`, `toolCalls`, `subagents`, `tokensIn`, `tokensOut`, `cacheReadTokens`, `cacheWriteTokens`, `costUsd`, `coverage`, `skills`. Only executions count as runs or enter execution usage/cost denominators. The six configured stages are intake, plan, implement, review, status and chronicle; corrections use implement. Outcomes are succeeded, failed, spawn-failed, timed-out, cancelled, interrupted and termination-unconfirmed.
|
|
16
|
+
- **Attributed execution extension:** exactly `taskRef`, `taskOwner`, `agentAccountOwner`, `executionRef`, `attempt`, `startedAt`, `endedAt`, `operatorMinutes`, `apiEquivalentUsd`, `estimateBasis`. Unlinked execution has null taskRef; unknown owners stay null. A private persisted random executionRef is reused across retries, never derived from a local run/session/account identifier. Task owner and account owner are different dimensions.
|
|
17
|
+
- **Activity, attributed only:** exactly `taskRef`, `taskOwner`, `agentAccountOwner`, `activity`, in addition to the common fields. Activity contains `taskRef`, `activityId`, `kind`, `occurredAt`, `deliveryRef`, `sourceRef`. Kinds are implemented, merged, released, review, fix and handback. Repeated `(taskRef, activityId)` observations count once across transport UUIDs. Activities do not add a run or duplicate usage.
|
|
18
|
+
- **Rework snapshot, attributed only:** exactly `taskRef`, `taskOwner`, `reworkSnapshot`, in addition to common fields. The snapshot contains `taskRef`, `asOf`, `sourceRef`, `counterEpoch`, `reviewRounds`, `fixRounds`, `handbacks`, `historyComplete`, `historyStart`. Counters are authoritative as-of values, never additive activity. Counter epoch is the approved-scope SHA-256 plus `:v2`. A difference needs complete boundary history, the same epoch and monotonic counters. Lifetime is the latest authoritative total and its date; expiry makes it unavailable until actual authorized source evidence is reread. Do not redate snapshots to retain identity indefinitely.
|
|
19
|
+
|
|
20
|
+
TaskRef contains exactly `repo`, positive `issue`, and nullable `taskId`. DeliveryRef contains exactly `repo`, `pr`, `prNodeId`, `acceptedParentHead`, nullable `mergedCommit`. Reporting sourceRef contains exactly `repo`, nullable `issue`, `commentId`, `nodeId`, `bodySha256`; at least one evidence identity is required. Inner and outer task references must agree, and all repository references must match the destination. These are typed GitHub IDs/hashes, not raw evidence text, arbitrary URLs or private recovery pointers.
|
|
21
|
+
|
|
22
|
+
Measurements are finite nonnegative numbers or explicit null; counters are safe nonnegative integers or null. Unknown is different from zero. Coverage contains exactly the nine execution measurement keys, each with nonnegative integer `known` and `unknown` observation counts. Skills contain at most128 exact `{name,trigger,harness}` entries; triggers are model, typed or mention. Price estimate basis contains exactly `sourceUrl`, `checkedAt`, `priceDigest`, `currency`, `model` and accompanies the API-equivalent estimate. `costUsd` means reported charge. Organization subscription fees are separate verified policy/account facts, never an invented per-task charge.
|
|
23
|
+
|
|
24
|
+
## Excluded from reports and basic diagnostics
|
|
25
|
+
|
|
26
|
+
Hostnames, local run/session/capture IDs, filesystem/worktree paths, credentials, prompts, conversations, file contents, raw tool input/output, argv, stdout/stderr and freeform diagnostic text never enter reports. The producer may reduce structured execution output to counters transiently; it does not persist raw output as diagnostics. Legacy hook capture does not read a caller-supplied transcript path by default.
|
|
27
|
+
|
|
28
|
+
Built-in Claude Code and Codex memory is excluded: no reads, imports, writes, generation, migration or fallback. Vendor hooks are integration points; VegaFactory owns its separately verified lesson records and selection. Existing vendor memory stores are not cleanup candidates.
|
|
29
|
+
|
|
30
|
+
Private recovery uses the existing closed recovery/acceptance/effect schemas. Original execution/account references, canonical approval source references and nullable recordBinding stay inside those typed private envelopes. They never become reporting fields through object copying. Hashes do not authorize exporting raw source, approval quotes, credentials or logs. Source checkpoints have their code repository's visibility, including public branches; a private recovery pointer does not make public source confidential.
|
|
31
|
+
|
|
32
|
+
## Delivery, local diagnostics and retention
|
|
33
|
+
|
|
34
|
+
`stats privacy --json` reports current mode, allowed fields, recipients, pending counts/bytes/age, diagnostic bytes and real disk pressure. `stats export --output <file>` creates a new private scoped file and refuses an existing destination. It applies current policy and read scope; it does not acknowledge remote delivery or upgrade historical non-attributed reports.
|
|
35
|
+
|
|
36
|
+
Basic local diagnostic directories use0700 and files0600. Their closed records contain event/time, stable reason codes and observed exits; raw log or transcript capture is outside this profile. Durable terminal state and pending capture remain visible after storage failure.
|
|
37
|
+
|
|
38
|
+
`stats cleanup --dry-run` previews the same local selector used by `--apply` and automatic maintenance. Inactive basic logs expire after14days; acknowledged active report payloads expire after12calendar months from original report observation, with month-end/leap-year clamping. Every candidate is enumerated again under the existing owned guard before removal. Active, undelivered, ambiguous, quarantined, recovery-dependent or unknown references are held. Capture mappings, delivery receipts, attempted hashes, minimal dedup identity, active authority evidence, source checkpoints, branches, worktrees, code, credentials and native memory are not expired by this selector.
|
|
39
|
+
|
|
40
|
+
Shared active-file removal uses the existing dedicated Git writer, a fresh validated destination/policy, the original acknowledged bytes and a private durable removal intent. Only actual remote absent-path readback permits local payload retirement. Its private removal receipt is separate from the original delivery receipt; deletion never becomes a new reporting acknowledgment. Missing authority, active references, changed remote bytes and unconfirmed pushes remain held/pending. Cleanup does not erase Git history, clones or platform metadata.
|
|
41
|
+
|
|
42
|
+
Delivery reconciliation checks historical attempted bytes before applying stricter current policy. Proven previous delivery keeps its real receipt and original policy digest; only truly undelivered bytes can be serialized again. A suppressed event receives a private policy-suppressed disposition, never a fabricated remote acknowledgment. Legacy migration previews exact original bytes, requires explicit apply and destination mapping, and preserves original files privately. It never retroactively attributes a historical non-attributed report.
|
|
43
|
+
|
|
44
|
+
Real filesystem free space below1GiB pauses new launches; capacity resumes at2GiB. A failed probe is unavailable and refuses launch. Pending spool at1GiB warns but does not independently stop work while capacity is safe. Running owned processes use the existing bounded stop protocol on pressure. This reserves shutdown/capture headroom; it cannot prevent another process from exhausting the disk. No automatic code/worktree/credential deletion is authorized to create space.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
Snippets the org prefers over a skill's own defaults. dev-setup reads this directory before falling back to what it ships.
|
|
4
|
+
|
|
5
|
+
- `hooks/` — hook wiring snippets per harness (ship guard, SessionStart context, Stop heartbeat, decision nudge).
|
|
6
|
+
- `factory-board.yml` — the board-mirror workflow a registered repo receives.
|
|
7
|
+
- `dev-md/` — dev.md section overrides: a file named after a section replaces that section's default text for every repo in the org.
|
|
8
|
+
|
|
9
|
+
A template here is a default, not a law: a repo may hand-edit what it received, and the precedence rule says the hand edit wins.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# The control room
|
|
2
|
+
|
|
3
|
+
The org's `vegafactory-control-room` repository: what each file holds, which file wins when two disagree, and how a run reads it. `vegafactory-setup` seeds every file here from `assets/control-room/*.template`; `dev-setup` reads them before it asks a repo anything.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
org.md global only: org name, goals, what applies to everyone (questionnaire)
|
|
9
|
+
people.csv login,name,role,slack,timezone,groups
|
|
10
|
+
decisions.md org-level register (same line format as repos)
|
|
11
|
+
groups/<g>/group.md department defaults: one line per knob a group can decide for a repo dev.md
|
|
12
|
+
groups/<g>/people.csv group-level people (adds to / overrides org)
|
|
13
|
+
groups/<g>/decisions.md group-level register
|
|
14
|
+
repos.md registry: repo, group, board, owner (maintained by this skill)
|
|
15
|
+
boards.md project boards and repo -> board mapping
|
|
16
|
+
rules/ org-wide review known-patterns, security rules, CODEOWNERS pattern
|
|
17
|
+
onboarding/new-repo.md checklist run by vegafactory-setup, then dev-setup
|
|
18
|
+
onboarding/new-teammate.md gh auth, harness install, skills install, control-room access, Slack
|
|
19
|
+
templates/ hook wiring snippets, board workflow, dev.md section overrides
|
|
20
|
+
stats/<owner>__<name>/<MON-YYYY>/<hostname>.jsonl one record per run or session, written by automation
|
|
21
|
+
stats/<owner>__<name>/<MON-YYYY>.summary.json regenerated per repo per month
|
|
22
|
+
stats/<owner>__<name>/<MON-YYYY>.timeline.json regenerated: the month's issue label timelines, read through gh at rollup
|
|
23
|
+
stats/org/<MON-YYYY>.summary.json regenerated across every repo
|
|
24
|
+
stats/org/<MON-YYYY>.skills.json regenerated: invocations per skill
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`stats/` is the one tree automation writes, and the shape is the reason it can. One file per repo, per month, per **machine** means two machines never touch the same file, so a concurrent push is a non-fast-forward — solved by `pull --rebase` and a retry — and never a content conflict needing a human. The repo segment is `<owner>__<name>` so a path stays two levels deep and a repo name can never be mistaken for a month directory. The three summaries are **regenerated**, never appended: a summary that accumulated would drift the first time a record arrived late from a machine that was offline. Records are counts and identifiers only — never prompt text, assistant text, tool arguments, or file contents — and `rules/stats-privacy.md` is where that promise is written down for everyone the org onboards.
|
|
28
|
+
|
|
29
|
+
`groups/dev/` is the only department seeded today; another department is a new `groups/<g>/` with the same three files.
|
|
30
|
+
|
|
31
|
+
## Effective policy
|
|
32
|
+
|
|
33
|
+
Resolve Markdown through dev-setup's `scripts/effective-policy.mjs`. Ordinary explicit values inherit org → group → repo; each harness stage inherits individually. Organization locks require exact organization delegation before a group or repo can change them. Repository `dispatch: local` remains an explicit local opt-in. Repository commands and Ship/Environments lines stay repository facts, not inherited executable instructions. Decision registers concatenate; a lesson or register entry grants no authority.
|
|
34
|
+
|
|
35
|
+
Use `policy-schema: 2` and one `vsk-policy` fenced JSON object in `org.md`. Its `schemaVersion` is2, with `locked` and `delegations` as shown in the org template. Lockable keys are `stats`, `stats-export`, `gates`, `tests`, `review`, `provider-mode`, `learning`, `learning-adoption`. A delegation names exact groups, canonical repositories and allowed values; wildcards and delegation chains refuse. Attributed reporting requires explicit org authorization. Unknown extension fields remain inert; duplicate keys, bad known values or an unknown schema refuse rather than overwrite.
|
|
36
|
+
|
|
37
|
+
Legacy version1 ordinary knobs remain readable. An org `stats-override: locked` locks its explicit `stats` value; without that value migration refuses. A group's `stats-override: allowed` is not org delegation. Inspect old/effective/proposed values and sources, retain original files, and approve the concrete authority-changing diff before migration. Other organizations confirm their own quality, reporting and supported subscription harness choices; templates do not select models for them.
|
|
38
|
+
|
|
39
|
+
## What each file may and may not carry
|
|
40
|
+
|
|
41
|
+
- `org.md` holds organization policy and stage defaults: the org name, the goals in one paragraph, and what applies to everyone — language, the date format, the "nothing ships without the operator's instruction" stance, and the statistics policy lines `stats:`, `stats-people:`, `stats-override:`. Groups may override ordinary org defaults; mandatory constraints and all administration assignments remain org-owned.
|
|
42
|
+
- `org.md`'s `## Automation identity` block records the org's GitHub App by name, five lines and no more: `app:` the App name, `app-slug:` the slug the actor string and the install URL both follow, `app-install:` the installation id from `gh api orgs/<org>/installations`, `app-secrets:` the two secret **names**, and `app-permissions:` the granted set. The permission table, the mint recipe, rotation and the kill switch live in dev-setup's `references/github-app.md` and are never restated here.
|
|
43
|
+
- `groups/<g>/group.md` carries one default for every knob a group can decide for a `.vegastack/dev.md`, in the same line shape dev.md uses (`harness-policy:` is one line, never six `harness:` lines — the dispatcher reads both files with one parser), so a repo that answers nothing else still gets a complete profile; per-repo facts (`repo:`, `skill-scan:`, `board:`, `control-room:`, detected types and fields) have no group default.
|
|
44
|
+
- `repos.md` and `boards.md` are registries, written when a repo is registered or a board is linked, never hand-curated in parallel with them.
|
|
45
|
+
- **Nothing secret goes in any file — names of secrets only.** A control room is readable by everyone the org onboards, and a name (`NPM_TOKEN`, `CLOUDFLARE_API_TOKEN`) is all a runbook needs; the value lives in the secret store the name points at.
|
|
46
|
+
- Preserve a confirmed optional decline as declined. Keep required unknown fields explicit and resume only those questions; show contradictions with a concrete example before writing. Agent-guided setup prepares a complete scoped diff, preserves unrelated fields and reads back the delivered files.
|
|
47
|
+
|
|
48
|
+
## The read path
|
|
49
|
+
|
|
50
|
+
Read a validated immutable control-room snapshot and retain its full source commit. A configured room whose mandatory policy is unavailable, malformed or expired blocks new tasks and external actions. The selected maximum age is an organization choice; a7200-second policy allows age7199 and refuses age7200. Failed fetches never renew validation time. An already-running job may finish reversible local work under pinned policy; pending external delivery revalidates authority. Optional knowledge may remain readable with a stale label and no privilege.
|
|
51
|
+
|
|
52
|
+
With no room configured, explicit local repository policy still works. Guided first setup may prepare missing answers while access is unavailable, but does not claim unattended readiness. Bootstrap records the verified room repository/remote/branch and local config path; local coordinates never appoint admins or enroll machines. Snapshot persistence, verified same-commit refresh and restore are the sync owner's contract.
|
|
53
|
+
|
|
54
|
+
## `people.csv`
|
|
55
|
+
|
|
56
|
+
The header line is exactly:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
login,name,role,slack,timezone,groups
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`login` is the GitHub username and the row's identity. A row in `groups/<g>/people.csv` with a `login` already present at org level **overrides** that row for that group; a `login` not present at org level **adds** a person to the group. `groups` on an org row is the comma-free list of the groups the person belongs to (use `;` between group names, since the file is comma-separated).
|
|
63
|
+
|
|
64
|
+
`role` is descriptive and recorded only on the operator's word. Neither a `lead` string nor a group row replacing an org row supplies admin authority. GitHub login keys are resolved against verified requester context and the current org admin map; execution-account identity stays separate.
|
|
65
|
+
|
|
66
|
+
## Boards
|
|
67
|
+
|
|
68
|
+
A board is created, field-configured and linked by the operator, never by an agent: **the operator runs these** commands, in this order — every one of them needs the `project` scope, which lives on a human token and never on an agent's:
|
|
69
|
+
|
|
70
|
+
1. `gh auth refresh -s project` — adds the scope to the operator's own `gh` login; without it every command below 403s.
|
|
71
|
+
2. `gh project create --owner <org> --title "<title>"` — note the number it prints; that number is the `board:` knob and the `number` column of `boards.md`.
|
|
72
|
+
3. `gh project field-list <n> --owner <org> --format json -q '.fields[] | select(.name=="Status") | .id'` — the id of the default Status field.
|
|
73
|
+
4. ``gh project field-delete --id FIELD_ID`` — use the field ID from step3; the default Status options are not the workflow's states.
|
|
74
|
+
5. `gh project field-create <n> --owner <org> --name Status --data-type SINGLE_SELECT --single-select-options "needs-operator,needs-plan,ready,working,for-operator,Done"` — the five state labels plus Done, in that order.
|
|
75
|
+
6. `gh project link <n> --owner <org> --repo <owner/repo>` — one call per repo that mirrors onto this board.
|
|
76
|
+
|
|
77
|
+
Then, in the project's Workflows UI, switch on the four built-in automations, which have no CLI: auto-add `is:issue is:open`, item closed → Done, PR merged → Done, and auto-archive after 14 days.
|
|
78
|
+
|
|
79
|
+
The mirror itself is one way. `.github/workflows/factory-board.yml` (dev-setup's `assets/factory-board.yml.template`) writes Status from the issue's single state label with the App token; nothing reads the board back, so a card dragged by hand is cosmetic until the next label change.
|
|
80
|
+
|
|
81
|
+
## Registers
|
|
82
|
+
|
|
83
|
+
`decisions.md` at every level uses the register line format defined in dev-setup's `references/conventions.md`, installed beside this file — one dated line per decision, append-only, no other metadata. This file does not restate the format; read it there.
|
|
84
|
+
|
|
85
|
+
## Administration and people visibility
|
|
86
|
+
|
|
87
|
+
The org policy object may carry `administration:{orgAdmins:string[],groupAdmins:Record<string,string[]>,groupAdminCapabilities:Record<string,GroupCapability[]>}`. At least one confirmed org admin is required when configured. Missing legacy administration remains unconfigured until reviewed migration; do not promote legacy leads. `GroupCapability` is `group.members.manage`, `group.repos.manage`, `group.defaults.manage` or `group.people.read`. Only org admins appoint/remove admins. Group admins act only inside assigned groups, on preauthorized repo registrations and permitted ordinary/delegated defaults. Membership edits do not grant GitHub access, operator status or shipping permission.
|
|
88
|
+
|
|
89
|
+
For chat requests, load the previous trusted config and verified human requester, prepare the exact target/diff, then use `authorizeAdministration` before applying configured Git review/delivery rules. A bot can execute an evidenced instruction but cannot supply the human grant. Refuse chat/URL identity claims, self-grants, cross-group targets, last-admin removal and stale authority. Dashboard remains read-only.
|
|
90
|
+
|
|
91
|
+
`resolveAdministration({orgLayer,peopleByScope,repoGroups})` reads only org assignments; `authorizeAdministration({actor,action,target,administration,policy})` returns allowed/reason. `actor` is `{login,verified:true}` from trusted GitHub context, optionally with separate execution-account evidence. Targets name the exact org/group/repo; proposed settings are `target.changes`, and admin replacement is `target.proposedAdministration`. These APIs are cooperative trusted-host checks, not a new authentication server.
|
|
92
|
+
|
|
93
|
+
`resolvePeopleReadScope({viewer,subject,requestedRepos,administration,policy,repoGroups})` returns allowedRepos/subject/refusal. Org admins read registered org repos; group admins need `group.people.read` in their assigned groups; people retain their own-data view. Filter records before totals, drill-downs or export. An empty allowedRepos array means no records. One person working in two groups does not let a group admin see the other group's records. Query filters may narrow but never expand scope. Control-room Git readers can still read committed report files; application scopes do not promise per-group storage secrecy.
|
|
94
|
+
|
|
95
|
+
## Registered machines
|
|
96
|
+
|
|
97
|
+
The org policy may carry `fleet:{schemaVersion:1,coordination,defaults,groupDefaults,groupDelegations,machines}`. Coordination names the verified private state repository node ID, canonical repository, branch, rootCommit and installation UUID. It is separate from the policy branch and source task branches. Organization admins own coordination identity and enrollment; setup preserves existing registrations and initially enrolls a machine disabled.
|
|
98
|
+
|
|
99
|
+
`FleetDefaults={pollSeconds,maxRuns,childConcurrent,checkpoints,recovery}`. Suggested selected defaults are120/1/3/task-branch/verified-transfer. Poll seconds must be an integer30–3600, maxRuns a positive safe integer, childConcurrent1–16 (also bounded by the installation's qualified child ceiling), checkpoints `off|task-branch`, recovery `original-host|verified-transfer`. Resolve org defaults → group defaults → explicit machine overrides. Polling is discovery timing; policy freshness and task duration are separate. Ordinary tasks have no cumulative elapsed-time limit.
|
|
100
|
+
|
|
101
|
+
Each machines key matches `[a-z0-9][a-z0-9-]{0,63}` and contains `{installationId,hostBindingDigest,executionLogin,group,repositories,enabled,overrides}`. Installation IDs are generated UUIDs, host bindings are digests, executionLogin is a confirmed GitHub login, and repositories are canonical registrations backed by verified GitHub node IDs. Credentials, raw host identifiers, shell commands and local paths stay outside this schema. A copied local config cannot match another host's binding or silently enroll it.
|
|
102
|
+
|
|
103
|
+
`groupDelegations` maps each group to `{fields,maxRunsMax?,childConcurrentMax?,pollSecondsMin?,pollSecondsMax?,checkpointValues?,recoveryValues?}`. Fields name permitted FleetDefaults keys; numeric limits remain inside schema bounds and enum subsets are valid/nonempty. No entry or field permission means org-admin-only. Group admins also need `group.defaults.manage`, and every edit uses the previous trusted delegation/current machine group. Changing repo/group scope, binding, enrollment, coordination or delegation is org-admin-only. Safety predicates cannot be delegated away.
|
|
104
|
+
|
|
105
|
+
`resolveMachinePolicy({policy,machineId,installationId,hostBindingDigest,executionLogin})` returns ok/machine/blocks. The effective machine includes coordination, resolved defaults, allowedRepositories, repositoryIds and policyDigest. Allowed work intersects registration, current policy/approval and verified GitHub access. A shared/enrolled machine never falls back to local-only locks on failure; no-fleet installations retain an explicit legacy mode.
|
|
106
|
+
|
|
107
|
+
Recovery `verified-transfer` still requires proof the original execution stopped, a verified checkpoint and task/scope/base/head, reconciled effects, safe shared ownership transfer and the same qualified harness/model/account/effort. A stale heartbeat is not stop proof. Task-branch checkpoints require the approved exact repo/ref/file scope and durable checked delivery intent; they grant no merge/release or arbitrary write authority. Runtime ownership/checkpoint machinery and actual service qualification are separate consumers of these settings.
|
|
108
|
+
|
|
109
|
+
## Resolver input and source contract
|
|
110
|
+
|
|
111
|
+
`resolvePolicy({org,group,repo,identity,freshness})` returns `{ok,policy,blocks}`; all three layers are Markdown strings. `identity` supplies `org`, canonical `repo`, `group`, full validated `roomSha`, optional per-layer `paths`, and confirmed `peopleByScope`, `repoGroups`, `repositoryIds`. People scopes map `org`/group IDs to `{login,groups:[]}` rows; repoGroups maps canonical repository to group; repositoryIds maps it to verified GitHub node ID. These are verified registry inputs, not fields a chat requester supplies.
|
|
112
|
+
|
|
113
|
+
`freshness` supplies configured/validatedAt/now/maxAgeSeconds. Effective schema2 includes resolved values, per-key scope/path/revision diagnostics, administration, fleet and policyDigest. Revisions are full Git SHAs for validated room sources or SHA256 of exact local text. The digest sorts resolved values/sources and authority/registry data and excludes observation time. Consumers must inspect `ok` or refusal before any effect: an effective locked value is useful diagnostic data even when an attempted override is denied.
|
|
114
|
+
|
|
115
|
+
Validated snapshot readers consume `factory.json` at `controlRooms[org].snapshots[canonicalCodeRepo]`. Each value keeps `{schemaVersion:2,org,group,repository,origin,sourceCommit,policyDigest,validatedAt,contentPath}`; repository is the control room, while the map key binds the code repo. Its digest is the full resolved policy for that repo/profile/group, with canonical relative paths. The reader checks exact origin/HEAD and clean content, reads regular blobs from the recorded Git commit, then recomputes the digest. Changed local policy needs renewed validation. The optional `repository-id` column in repos.md supplies confirmed GitHub node IDs required by fleet registrations. The snapshot owner verifies those IDs during publication; this parser does not turn authored strings into verified network identity.
|
|
116
|
+
|
|
117
|
+
## Local settings, refresh and recovery
|
|
118
|
+
|
|
119
|
+
`factory.json` is the single machine-local store. Its supported wire shape is `{schemaVersion:2,revision,controlRooms:{[org]:...},...extensions}`. The transaction API's `orgs` is a view of `controlRooms`, never a second file/map; an existing extension named `orgs` stays inert. Persist confirmed setup answers, optional declines, bootstrap and verified local checkout registrations through `updateSettings(root,mutate)` before attempting sync. `root` contains `factory.json`; services using a different absolute config path call `updateSettingsAtPath(path,mutate)` and pass that same path to readers and refresh. Neither API enrolls the machine or approves Git delivery.
|
|
120
|
+
|
|
121
|
+
Every mutation rereads under the canonical path's exclusive guard and increments revision. Schema1 converts only after successful mutation/validation, retaining its original bytes in `factory.json.schema1.bak`. Unknown versions, unreadable files and unsafe symlink paths refuse unchanged. An interrupted `.guard` directory is never stolen because its owner appears old; stop participating writers, verify their termination and inspect the owner record before offline recovery. A text editor bypassing this transaction cannot receive its concurrent lost-update guarantee.
|
|
122
|
+
|
|
123
|
+
`vegafactory sync --dry-run --json` describes refresh/migration without fetching or writing. A real sync verifies the configured connection, fetches a managed candidate (30 seconds per fetch, at most two attempts, 90 seconds for candidate work), validates every configured code-repository profile through the canonical resolver, then publishes all bindings together. Same-commit refresh renews `validatedAt` only after successful fetch and validation. A failed attempt retains last-good source identity and settings. Unconfigured first setup must complete a confirmed code-repository profile before it can publish authority; answers already persisted remain resumable.
|
|
124
|
+
|
|
125
|
+
Policy reader content lives under the settings directory's `policy-snapshots/<org>/snapshot-*`. The separate `controlRooms[org].path` is the telemetry writer checkout, initialized once from validated content; existing operator edits and unpushed commits are never reset or repointed. Do not write telemetry into `contentPath`. Canonical GitHub owner/name and repository node ID must match the verified connection; a rename needs explicit verified reconciliation. Enrolled machines additionally match the current host binding, installation, account, group and registry scope. Host bindings come from the canonical machine-identity reader, using its versioned platform-separated digest of the validated machine identifier; account identity is checked separately. Copying factory.json to another host is not enrollment.
|
|
126
|
+
|
|
127
|
+
`status --json` exposes each repo's validation state, full source SHA, policy digest, timestamp, age and refusal. Machine configuration displayed by status is diagnostic, not verified execution-account authority. Dashboard policy reads the same manifest and local profiles; legacy fetch time or directory mtime cannot manufacture freshness. Optional old knowledge carries source/date and a warning; it grants no authority. At the selected two-hour bound, age7199 seconds is fresh and age7200 is stale. Dispatcher polling remains distinct from this bound; running reversible work retains its pinned rules and external actions revalidate.
|
|
128
|
+
|
|
129
|
+
The source APIs `inspectSnapshots({target,now})` and `restoreSnapshot({target,index,now,apply?})` verify supported schema, exact source/content identity and every backup's per-repo digest. Restore defaults to dry-run. Explicit `apply:true` selects inactive recovery content with its original timestamp and empties the authoritative snapshot map. A successful real sync is required before authority resumes, including when the selected backup was recently validated. Two prior valid pointer sets are retained; immutable directories are not automatically removed, so older active-run pins remain available. Failed candidate directories may remain for inspection.
|
|
130
|
+
|
|
131
|
+
Until a packaged recovery entrypoint is approved and integrated, these are source-only recovery APIs, not installed CLI subcommands. From the source checkout, inspect the exact configured path without writes:
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
VF_SETTINGS_PATH=/absolute/path/factory.json VF_REPO_PATH=/absolute/path/code-repo bun --eval '
|
|
135
|
+
import {readFile} from "node:fs/promises";
|
|
136
|
+
import {homedir} from "node:os";
|
|
137
|
+
import {join} from "node:path";
|
|
138
|
+
import {readSettingsFile} from "./packages/cli/src/control-room.ts";
|
|
139
|
+
import {resolveTarget,inspectSnapshots} from "./packages/cli/src/sync.ts";
|
|
140
|
+
const settingsPath=process.env.VF_SETTINGS_PATH, repoPath=process.env.VF_REPO_PATH;
|
|
141
|
+
const config=await readSettingsFile(settingsPath);
|
|
142
|
+
const devMdText=await readFile(join(repoPath,".vegastack/dev.md"),"utf8");
|
|
143
|
+
const target=resolveTarget({config,devMdText,home:homedir(),settingsPath,repoPath});
|
|
144
|
+
if(!target) throw new Error("No configured control room");
|
|
145
|
+
console.log(JSON.stringify(await inspectSnapshots({target,now:Date.now()}),null,2));
|
|
146
|
+
'
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For a reviewed restoration, use the same resolved target and call `restoreSnapshot({target,index:0,now:Date.now()})` first. Inspect that exact result before explicitly adding `apply:true`; never alter `validatedAt` to bypass the required fresh sync. Packaged recovery availability and final behavioral/provider qualification remain open integration gates.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Workflow conventions
|
|
2
|
+
|
|
3
|
+
Artifact authority.
|
|
4
|
+
|
|
5
|
+
Defaults resolve repo, group, then org; locks require explicit org delegation. Repository dispatch/commands never inherit; registers concatenate. Policy/migration uses dev-setup's `scripts/effective-policy.mjs` and vegafactory-setup's control-room reference.
|
|
6
|
+
|
|
7
|
+
## Comment metadata markers
|
|
8
|
+
|
|
9
|
+
Comments open:
|
|
10
|
+
|
|
11
|
+
```markdown
|
|
12
|
+
<!-- vsk:v1 type=<type> rev=<n> [key=value ...] -->
|
|
13
|
+
## <Human title> (v<n>)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| type | required keys | instances |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `approval` | `scope=<brief\|brief+plan\|plan\|consolidated\|none>` and schema-v2 JSON | one per approval event |
|
|
19
|
+
| `questions` | `rev` | one per ask round; earlier rounds stay as record (dev-setup's `references/ask-route.md`) |
|
|
20
|
+
| `plan` | `rev` | one, edited in place |
|
|
21
|
+
| `ledger` | `branch` | one, edited in place |
|
|
22
|
+
| `evidence` | `rev branch sha` | one, edited in place |
|
|
23
|
+
| `review` | `round sha agent=<claude\|codex> verdict=<clean\|needs-fixes>` | one per review cycle, rounds appended inside |
|
|
24
|
+
| `decision` | — | one per decision proposal |
|
|
25
|
+
| `handback` | — | one per stop event |
|
|
26
|
+
|
|
27
|
+
`rev=<n>` and `(v<n>)` start at 1 only on brief, plan, questions and evidence; other types have neither. Locate by marker, never heading/legacy fallback.
|
|
28
|
+
|
|
29
|
+
## Operator identity
|
|
30
|
+
|
|
31
|
+
Use parenthesized GitHub usernames:
|
|
32
|
+
|
|
33
|
+
- Approval: `Approved by (<username>) on DD-MM-YYYY: "<their words>"`
|
|
34
|
+
- Register line: `- DD-MM-YYYY (<username>) — <decision>`
|
|
35
|
+
|
|
36
|
+
Approval.mjs’s publisher/relay contract lets current-policy provider-envelope publishers attest listed operators’ session words. Other recorders may only relay independently read identical operator-published scoped grants within complete authority history, without lifecycle mutations. Relays inherit source authority/lifecycle; account attestation cannot authenticate off-platform speech.
|
|
37
|
+
|
|
38
|
+
## Scoped approval records
|
|
39
|
+
|
|
40
|
+
Use only dev-implement’s `scripts/lib/approval.mjs` and follow its contract. Refresh current policy and complete GitHub histories. `ArtifactRef={repo,issue,kind,artifactId,rev,digest}` binds brief issue-node or unique plan/protocol comment-node identity, revision and canonical SHA-256.
|
|
41
|
+
|
|
42
|
+
Post exactly one approval comment: matching scope marker, then one fenced JSON `ApprovalRecord={schemaVersion:2,id,operator,scope,source:{kind,ref,quote},artifacts,supersedes,revokes}`. Exclude outer Markdown fences, future alternatives and unresolved source locators; validate the whole body with approval.mjs's `parseApproval`. Source kind is `session` or `github-comment`, with inspectable words. Reuse valid current grants/relays; avoid counterfactual plan-only or redundant approvals. Scope is `brief`, `plan` or `brief+plan`; planning requires brief, implementation both, research execution also its protocol. Empty-artifact revocations remove exact earlier IDs. Conflicts explicitly supersede; newest never wins.
|
|
43
|
+
|
|
44
|
+
Preserve legacy comments. Without writes, inventory refusals/current digests and request reconfirmation. For duplicate canonical plans preserve both identities/bodies and request record-preserving reconciliation; never delete to clear ambiguity. Follow approval.mjs’s exact correction schema, operator-publisher and target checks. Only malformed or demonstrably invalid-source targets qualify, never valid authority or unavailable/inconsistent facts. Resolve source facts first; corrections grant no scope. Exact child checkpoint actions bind one selected code child's branch/ref/base/tasks/files; other actions never substitute.
|
|
45
|
+
|
|
46
|
+
Consolidated parent events bind frozen manifests, canonical artifacts and exact task/action subsets. Use inline UTF-8 or immutable repository/commit/path plus blob hash, never local paths. Canonical `approvalBindings` authorize; requested `recordBinding` only audits. Follow approval.mjs’s preparation/research/recovery provenance, receipts, adapters, counted attempts and fresh admission; retain immutable history and unverified legacy records. Keep checkpoint/private/live/shipping gates separate.
|
|
47
|
+
|
|
48
|
+
Canonicalization normalizes CRLF; its only exceptions are structural plan checkboxes and one validated JSON `{tasks:[{id,evidenceUrls}]}` block between `<!-- vsk:progress:start -->` / `<!-- vsk:progress:end -->`. IDs must exist; URLs are HTTP(S); unknown fields/duplicates refuse. Stable task IDs/order, interfaces, actions, revisions and all other bytes remain scope. Brief/protocol bodies have no mutable fields; fenced examples stay immutable and grant no authority.
|
|
49
|
+
|
|
50
|
+
## Revision markers
|
|
51
|
+
|
|
52
|
+
Scope edits increment marker/heading revisions and append `Revisions: v2 — DD-MM-YYYY: <change>, per (<username>) correction`; preserve earlier lines and obtain fresh approval. Validated progress changes need neither.
|
|
53
|
+
|
|
54
|
+
## Scope classes
|
|
55
|
+
|
|
56
|
+
Intake explains scope; operator overrides:
|
|
57
|
+
|
|
58
|
+
- **`research`** — inquiry; throwaway code allowed, never merged. No branch/PR/changelog; evidence comment contains findings and recommendation.
|
|
59
|
+
- **`quick-build`** — existing flow: draft brief+plan together, approve both, then `ready`.
|
|
60
|
+
- **`full-plan`** — new ground: approve brief, `needs-plan`, separate grounded planning session, `needs-operator`, approve plan, `ready`. Split multiple deliverables into independently classified epic children.
|
|
61
|
+
|
|
62
|
+
Scope ratchet: `dev-plan`.
|
|
63
|
+
|
|
64
|
+
## Labels
|
|
65
|
+
|
|
66
|
+
One state; flips set assignees (colors: dev-setup):
|
|
67
|
+
|
|
68
|
+
| label | meaning | assignee |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `needs-operator` | question, brief or plan approval, proposal | the operator |
|
|
71
|
+
| `needs-plan` | brief approved; awaiting planning (full-plan only) | the operator |
|
|
72
|
+
| `ready` | approved — an agent may start | nobody |
|
|
73
|
+
| `working` | claimed; ledger shows live progress | the runner |
|
|
74
|
+
| `for-operator` | done — evidence posted, awaiting operator review | the operator |
|
|
75
|
+
|
|
76
|
+
Modifiers coexist with state: `risky` · scope `research` / `quick-build` / `full-plan` · `epic` (map parents without a native Epic type). Boards mirror states one-way.
|
|
77
|
+
|
|
78
|
+
## Titles, types, hierarchy
|
|
79
|
+
|
|
80
|
+
- **Title prefixes:** issues, branches and PRs use dev.md's `branch:` types plus `research:`; PR title = issue title.
|
|
81
|
+
- **Native issue types/fields:** Feature (feat) · Bug (fix) · Task (docs/chore/refactor/research) · Epic for parents (else label); intake sets Priority/Effort. Scope classes stay labels.
|
|
82
|
+
- **Hierarchy:** epic parent = map only (Destination · Decisions so far · Not clear yet · Out of scope), with native child sub-issues. Issues are work units (brief, approvals, branch, PR, evidence); tasks are checkboxes **only in the plan comment**. Blockers use dependencies; phases use milestones. Only non-epic issues get `ready`.
|
|
83
|
+
|
|
84
|
+
## The ledger
|
|
85
|
+
|
|
86
|
+
One implementation ledger:
|
|
87
|
+
|
|
88
|
+
```markdown
|
|
89
|
+
<!-- vsk:v1 type=ledger branch=<branch> -->
|
|
90
|
+
## Ledger — <branch>
|
|
91
|
+
- <issue>-T<N>: complete (commits <base7>..<head7>[, review clean | K parked])
|
|
92
|
+
- <issue>-T<N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a>..<b>)
|
|
93
|
+
- Ruling: <what> — <why> — cost if wrong: <cost>
|
|
94
|
+
- <issue>-T<N>: parked — <finding> — Ruling: <why the code stands>
|
|
95
|
+
- Deferred minor: <one-liner>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
**Resume protocol:** brief → plan comment → ledger → `git log`; then reconcile task IDs, canonical approval history, edited authority, source/evidence, ownership and delivery effects. Preserve completed work/provenance; stale heartbeat is not stop proof. Preparation never implies issue completion. Dev-implement's ledger reference owns recovery detail.
|
|
100
|
+
|
|
101
|
+
## `.vegastack/` workspaces
|
|
102
|
+
|
|
103
|
+
Drafts/reports: `.vegastack/.tmp/<issue-number>-<title-slug>/` (pre-issue: `intake-<slug>`), self-ignored by a `.gitignore` containing `*`. Branch checkouts: root-ignored `.vegastack/.worktrees/<issue-number>-<title-slug>/`; main stays on its default branch. Keep both outside `.git/`. Subagents save full reports and return short status. `<path-to-this-skill>` means SKILL.md’s directory.
|
|
104
|
+
|
|
105
|
+
## Verification gate
|
|
106
|
+
|
|
107
|
+
Prove claims with fresh command output and exit codes; report failures and skips. Delegate only substantial independent parallel work, never your own verification; keep spawn counts low. Guards block machine-verifiable failures (exit 2); heuristics warn. Guards contain no AI inference; unverifiable state fails closed.
|
|
108
|
+
|
|
109
|
+
## Review bindings
|
|
110
|
+
|
|
111
|
+
One fenced JSON each: `{"reviewBinding":{sha,baseSha,scopeDigest,verdict,findings:[{id,status}]}}` in review; `{"adjudication":{sha,reviewCommentId,operator,source:{kind,ref,quote},findings:[{id,disposition,reason}]}}` in evidence. Use full commit IDs and canonical-plan scopeDigest; status=open/resolved; disposition=accept-risk. Every open finding requires same-review operator acceptance. dev-ship’s README defines source checks. No prose exceptions.
|
|
112
|
+
|
|
113
|
+
Communicate starts/findings/direction plainly; self-contained outcomes include paths and remaining checks. Avoid invented labels/arrows; visualize usefully. Challenge ambiguity with options; never guess silently.
|