instar 1.3.425 → 1.3.427
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/dist/commands/init.js +5 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +7 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +20 -20
- package/src/templates/hooks/dangerous-command-guard.sh +9 -2
- package/upgrades/1.3.426.md +20 -0
- package/upgrades/1.3.427.md +20 -0
- package/upgrades/guard-forcepush-precise.eli16.md +29 -0
- package/upgrades/side-effects/guard-forcepush-precise.md +38 -0
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-08T05:
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-08T05:54:27.957Z",
|
|
5
|
+
"instarVersion": "1.3.427",
|
|
6
6
|
"entryCount": 199,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"domain": "identity",
|
|
12
12
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
13
13
|
"installedPath": ".instar/hooks/instar/session-start.sh",
|
|
14
|
-
"contentHash": "
|
|
14
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
15
15
|
"since": "2025-01-01"
|
|
16
16
|
},
|
|
17
17
|
"hook:dangerous-command-guard": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"domain": "safety",
|
|
21
21
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
22
22
|
"installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
|
|
23
|
-
"contentHash": "
|
|
23
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
24
24
|
"since": "2025-01-01"
|
|
25
25
|
},
|
|
26
26
|
"hook:grounding-before-messaging": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"domain": "safety",
|
|
30
30
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
31
31
|
"installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
|
|
32
|
-
"contentHash": "
|
|
32
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
33
33
|
"since": "2025-01-01"
|
|
34
34
|
},
|
|
35
35
|
"hook:compaction-recovery": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"domain": "identity",
|
|
39
39
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
40
40
|
"installedPath": ".instar/hooks/instar/compaction-recovery.sh",
|
|
41
|
-
"contentHash": "
|
|
41
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
42
42
|
"since": "2025-01-01"
|
|
43
43
|
},
|
|
44
44
|
"hook:external-operation-gate": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"domain": "safety",
|
|
48
48
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
49
49
|
"installedPath": ".instar/hooks/instar/external-operation-gate.js",
|
|
50
|
-
"contentHash": "
|
|
50
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
51
51
|
"since": "2025-01-01"
|
|
52
52
|
},
|
|
53
53
|
"hook:deferral-detector": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"domain": "safety",
|
|
57
57
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
58
58
|
"installedPath": ".instar/hooks/instar/deferral-detector.js",
|
|
59
|
-
"contentHash": "
|
|
59
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
60
60
|
"since": "2025-01-01"
|
|
61
61
|
},
|
|
62
62
|
"hook:self-stop-guard": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"domain": "coherence",
|
|
66
66
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
67
67
|
"installedPath": ".instar/hooks/instar/self-stop-guard.js",
|
|
68
|
-
"contentHash": "
|
|
68
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
69
69
|
"since": "2025-01-01"
|
|
70
70
|
},
|
|
71
71
|
"hook:post-action-reflection": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"domain": "evolution",
|
|
75
75
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
76
76
|
"installedPath": ".instar/hooks/instar/post-action-reflection.js",
|
|
77
|
-
"contentHash": "
|
|
77
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
78
78
|
"since": "2025-01-01"
|
|
79
79
|
},
|
|
80
80
|
"hook:external-communication-guard": {
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"domain": "safety",
|
|
84
84
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
85
85
|
"installedPath": ".instar/hooks/instar/external-communication-guard.js",
|
|
86
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
87
87
|
"since": "2025-01-01"
|
|
88
88
|
},
|
|
89
89
|
"hook:scope-coherence-collector": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"domain": "coherence",
|
|
93
93
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
94
94
|
"installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
|
|
95
|
-
"contentHash": "
|
|
95
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
96
96
|
"since": "2025-01-01"
|
|
97
97
|
},
|
|
98
98
|
"hook:scope-coherence-checkpoint": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"domain": "coherence",
|
|
102
102
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
103
103
|
"installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
|
|
104
|
-
"contentHash": "
|
|
104
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
105
105
|
"since": "2025-01-01"
|
|
106
106
|
},
|
|
107
107
|
"hook:free-text-guard": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"domain": "safety",
|
|
111
111
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
112
112
|
"installedPath": ".instar/hooks/instar/free-text-guard.sh",
|
|
113
|
-
"contentHash": "
|
|
113
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
114
114
|
"since": "2025-01-01"
|
|
115
115
|
},
|
|
116
116
|
"hook:claim-intercept": {
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"domain": "coherence",
|
|
120
120
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
121
121
|
"installedPath": ".instar/hooks/instar/claim-intercept.js",
|
|
122
|
-
"contentHash": "
|
|
122
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:claim-intercept-response": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "coherence",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/claim-intercept-response.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"hook:stop-gate-router": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"domain": "safety",
|
|
138
138
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
139
139
|
"installedPath": ".instar/hooks/instar/stop-gate-router.js",
|
|
140
|
-
"contentHash": "
|
|
140
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"hook:auto-approve-permissions": {
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"domain": "safety",
|
|
147
147
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
148
148
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
149
|
-
"contentHash": "
|
|
149
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
150
150
|
"since": "2025-01-01"
|
|
151
151
|
},
|
|
152
152
|
"job:health-check": {
|
|
@@ -1050,7 +1050,7 @@
|
|
|
1050
1050
|
"type": "template",
|
|
1051
1051
|
"domain": "safety",
|
|
1052
1052
|
"sourcePath": "src/templates/hooks/dangerous-command-guard.sh",
|
|
1053
|
-
"contentHash": "
|
|
1053
|
+
"contentHash": "9c44b35ead12cf015b055b4a63d5d395257dc4479de2d83b280513c7cf214f28",
|
|
1054
1054
|
"since": "2025-01-01"
|
|
1055
1055
|
},
|
|
1056
1056
|
"template:free-text-guard.sh": {
|
|
@@ -1538,7 +1538,7 @@
|
|
|
1538
1538
|
"type": "subsystem",
|
|
1539
1539
|
"domain": "updates",
|
|
1540
1540
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1541
|
-
"contentHash": "
|
|
1541
|
+
"contentHash": "02ef1d845e3c49eba88d81c593bc621105d7e3c2f943cccaafcb9194ab5eb4c9",
|
|
1542
1542
|
"since": "2025-01-01"
|
|
1543
1543
|
},
|
|
1544
1544
|
"subsystem:scheduler": {
|
|
@@ -84,8 +84,15 @@ RISKY_PATTERNS=(
|
|
|
84
84
|
# main carries remote branch protection that rejects a force-push regardless.
|
|
85
85
|
FORCE_WITH_LEASE_OWN_BRANCH=0
|
|
86
86
|
if echo "$INPUT" | grep -qiE 'git +push[^|;&]*--force-with-lease'; then
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
# Scan ONLY the `git push …` invocation for a protected branch — NOT the whole
|
|
88
|
+
# $INPUT. The previous whole-$INPUT scan false-positived on any unrelated text in the
|
|
89
|
+
# command (e.g. a heredoc status message mentioning "release cadence" or "main"),
|
|
90
|
+
# blocking a legitimate PR-branch force-with-lease update — the recurring friction
|
|
91
|
+
# the carve-out exists to remove (2026-06-07, topic 19437). Isolating to the push
|
|
92
|
+
# invocation keeps the main/master/release block precise.
|
|
93
|
+
PUSH_INVOCATION=$(echo "$INPUT" | grep -oiE 'git +push[^|;&]*' | head -1)
|
|
94
|
+
if echo "$PUSH_INVOCATION" | grep -qiE '(^|[[:space:]:/])(main|master|develop|release[A-Za-z0-9._/-]*)([[:space:]]|:|$)'; then
|
|
95
|
+
FORCE_WITH_LEASE_OWN_BRANCH=0 # explicit protected target in the push command — keep blocking
|
|
89
96
|
else
|
|
90
97
|
FORCE_WITH_LEASE_OWN_BRANCH=1 # safe: force-with-lease to a non-protected branch
|
|
91
98
|
fi
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Fixed a false-positive in the `dangerous-command-guard` safety hook. The hook allows the safe `git push --force-with-lease` to your own feature/PR branch while still blocking a force-push to a protected branch (main, master, develop, release*). It was deciding "is this a protected branch?" by scanning the entire command line for those words — so unrelated text in the command (a chained status message, a log path, anything mentioning "release" or "main") could wrongly trip the block and refuse a perfectly safe branch update. The check now reads only the extracted `git push …` portion of the command, keeping the protected-branch block precise while removing the false-positive. The same one-line fix is applied to all three places the guard is written (the shipped template, the update-migration writer, and the fresh-install writer), so deployed agents pick it up on their next update.
|
|
9
|
+
|
|
10
|
+
## What to Tell Your User
|
|
11
|
+
|
|
12
|
+
I fixed a case where my safety check for force-pushes was a little too eager — if a command happened to mention a word like "release" or "main" anywhere in it, I'd block a safe update to my own branch by mistake. Now I only look at the actual push command, so safe updates go through while real force-pushes to protected branches are still stopped. Existing agents get this automatically on their next update.
|
|
13
|
+
|
|
14
|
+
## Summary of New Capabilities
|
|
15
|
+
|
|
16
|
+
No new capability — this is a precision fix to an existing safety hook. The force-with-lease carve-out now scans only the push command, eliminating false-positives from unrelated command text while leaving the protected-branch block fully intact.
|
|
17
|
+
|
|
18
|
+
## Evidence
|
|
19
|
+
|
|
20
|
+
Reproduced live on 2026-06-07 (topic 19437): a `git push --force-with-lease` to a feature branch was blocked because the surrounding command text mentioned "release cadence". Before: the guard's protected-branch regex matched the word "release" anywhere in the command input and returned a block. After: the guard extracts only the `git push …` invocation and finds no protected-branch token there, so the push is allowed. A regression test pins the exact case — `git push --force-with-lease origin echo/provider-swap && echo "advancing the release cadence on main"` now exits 0 (allowed) — alongside the existing tests that still confirm force-with-lease to `main`/`master` is blocked and plain `--force`/`-f` is blocked. All 11 guard tests pass; the two sibling guard test suites (gh-pr-merge gate, codex dangerous-command block) also stay green.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Added the forward-ratchet enforcement for the "No Silent Degradation to Brittle Fallback" safety standard: `tests/unit/no-silent-llm-fallback.test.ts`. It enumerates every file that calls an LLM (`IntelligenceProvider.evaluate()`) and requires each to either carry a safety marker (degradation is reported, or the call is marked gating so it swaps providers and fails closed) or be listed as reviewed-advisory with a reason. A new LLM call that ships a silent brittle fallback in a gating path now fails CI instead of slipping through. Also recorded the round-2 convergence audit in the standard's spec: 44 callsites swept, zero dangerous fail-open gates remaining (the two that existed were fixed earlier), 23 classified as benign-advisory.
|
|
9
|
+
|
|
10
|
+
## What to Tell Your User
|
|
11
|
+
|
|
12
|
+
I added a guard that makes it impossible to quietly ship a safety check that silently falls back to dumb logic when its AI is unavailable — any new one has to either switch to a backup provider, refuse safely, or be explicitly reviewed. I also finished a full sweep and confirmed there are no remaining dangerous spots.
|
|
13
|
+
|
|
14
|
+
## Summary of New Capabilities
|
|
15
|
+
|
|
16
|
+
- A CI ratchet over every LLM call site that prevents new silent LLM-to-heuristic fallbacks in gating paths, backed by a documented, staleness-checked classification of every existing call site.
|
|
17
|
+
|
|
18
|
+
## Evidence
|
|
19
|
+
|
|
20
|
+
The audit that prompted this standard found two safety gates that returned a permissive verdict when their LLM was rate-limited — failing open exactly when they mattered. Those were fixed (fail-closed) and the provider-swap was added. This lint is the structural guard that stops a new one from being introduced: before it, a fresh gate with a silent heuristic fallback would pass CI unnoticed; now it fails the ratchet until the author swaps, fails closed, reports the degradation, or explicitly classifies the call as advisory. Verified by running the test against current main — it discovers 44 callsites and passes only because all are marked or reviewed; adding an unmarked gating callsite makes it fail with the offending file named.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Guard force-with-lease check — scope it to the actual push command
|
|
2
|
+
|
|
3
|
+
> The one-line version: the safety hook that blocks force-pushes was reading the *whole* command line — including unrelated status text — so it sometimes blocked a perfectly safe branch update by mistake; now it reads only the `git push` part.
|
|
4
|
+
|
|
5
|
+
## The problem in one breath
|
|
6
|
+
|
|
7
|
+
Instar has a safety hook (`dangerous-command-guard`) that stops dangerous git commands. It deliberately *allows* one safe case: `git push --force-with-lease` to your own feature/PR branch (the normal way to update a rebased branch), while still blocking a force-push that targets a protected branch like `main`, `master`, `develop`, or anything starting with `release`. The trouble was *how* it decided "is this targeting a protected branch": it scanned the entire command string for those words. So if the command happened to contain unrelated text — for example a chained status message or log line that mentioned "release cadence" or "main menu" — the guard saw the word "release"/"main" and wrongly concluded you were force-pushing a protected branch. It blocked a legitimate update to a feature branch.
|
|
8
|
+
|
|
9
|
+
## What already exists
|
|
10
|
+
|
|
11
|
+
- **`dangerous-command-guard` hook** — a PreToolUse shell hook that inspects every shell command an agent runs and blocks catastrophic or destructive ones (`rm -rf /`, `git push --force`, etc.). It already had the force-with-lease carve-out; only the protected-branch test inside it was too broad.
|
|
12
|
+
- **The carve-out itself** — the logic that says "force-with-lease to a non-protected branch is fine, force-with-lease to main is not." That intent is correct and unchanged.
|
|
13
|
+
- **Three writers of the guard** — the same guard script is produced in three places: the shipped template (`src/templates/hooks/dangerous-command-guard.sh`), the migration writer that updates existing agents (`PostUpdateMigrator`), and the fresh-install writer (`init.ts`). All three carried the identical bug.
|
|
14
|
+
|
|
15
|
+
## What this adds
|
|
16
|
+
|
|
17
|
+
The fix narrows the protected-branch check so it looks **only at the extracted `git push …` invocation**, not the whole command. Concretely: pull out just the `git push ...` portion of the command, and check *that* for a protected-branch token. Unrelated text elsewhere in the command can no longer flip the decision. The main/master/develop/release block stays exactly as precise as before for the part that actually matters — the push command — so nothing is loosened; force-with-lease to `main` is still blocked.
|
|
18
|
+
|
|
19
|
+
The same one-line change is applied to all three writers, so existing agents get it on their next update and new agents get it at install. A regression test pins the exact false-positive (a force-with-lease to a feature branch with the word "release" in trailing text must be allowed).
|
|
20
|
+
|
|
21
|
+
## The safeguards
|
|
22
|
+
|
|
23
|
+
**Prevents the false-positive without widening the guard.** The check is now scoped to the push invocation, so it is *narrower*, not broader. A force-push to a protected branch is still blocked; plain `--force` / `-f` (no lease) is still blocked; everything the guard caught before, it still catches.
|
|
24
|
+
|
|
25
|
+
**Prevents drift between the three writers.** All three copies are fixed together, and existing tests already assert all three writers contain the carve-out, so a future edit that fixes only one copy would be caught.
|
|
26
|
+
|
|
27
|
+
## What ships when
|
|
28
|
+
|
|
29
|
+
One PR, one release. The migration writer means deployed agents pick the fix up automatically on their next update; no action required from anyone.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Side-Effects Review — scope force-with-lease protected-branch check to the push invocation
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `guard-forcepush-precise`
|
|
4
|
+
**Date:** `2026-06-07`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `self-review under the Tier-1 lite lane; the does-this-widen-the-guard question addressed below`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The `dangerous-command-guard` carve-out that permits `git push --force-with-lease` to a non-protected branch previously decided "is this a protected branch?" by scanning the WHOLE command input (`$INPUT`) for `(main|master|develop|release*)`. Any unrelated text in the command — a chained heredoc status message, a redirect path, a log line mentioning "release cadence" or "main" — false-positived and blocked a legitimate PR-branch force-with-lease update (observed live 2026-06-07, topic 19437: a force-push whose accompanying report text mentioned "release cadence" was blocked). The fix extracts only the `git push …` invocation (`grep -oiE 'git +push[^|;&]*' | head -1`) and scans THAT for the protected-branch token. Applied identically to all three writers (template, PostUpdateMigrator, init.ts) plus a regression test.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
- Protected-branch scan target — modified — `$INPUT` (whole command) → `$PUSH_INVOCATION` (extracted `git push …` segment only). No change to the regex itself.
|
|
15
|
+
- Carve-out semantics — unchanged — force-with-lease to a non-protected branch allowed; to main/master/develop/release* blocked; plain `--force`/`-f` blocked.
|
|
16
|
+
- Writers touched — all three (template `.sh`, `PostUpdateMigrator.getDangerousCommandGuard`, `init.ts` inline copy) — kept byte-consistent.
|
|
17
|
+
|
|
18
|
+
## 1. Direction-of-failure analysis
|
|
19
|
+
|
|
20
|
+
- **Old failure (live):** the guard blocked a SAFE force-with-lease to a feature branch whenever unrelated command text contained a protected-branch word → recurring friction; the agent could not update its own PR branch and resorted to workarounds.
|
|
21
|
+
- **New behavior:** the scan is confined to the push command. `git push --force-with-lease origin echo/feature && echo "release cadence on main"` is now ALLOWED (push targets a feature branch); `git push --force-with-lease origin main` is still BLOCKED. Both pinned by tests.
|
|
22
|
+
- **Trust surface NOT widened:** the change makes the protected-branch check NARROWER (fewer inputs match), never broader. A force-push to a protected branch, and plain `--force`/`-f`, remain blocked exactly as before — verified by the existing "BLOCKS force-with-lease that explicitly targets main/master" and "BLOCKS plain git push --force" tests, which still pass.
|
|
23
|
+
|
|
24
|
+
## 2. Over-permit
|
|
25
|
+
|
|
26
|
+
None. The only behavioral delta is that unrelated text outside the `git push` segment no longer triggers the protected-branch block. No new verbs, no wildcarding, no relaxation of the protected-branch set.
|
|
27
|
+
|
|
28
|
+
## 3. Scope deliberately NOT taken
|
|
29
|
+
|
|
30
|
+
- The broader text-scanning class (a `git commit` whose *message* mentions `git push --force` trips the risky-pattern loop) is a real but separate limitation of the deploy/risky-pattern scan; fixing it requires command-verb parsing across the whole guard and is out of scope for this targeted carve-out fix. Noted for a follow-up.
|
|
31
|
+
|
|
32
|
+
## 4. Migration parity
|
|
33
|
+
|
|
34
|
+
Covered. The migration writer (`PostUpdateMigrator.getDangerousCommandGuard`) is fixed, so existing agents receive the corrected guard on their next update (built-in `instar/` hooks are always-overwritten on migration). New agents get it via `init.ts`. The shipped template is fixed for completeness.
|
|
35
|
+
|
|
36
|
+
## 5. Token/cost impact
|
|
37
|
+
|
|
38
|
+
None.
|