feat(skills): push state read from facts, never pushed by the skills
Run C2 of manual-push mode (BDR-111/BDR-112). The four flows that pushed on their own, or claimed the branch was on origin, now read the truth after the fact and hand the user the exact command: - client-handover-writer: the "Push to origin now?" question and its push block are gone (the hooks had already pushed in auto-push mode; push-guard denies it in manual mode). A reusable PUSH STATE READ (branch, origin probe, `git rev-list --count origin/<br>..<br>`, the verb only to word the reason) runs after commit-change, at the top of the deploy pause, after "Deployed" and before each end report. The branch name is validated against an allowlist before it is placed in any command or hint (a hostile branch name is otherwise a shell injection). Pending → the user pushes BEFORE the deploy pause; the deploy brief says "after your push". `Push:` line in both reports. - release-candidate STEP 6: two ahead counts + the verb; anything other than auto with both counts 0 prints one user command `! git push --atomic origin main develop v<X.Y.Z>` and stops; the tag gate stays for auto mode; `hold` notes --follow-tags; version regex. - release-executor: push claims qualified (auto-push mode, best effort). - tour: mode-agnostic rule; STEP 3 reads one `git -C <project>` fact per project (suffix-aware branch, --remotes=origin, origin probe) and the summary row says on origin / local only with the user command.
This commit is contained in:
@@ -62,7 +62,7 @@ and degrading Google's NAP-consistency signal.
|
|||||||
Pipeline (each step gates the next):
|
Pipeline (each step gates the next):
|
||||||
1. Baseline audits: SEO+GEO and security hardening in parallel.
|
1. Baseline audits: SEO+GEO and security hardening in parallel.
|
||||||
2. Fix loops: apply each audit's bundle (AUTO items, ONE gate for GATED ones) and re-audit until ≥17/20 or `MAX_ITERATIONS` hit.
|
2. Fix loops: apply each audit's bundle (AUTO items, ONE gate for GATED ones) and re-audit until ≥17/20 or `MAX_ITERATIONS` hit.
|
||||||
3. Commit + push if files changed.
|
3. Commit if files changed (the hooks push in auto-push mode; the push state is read, never assumed).
|
||||||
4. Deploy pause: list deploy artifacts + process, wait for user confirmation.
|
4. Deploy pause: list deploy artifacts + process, wait for user confirmation.
|
||||||
5. Live-site validation against the deployed URL.
|
5. Live-site validation against the deployed URL.
|
||||||
6. Per-axis gate: every score ≥17/20 OR stop + roadmap.
|
6. Per-axis gate: every score ≥17/20 OR stop + roadmap.
|
||||||
@@ -567,40 +567,45 @@ If `PENDING_CHANGES` non-empty → invoke /commit-change skill via subagent:
|
|||||||
> commit). Use Conventional Commits format. After committing, return the
|
> commit). Use Conventional Commits format. After committing, return the
|
||||||
> SHA list."
|
> SHA list."
|
||||||
|
|
||||||
Then, **before pushing, STOP and ask for an explicit GO** — the push is an
|
**PUSH STATE READ.** Three separate Bash calls, never combined, read-only:
|
||||||
outward-facing action and never fires autonomously:
|
`git branch --show-current` → `<br>`;
|
||||||
|
`git remote get-url origin >/dev/null 2>&1 && echo origin || echo no-origin`;
|
||||||
|
`git rev-list --count origin/<br>..<br> 2>/dev/null || echo unknown` →
|
||||||
|
`ahead`. Validate `<br>` against `^[A-Za-z0-9._/-]+$` before using it
|
||||||
|
anywhere (git accepts shell metacharacters in branch names). On mismatch:
|
||||||
|
state = `unknown (branch name contains characters this pipeline refuses to
|
||||||
|
interpolate: push by hand after renaming the branch)`, interpolate NOTHING,
|
||||||
|
skip the rev-list and the verb. The validated `<br>` is the only name ever
|
||||||
|
placed in a `! git push -u origin <br>` hint (STEP 5, deploy brief,
|
||||||
|
reports); every re-run of PUSH STATE READ inherits this rule.
|
||||||
|
If `ahead` ≠ 0 and origin exists:
|
||||||
|
`bash "$HOME/.claude/lib/gitflow.sh" push-mode` → anything other than `auto`
|
||||||
|
is treated like `manual` (stderr line kept verbatim when `invalid`).
|
||||||
|
State, first match wins, in this order: (1) no commits were made this run
|
||||||
|
or the gitflow fallback left changes uncommitted →
|
||||||
|
`nothing to push (no commits this run)` / `uncommitted changes (no gitflow
|
||||||
|
model): publish by hand`, stop; (2) `<br>` invalid → the unknown state
|
||||||
|
above; (3) `no-origin` → `not on origin (no origin remote: add one first)`;
|
||||||
|
(4) `ahead` = 0 → `on origin`; (5) otherwise (`ahead` > 0 or `unknown`)
|
||||||
|
→ `pending — you: ! git push -u origin <br>` + reason: push mode `manual` →
|
||||||
|
`(manual push mode)`, `auto` → `(not on origin: no remote-tracking ref or
|
||||||
|
the hook push did not land)`, `invalid` → `(<verb stderr line verbatim>)`.
|
||||||
|
The pipeline never runs `git push` itself.
|
||||||
|
|
||||||
> AskUserQuestion — "Changes committed on `<CURRENT_BRANCH>`. Push to origin now?
|
`pending` → tell the user NOW: `Commits are local only. Push first:
|
||||||
> - A) Yes — push `<CURRENT_BRANCH>` to origin
|
! git push -u origin <br>`.
|
||||||
> - B) No — I'll push manually before confirming deploy"
|
|
||||||
|
|
||||||
Only on **A** run the push; on **B** skip it and note "push deferred to user"
|
> **Red flag — STOP:** never `git push` (the hooks push in auto-push mode;
|
||||||
in the STEP 8 summary, then continue.
|
> otherwise the user does); never `gitflow finish`/`merge`. This pipeline
|
||||||
|
> commits a working branch — it never integrates into a protected branch.
|
||||||
> **Red flag — STOP:** never `git push` without option-A GO; never
|
|
||||||
> `gitflow finish`/`merge`. This pipeline commits and (on GO) pushes a working
|
|
||||||
> branch — it never integrates into a protected branch.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
CURRENT_BRANCH=$(git branch --show-current)
|
|
||||||
git push origin "$CURRENT_BRANCH" 2>&1
|
|
||||||
```
|
|
||||||
|
|
||||||
If push fails (no remote, auth issue, conflict): capture error, report to
|
|
||||||
user via AskUserQuestion:
|
|
||||||
|
|
||||||
```
|
|
||||||
"Push failed: <error>. Pipeline needs the changes published before deploy.
|
|
||||||
Options:
|
|
||||||
- A) Retry push (after I fix it manually)
|
|
||||||
- B) Skip push — I'll publish manually before confirming deploy
|
|
||||||
- C) Abort pipeline"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## STEP 6 — DEPLOY PAUSE
|
## STEP 6 — DEPLOY PAUSE
|
||||||
|
|
||||||
|
Re-run PUSH STATE READ (every path reaches STEP 6, some without STEP 5's
|
||||||
|
read).
|
||||||
|
|
||||||
Skip if `PROJECT_TYPE != web` (non-web has no deploy-then-validate flow —
|
Skip if `PROJECT_TYPE != web` (non-web has no deploy-then-validate flow —
|
||||||
set `VALIDATE_SKIPPED=true` and jump to STEP 8).
|
set `VALIDATE_SKIPPED=true` and jump to STEP 8).
|
||||||
|
|
||||||
@@ -625,10 +630,15 @@ Commits added in this session:
|
|||||||
|
|
||||||
Tailor to project deploy method (use DEPLOY_HINTS):
|
Tailor to project deploy method (use DEPLOY_HINTS):
|
||||||
|
|
||||||
- **Vercel/Netlify/Cloudflare Pages auto-deploy from git**: "Push has been
|
When the state is `pending`, the brief OPENS with
|
||||||
done. The platform deploys automatically — usually 1-3 min. Watch the
|
`First push: ! git push -u origin <br>`. When `on origin`, keep "Push has
|
||||||
dashboard. Tell me when the new version is live."
|
been done. …".
|
||||||
- **GitHub Actions / GitLab CI**: "Workflow `<file>` should run on push.
|
|
||||||
|
- **Vercel/Netlify/Cloudflare Pages auto-deploy from git**: "The platform
|
||||||
|
deploys automatically after your push (a working branch gives a preview
|
||||||
|
at most; production builds from the production branch) — usually 1-3
|
||||||
|
min. Watch the dashboard. Tell me when the new version is live."
|
||||||
|
- **GitHub Actions / GitLab CI**: "Workflow `<file>` runs on your push.
|
||||||
Watch CI status. Tell me when it's green and live."
|
Watch CI status. Tell me when it's green and live."
|
||||||
- **Manual upload (FTP / SSH)**: "Upload these files to the server: `<list>`.
|
- **Manual upload (FTP / SSH)**: "Upload these files to the server: `<list>`.
|
||||||
If using rsync, here's a template: `rsync -avz dist/ user@server:/path`."
|
If using rsync, here's a template: `rsync -avz dist/ user@server:/path`."
|
||||||
@@ -650,6 +660,9 @@ AskUserQuestion:
|
|||||||
- C) Skip /web-validate — proceed to handover doc with VALIDATE marked SKIPPED
|
- C) Skip /web-validate — proceed to handover doc with VALIDATE marked SKIPPED
|
||||||
```
|
```
|
||||||
|
|
||||||
|
After option A "Deployed": re-run PUSH STATE READ; still `pending` → ask
|
||||||
|
again (the live site cannot hold these commits).
|
||||||
|
|
||||||
If A → proceed to STEP 7. If B → exit cleanly with state report. If C →
|
If A → proceed to STEP 7. If B → exit cleanly with state report. If C →
|
||||||
mark `VALIDATE_SKIPPED=true` and jump to STEP 8.
|
mark `VALIDATE_SKIPPED=true` and jump to STEP 8.
|
||||||
|
|
||||||
@@ -683,8 +696,8 @@ SCORE_VALIDATE_AFTER=$(extract_score .claude/audits/VALIDATE.md)
|
|||||||
Note: VALIDATE has no `_BEFORE` (first run is post-deploy). The before/after
|
Note: VALIDATE has no `_BEFORE` (first run is post-deploy). The before/after
|
||||||
table for VALIDATE shows `—` for before, `<score>` for after.
|
table for VALIDATE shows `—` for before, `<score>` for after.
|
||||||
|
|
||||||
If /web-validate produced new fixes in source code, run STEP 5 again (mini-commit
|
If /web-validate produced new fixes in source code, run STEP 5 again (mini-commit;
|
||||||
+ push) BEFORE moving to STEP 8 — but DO NOT loop /web-validate. The remaining
|
push state read, never assumed) BEFORE moving to STEP 8 — but DO NOT loop /web-validate. The remaining
|
||||||
deploy of those fixes is mentioned to the user in the final doc.
|
deploy of those fixes is mentioned to the user in the final doc.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -806,9 +819,14 @@ Below-threshold audits:
|
|||||||
Roadmap written to .claude/audits/HANDOVER-ROADMAP.md.
|
Roadmap written to .claude/audits/HANDOVER-ROADMAP.md.
|
||||||
Tasks appended to .claude/tasks/TODO.md.
|
Tasks appended to .claude/tasks/TODO.md.
|
||||||
|
|
||||||
|
Push: <state>
|
||||||
|
|
||||||
Resolve P0 items, then re-run /client-handover.
|
Resolve P0 items, then re-run /client-handover.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Re-run PUSH STATE READ right before printing this report (never reuse
|
||||||
|
the STEP 5 snapshot).
|
||||||
|
|
||||||
If `ALL_PASS = true` → proceed to STEP 9 (memory load + doc generation).
|
If `ALL_PASS = true` → proceed to STEP 9 (memory load + doc generation).
|
||||||
|
|
||||||
### Roadmap structure (when gate fails)
|
### Roadmap structure (when gate fails)
|
||||||
@@ -1170,9 +1188,13 @@ Parse the returned `HANDOVER-DOC REPORT`:
|
|||||||
- `STATUS: DONE` → report the `MD` / `HTML` / `PDF` paths to the user,
|
- `STATUS: DONE` → report the `MD` / `HTML` / `PDF` paths to the user,
|
||||||
plus the `GATES` line and any `NOTES` caveats (e.g. `[À COMPLÉTER]`
|
plus the `GATES` line and any `NOTES` caveats (e.g. `[À COMPLÉTER]`
|
||||||
markers left in NAP, deploy chapter included/skipped).
|
markers left in NAP, deploy chapter included/skipped).
|
||||||
|
Re-run PUSH STATE READ right before printing, then add the bullet:
|
||||||
|
- Push: <state>
|
||||||
- `STATUS: BLOCKED` → surface the report verbatim (including which
|
- `STATUS: BLOCKED` → surface the report verbatim (including which
|
||||||
PACKAGE field the doc-writer flagged) and stop — do not retry or
|
PACKAGE field the doc-writer flagged) and stop — do not retry or
|
||||||
patch the PACKAGE silently.
|
patch the PACKAGE silently. Re-run PUSH STATE READ and add the same
|
||||||
|
bullet:
|
||||||
|
- Push: <state>
|
||||||
|
|
||||||
In BOTH branches, then clean the transient draft:
|
In BOTH branches, then clean the transient draft:
|
||||||
`rm -f ".audit/handover-draft-${RUNID}.md"` (run-scoped, gitignored —
|
`rm -f ".audit/handover-draft-${RUNID}.md"` (run-scoped, gitignored —
|
||||||
|
|||||||
@@ -77,15 +77,17 @@ actual branch; never finish whatever happens to be checked out.
|
|||||||
output verbatim; do not attempt to resolve it yourself.
|
output verbatim; do not attempt to resolve it yourself.
|
||||||
2. **Tag AFTER finish, on `main`** — never before:
|
2. **Tag AFTER finish, on `main`** — never before:
|
||||||
`git tag -a v<X.Y.Z> main -m "release <X.Y.Z>"` (annotated, so it lands on
|
`git tag -a v<X.Y.Z> main -m "release <X.Y.Z>"` (annotated, so it lands on
|
||||||
main's release-merge commit). Finish has already pushed `main` and
|
main's release-merge commit). In auto-push mode finish pushes `main`
|
||||||
`develop` through the lib's hooks (BDR-095); the tag stays local until
|
and `develop` (best effort: the lib warns and returns 0 on a failed
|
||||||
the dispatcher's tag-push gate.
|
push; the dispatcher re-verifies with ahead counts) (BDR-095); in
|
||||||
|
manual push mode they stay local. The tag stays local until the
|
||||||
|
dispatcher's tag-push gate.
|
||||||
|
|
||||||
### Forbidden in this span
|
### Forbidden in this span
|
||||||
`git push` (any remote, any ref — `main`/`develop` ride the lib's hook
|
`git push` (any remote, any ref — `main`/`develop` ride the lib's
|
||||||
pushes during finish; the dispatcher owns the tag-push gate), deciding the
|
pushes during finish in auto-push mode; the dispatcher owns the tag-push
|
||||||
version number, the when-to-release decision, attribution trailers of any
|
gate), deciding the version number, the when-to-release decision,
|
||||||
kind.
|
attribution trailers of any kind.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ The agent runs a **ship-and-handover pipeline** with explicit gates:
|
|||||||
- Re-invoke the audit subagent in audit mode: it re-scores and returns the next FIX BUNDLE; it applies nothing (a dispatched child cannot hold a gate).
|
- Re-invoke the audit subagent in audit mode: it re-scores and returns the next FIX BUNDLE; it applies nothing (a dispatched child cannot hold a gate).
|
||||||
- Repeat up to `MAX_ITERATIONS` (default 5).
|
- Repeat up to `MAX_ITERATIONS` (default 5).
|
||||||
- If still < 17/20 after cap → escalate to user with concrete remaining issues; user decides continue / stop / manual intervention.
|
- If still < 17/20 after cap → escalate to user with concrete remaining issues; user decides continue / stop / manual intervention.
|
||||||
4. **COMMIT + PUSH** — If files changed during fix loops, run /commit-change (atomic logical commits) then `git push`.
|
4. **COMMIT + PUSH** — If files changed during fix loops, run /commit-change (atomic logical commits); the gitflow hooks push in auto-push mode, otherwise (manual push mode, or a hook push that failed) the agent tells the user to push with `! git push -u origin <branch>` BEFORE the deploy pause.
|
||||||
5. **DEPLOY PAUSE** — List exact deploy artifacts: changed files since baseline, deploy hints from project (vercel.json, netlify.toml, Dockerfile, .github/workflows/deploy.yml, etc.), and the deploy process in plain words. Use AskUserQuestion: "Deploy done? (Yes / Not yet / Skip validate)". Block until Yes or Skip.
|
5. **DEPLOY PAUSE** — List exact deploy artifacts: changed files since baseline, deploy hints from project (vercel.json, netlify.toml, Dockerfile, .github/workflows/deploy.yml, etc.), and the deploy process in plain words. Use AskUserQuestion: "Deploy done? (Yes / Not yet / Skip validate)". Block until Yes or Skip.
|
||||||
6. **/web-validate (live site)** — Run validator-analyzer against the deployed URL. Capture `SCORE_VALIDATE`.
|
6. **/web-validate (live site)** — Run validator-analyzer against the deployed URL. Capture `SCORE_VALIDATE`.
|
||||||
7. **GATE — per-axis threshold ≥17/20** — Compute final `SCORE_*_AFTER` for SEO classique, GEO (IA), HARDEN, VALIDATE. If ANY < 17/20: STOP. Generate `.claude/audits/HANDOVER-ROADMAP.md` with prioritized analysis of what's blocking each below-threshold axis. Do NOT write the client deliverable. Report to user.
|
7. **GATE — per-axis threshold ≥17/20** — Compute final `SCORE_*_AFTER` for SEO classique, GEO (IA), HARDEN, VALIDATE. If ANY < 17/20: STOP. Generate `.claude/audits/HANDOVER-ROADMAP.md` with prioritized analysis of what's blocking each below-threshold axis. Do NOT write the client deliverable. Report to user.
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ The two mechanical spans (prep, finish+tag) run on the sonnet-pinned
|
|||||||
gate needed here, dispatch does the job. This dispatcher keeps everything
|
gate needed here, dispatch does the job. This dispatcher keeps everything
|
||||||
the executor must never own: the version-NUMBER decision (judgment — derives
|
the executor must never own: the version-NUMBER decision (judgment — derives
|
||||||
from semver change nature), and the two human gates (when to release, and
|
from semver change nature), and the two human gates (when to release, and
|
||||||
the tag push). A human gate sits BETWEEN the two spans by construction, so the
|
the tag push (auto-push mode; in manual push mode the user pushes main,
|
||||||
executor is never dispatched twice in one call.
|
develop and the tag in one command)). A human gate sits BETWEEN the two
|
||||||
|
spans by construction, so the executor is never dispatched twice in one call.
|
||||||
|
|
||||||
## When to use
|
## When to use
|
||||||
- `develop` is ahead of `main` and you want to publish a version.
|
- `develop` is ahead of `main` and you want to publish a version.
|
||||||
@@ -54,6 +55,8 @@ Read the `## [Unreleased]` section of `CHANGELOG.md` and the commits on
|
|||||||
`develop` since `main`. Apply the Versioning rule above (breaking → MAJOR,
|
`develop` since `main`. Apply the Versioning rule above (breaking → MAJOR,
|
||||||
features → MINOR, fixes → PATCH) and settle `<X.Y.Z>` before dispatching
|
features → MINOR, fixes → PATCH) and settle `<X.Y.Z>` before dispatching
|
||||||
anything — the executor never derives or second-guesses this number.
|
anything — the executor never derives or second-guesses this number.
|
||||||
|
The version must match `^[0-9]+\.[0-9]+\.[0-9]+$` before it is placed in
|
||||||
|
any command or tag; anything else stops the run.
|
||||||
|
|
||||||
### STEP 3 — Dispatch: prep
|
### STEP 3 — Dispatch: prep
|
||||||
```
|
```
|
||||||
@@ -93,10 +96,22 @@ Parse the `RELEASE-EXEC REPORT`:
|
|||||||
not an auto-retry.
|
not an auto-retry.
|
||||||
|
|
||||||
### STEP 6 — Tag push GATE (ASK)
|
### STEP 6 — Tag push GATE (ASK)
|
||||||
`main` and `develop` are already on origin: the lib pushes every merge as
|
Read the state, separate Bash calls:
|
||||||
it lands (`_gitflow_merge_into` + the post-merge hook, BDR-095). Only the
|
`git rev-list --count origin/main..main 2>/dev/null || echo unknown`,
|
||||||
tag is left. STOP. On explicit go only ([[LRN-069]]) — run the tag push
|
`git rev-list --count origin/develop..develop 2>/dev/null || echo unknown`,
|
||||||
HERE, in this dispatcher, never delegated to the executor:
|
`bash "$HOME/.claude/lib/gitflow.sh" push-mode`.
|
||||||
|
- Anything other than `auto` from the verb (manual, invalid, empty, usage
|
||||||
|
error) OR either count ≠ 0 or `unknown` → Claude pushes nothing
|
||||||
|
(push-guard would refuse it in manual mode; a failed lib push is the
|
||||||
|
user's call, BDR-095). Print ONE command for the user and STOP, no
|
||||||
|
question: `! git push --atomic origin main develop v<X.Y.Z>` (invalid:
|
||||||
|
quote the verb's stderr line verbatim; auto with a count ≠ 0 or unknown:
|
||||||
|
say `main/develop not on origin (no remote-tracking ref or the lib's push
|
||||||
|
did not land)`; no origin remote (`git remote get-url origin` fails): say
|
||||||
|
`add an origin remote first`).
|
||||||
|
- Push mode `auto` and both counts 0 → main and develop are on origin; only
|
||||||
|
the tag is left. STOP. On explicit go only ([[LRN-069]]) — run the tag
|
||||||
|
push HERE, never delegated:
|
||||||
```
|
```
|
||||||
AskUserQuestion:
|
AskUserQuestion:
|
||||||
Push tag v<X.Y.Z> to origin? — go / hold
|
Push tag v<X.Y.Z> to origin? — go / hold
|
||||||
@@ -105,13 +120,16 @@ Go →
|
|||||||
```bash
|
```bash
|
||||||
git push origin v<X.Y.Z>
|
git push origin v<X.Y.Z>
|
||||||
```
|
```
|
||||||
`hold` → stop; the release is on origin (main + develop), the tag stays local.
|
`hold` → stop; the release is on origin (main + develop), the tag stays
|
||||||
|
local until the next push of main (`--follow-tags` on every lib and hook
|
||||||
|
push).
|
||||||
|
|
||||||
## Common mistakes
|
## Common mistakes
|
||||||
- Tagging before `gitflow finish` → tag wouldn't sit on main's merge commit. Tag AFTER, on main.
|
- Tagging before `gitflow finish` → tag wouldn't sit on main's merge commit. Tag AFTER, on main.
|
||||||
- Auto-firing finish because tests pass → finish is a HUMAN gate.
|
- Auto-firing finish because tests pass → finish is a HUMAN gate.
|
||||||
- Restarting the tag at v1.0.0 → desyncs from the CHANGELOG lineage. Continue it.
|
- Restarting the tag at v1.0.0 → desyncs from the CHANGELOG lineage. Continue it.
|
||||||
- Pushing the tag without the ASK gate → [[LRN-069]].
|
- Pushing the tag without the ASK gate → [[LRN-069]].
|
||||||
|
- Pushing anything in manual push mode → print the one user command, push nothing.
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
`RC_WORK=$(mktemp -d) RC_TAG=1 bash lib/tests/run-release-candidate.sh` → 5/5 (fan-out + tag on main). `RC_TAG=0` reds the tag assertion — proves the lib alone never tags (the gap this skill fills).
|
`RC_WORK=$(mktemp -d) RC_TAG=1 bash lib/tests/run-release-candidate.sh` → 5/5 (fan-out + tag on main). `RC_TAG=0` reds the tag assertion — proves the lib alone never tags (the gap this skill fills).
|
||||||
|
|||||||
+16
-5
@@ -237,6 +237,16 @@ order:
|
|||||||
and says so in the summary.
|
and says so in the summary.
|
||||||
4. Confirm `git status --porcelain` is clean (runtime junk the sandbox
|
4. Confirm `git status --porcelain` is clean (runtime junk the sandbox
|
||||||
cannot delete, e.g. `__pycache__/`, becomes a report residual line).
|
cannot delete, e.g. `__pycache__/`, becomes a report residual line).
|
||||||
|
5. Push state, only when a branch exists (report-only, skipped or
|
||||||
|
dirty-tree projects have none: their row keeps `no branch`, no push
|
||||||
|
column). Two read-only calls, probe first:
|
||||||
|
`git -C <abs project> remote get-url origin >/dev/null 2>&1 || echo no-origin`
|
||||||
|
then
|
||||||
|
`git -C <abs project> rev-list --count <branch> --not --remotes=origin 2>/dev/null || echo unknown`
|
||||||
|
(`<branch>` = the name `gitflow start` returned, suffixed `-2`/`-3` on a
|
||||||
|
same-day re-run — never the bare `chore/tour-<date>`). 0 → `on origin`;
|
||||||
|
else `local only → ! git -C <abs project> push -u origin <branch>` (probe
|
||||||
|
printed `no-origin` → `local only (no origin remote)`).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
## Tour 2026-07-04 — branch chore/tour-2026-07-04 — 2 iterations — CONVERGED
|
## Tour 2026-07-04 — branch chore/tour-2026-07-04 — 2 iterations — CONVERGED
|
||||||
@@ -255,8 +265,8 @@ any project line with contract-changing fixes left open for decision):
|
|||||||
|
|
||||||
```
|
```
|
||||||
TOUR COMPLETE — 2026-07-04
|
TOUR COMPLETE — 2026-07-04
|
||||||
~/proj/api : CONVERGED (2 it.) — 3 fixed, 1 suggested | chore/tour-2026-07-04, 4 commits
|
~/proj/api : CONVERGED (2 it.) — 3 fixed, 1 suggested | chore/tour-2026-07-04, 4 commits | on origin
|
||||||
~/proj/site : NOT CONVERGED (3 it.) — 2 open residuals | chore/tour-2026-07-04, 6 commits
|
~/proj/site : NOT CONVERGED (3 it.) — 2 open residuals | chore/tour-2026-07-04, 6 commits | local only → ! git -C ~/proj/site push -u origin chore/tour-2026-07-04
|
||||||
~/proj/lib : report-only (dirty tree) | no branch
|
~/proj/lib : report-only (dirty tree) | no branch
|
||||||
Branches left UNMERGED — review each, then `gitflow finish` on your GO.
|
Branches left UNMERGED — review each, then `gitflow finish` on your GO.
|
||||||
Reconcile suggestions pending — apply via /reconcile.
|
Reconcile suggestions pending — apply via /reconcile.
|
||||||
@@ -270,9 +280,10 @@ without that approval — neither this repo's nor any target project's.
|
|||||||
|
|
||||||
- Branch via the gitflow lib; **never `gitflow finish`, never merge,
|
- Branch via the gitflow lib; **never `gitflow finish`, never merge,
|
||||||
never push `main`/`develop`** — "the tour is green" is not a signal.
|
never push `main`/`develop`** — "the tour is green" is not a signal.
|
||||||
The chore branch's own commits are pushed by the gitflow hooks
|
The gitflow hooks push the chore branch in auto-push mode only; when it
|
||||||
(BDR-095); a `push FAILED` hook warning is a report residual, fixed
|
is not on origin (manual push mode, or a `push FAILED` warning) the USER
|
||||||
with a plain `git push -u origin chore/tour-<date>`.
|
pushes it — `! git -C <abs project> push -u origin <branch>` — the tour
|
||||||
|
never pushes or retries.
|
||||||
- Scoped pathspecs only; `git add -A` is forbidden.
|
- Scoped pathspecs only; `git add -A` is forbidden.
|
||||||
- Target TODO.md and target `.claude/memory/` are READ-ONLY. Reconcile
|
- Target TODO.md and target `.claude/memory/` are READ-ONLY. Reconcile
|
||||||
produces suggestions, not edits.
|
produces suggestions, not edits.
|
||||||
|
|||||||
Reference in New Issue
Block a user