instar 1.3.1613 → 1.3.1614
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/dashboard/console/machines-model.js +48 -0
- package/dashboard/console/machines.js +6 -3
- package/dashboard/console/plans-model.js +8 -6
- package/dist/core/AppConversationService.d.ts.map +1 -1
- package/dist/core/AppConversationService.js +3 -4
- package/dist/core/AppConversationService.js.map +1 -1
- package/dist/core/AppConversationStore.d.ts +26 -2
- package/dist/core/AppConversationStore.d.ts.map +1 -1
- package/dist/core/AppConversationStore.js +39 -1
- package/dist/core/AppConversationStore.js.map +1 -1
- package/dist/core/AppConversationsReplicatedStore.js +1 -1
- package/dist/core/AppConversationsReplicatedStore.js.map +1 -1
- package/dist/core/MobilePush.d.ts +3 -0
- package/dist/core/MobilePush.d.ts.map +1 -1
- package/dist/core/MobilePush.js +9 -3
- package/dist/core/MobilePush.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +6 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +24 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/appMediaReplyFiles.d.ts +10 -0
- package/dist/core/appMediaReplyFiles.d.ts.map +1 -1
- package/dist/core/appMediaReplyFiles.js +37 -19
- package/dist/core/appMediaReplyFiles.js.map +1 -1
- package/dist/core/appMediaTypes.d.ts +7 -0
- package/dist/core/appMediaTypes.d.ts.map +1 -1
- package/dist/core/appMediaTypes.js +17 -0
- package/dist/core/appMediaTypes.js.map +1 -1
- package/dist/core/appPlatformMedia.d.ts +44 -0
- package/dist/core/appPlatformMedia.d.ts.map +1 -0
- package/dist/core/appPlatformMedia.js +121 -0
- package/dist/core/appPlatformMedia.js.map +1 -0
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/messaging/TelegramAdapter.d.ts +21 -0
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +48 -0
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/monitoring/GreenPrAutoMerger.d.ts.map +1 -1
- package/dist/monitoring/GreenPrAutoMerger.js +5 -2
- package/dist/monitoring/GreenPrAutoMerger.js.map +1 -1
- package/dist/monitoring/greenPrLogic.d.ts +7 -1
- package/dist/monitoring/greenPrLogic.d.ts.map +1 -1
- package/dist/monitoring/greenPrLogic.js +13 -0
- package/dist/monitoring/greenPrLogic.js.map +1 -1
- package/dist/native/instar-desktop-host +0 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +2 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +17 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.js +3 -3
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/machineMaintenancePool.d.ts +84 -0
- package/dist/server/machineMaintenancePool.d.ts.map +1 -0
- package/dist/server/machineMaintenancePool.js +165 -0
- package/dist/server/machineMaintenancePool.js.map +1 -0
- package/dist/server/mobileConversationRoutes.d.ts +7 -0
- package/dist/server/mobileConversationRoutes.d.ts.map +1 -1
- package/dist/server/mobileConversationRoutes.js +55 -1
- package/dist/server/mobileConversationRoutes.js.map +1 -1
- package/dist/server/mobileMediaRoutes.d.ts.map +1 -1
- package/dist/server/mobileMediaRoutes.js +9 -5
- package/dist/server/mobileMediaRoutes.js.map +1 -1
- package/dist/server/mobilePairingRoutes.d.ts +0 -5
- package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
- package/dist/server/mobilePairingRoutes.js +11 -2
- package/dist/server/mobilePairingRoutes.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +59 -4
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/scripts/lib/release-local-steps.mjs +11 -2
- package/scripts/safe-merge.mjs +35 -0
- package/scripts/standards-coverage.mjs +6 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/src/scaffold/templates.ts +2 -1
- package/upgrades/1.3.1614.md +73 -0
- package/upgrades/side-effects/app-reply-push-preview.eli16.md +11 -0
- package/upgrades/side-effects/app-reply-push-preview.md +57 -0
- package/upgrades/side-effects/chat-media-telegram-inbound.eli16.md +11 -0
- package/upgrades/side-effects/chat-media-telegram-inbound.md +75 -0
- package/upgrades/side-effects/console-blocker-topic-names.eli16.md +5 -0
- package/upgrades/side-effects/console-blocker-topic-names.md +34 -0
- package/upgrades/side-effects/machine-maintenance-pool-view.md +107 -0
- package/upgrades/side-effects/release-local-pending-runs.md +60 -0
- package/upgrades/side-effects/stacked-pr-and-ci-timeouts.md +120 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Side-Effects Review — stacked PRs are never merged or shown clean; every CI job has a timeout
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `stacked-pr-and-ci-timeouts`
|
|
4
|
+
**Date:** `2026-11-02`
|
|
5
|
+
**Author:** `Echo`
|
|
6
|
+
**Second-pass reviewer:** `independent reviewer subagent (see below)`
|
|
7
|
+
**Tier:** 1 (small, reversible by one revert; only adds refusals, skips and time limits). Change size: 2 workflow files, 3 source files, 5 test files, 3 docs. Effort: one design pass, no spec rounds.
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
Two evolution actions on the CI/merge path.
|
|
12
|
+
|
|
13
|
+
**ACT-053.** `ci.yml` runs on `pull_request: branches: [main]` and the main ruleset's required checks apply only to main. A PR whose base is a feature branch (a stacked PR) therefore runs no suite on GitHub and shows mergeStateStatus CLEAN. Of the last 400 merged PRs, one (#2202, 2026-10-19) merged branch-to-branch.
|
|
14
|
+
|
|
15
|
+
Options weighed:
|
|
16
|
+
- (a) widen ci.yml's filter: every push to every stacked PR runs all 13 jobs (8 unit shards), then again after retarget. On an Actions allowance measured saturated (ci.yml concurrency notes: a single PR took hours), that roughly doubles stack cost. Rejected on capacity.
|
|
17
|
+
- (b) required checks on every base: a repository ruleset setting, not a reviewable file; with no suite running on those bases it would leave stacked PRs pending forever with no explanation. Rejected.
|
|
18
|
+
- (c) refuse merges into a feature branch, retarget to main first. Zero extra suite runs; stacks are still reviewed in place and verified exactly once against main. **Chosen.**
|
|
19
|
+
|
|
20
|
+
How the existing merge paths treat a non-main base today (checked before choosing):
|
|
21
|
+
- `safe-merge --admin` (actions floor): refuses already, because the e2e check never ran (`refused:e2e-missing-or-red`). Safe, but for the wrong stated reason.
|
|
22
|
+
- `safe-merge --auto`: refuses only when zero Actions checks ran. Any non-main-scoped workflow running (as eli16/ux-impact did on #2142) lets it arm, and with nothing required on that base GitHub merges at once. **Hole.**
|
|
23
|
+
- Local floor (`safe-merge` sync path with `floor: local`, configured on this agent): Local Verify keys records by (pr, head, base) and will verify a PR against its feature base on request; the record then admits a merge INTO the feature branch. The content is tested, but the merge is not a landing on main and reports "merged".
|
|
24
|
+
- `StatusReconciler` (local-verify GitHub status mirror) already only posts for `baseRefName === 'main'`.
|
|
25
|
+
- Green-PR watcher: on the local floor, a stacked PR with a record is a candidate.
|
|
26
|
+
|
|
27
|
+
Change:
|
|
28
|
+
1. `scripts/safe-merge.mjs`: `nonMainBaseRefusal(baseRefName)` (pure, exact match on `main`); `main()` exits `refused:non-main-base` right after the draft check, before `--auto`, floor selection and any check read. New capabilities feature `non-main-base-refusal`.
|
|
29
|
+
2. `.github/workflows/stacked-pr-guard.yml`: `pull_request` with `branches-ignore: [main]`, types opened/edited/synchronize/reopened; one step, no checkout, `timeout-minutes: 2`, prints an `::error::` with the retarget command and exits 1. The base name reaches the shell through `env`, never inline.
|
|
30
|
+
3. `src/monitoring/greenPrLogic.ts`: `isStackedPr(pr)` (known, non-empty, not `main`); `classifyCandidate` skips `non-main-base` first after ownership.
|
|
31
|
+
4. `src/monitoring/GreenPrAutoMerger.ts`: the red-PR watchdog treats a stacked PR as not stuck (it is red by design from the guard).
|
|
32
|
+
|
|
33
|
+
**ACT-059.** No ci.yml job declared `timeout-minutes`, so all inherited the 6-hour default. Measured 79 completed ci.yml runs (2026-11-02): slowest unit shard 29.6 min, integration 24.4, e2e 34.9, desktop packages 3.9, every other gate at most 2.3. Limits set at about twice the slowest: unit 60, integration 50, e2e 70, all others 15. A header comment in ci.yml records the measurement.
|
|
34
|
+
|
|
35
|
+
## Decision-point inventory
|
|
36
|
+
|
|
37
|
+
- `safe-merge` main(): new refusal `refused:non-main-base` (deterministic base-name fact).
|
|
38
|
+
- `classifyCandidate`: new skip `non-main-base` (more conservative only).
|
|
39
|
+
- `redPrWatchdogPass`: stacked PRs no longer raise stuck-red attention (signal suppression for a known-by-design red).
|
|
40
|
+
- GitHub: a new non-required check that is always red on stacked PRs; ci.yml job time limits.
|
|
41
|
+
|
|
42
|
+
## 1. Over-block
|
|
43
|
+
|
|
44
|
+
- A deliberate branch-to-branch merge through safe-merge is refused. No such merge is part of any flow here (1 in the last 400, and that one is the incident). A human can still merge on GitHub; the red guard check tells them why not to.
|
|
45
|
+
- A job legitimately exceeding its limit (e.g. the suite grows ~2x) fails and must be re-run or the limit raised. Margin is ~2x the slowest of 79 runs; the header comment says to raise it when the job genuinely grows.
|
|
46
|
+
- Runner queue time does not count toward `timeout-minutes` (it starts when the job starts on a runner), so the saturated allowance cannot cause false timeouts.
|
|
47
|
+
|
|
48
|
+
## 2. Under-block
|
|
49
|
+
|
|
50
|
+
- A human clicking Merge on GitHub on a red stacked PR is not prevented: the guard is not a required check (making it required is a ruleset change, option b). The badge is no longer CLEAN, which is the reported defect; every agent merge goes through safe-merge.
|
|
51
|
+
- After a stacked PR is retargeted to main (by hand, or by GitHub when the bottom PR's branch is deleted), ci.yml does not fire on the base change alone (`edited` is not in its types). Until a push or close/reopen: `--admin` refuses (`e2e-missing-or-red`); `--auto` is NOT refused by `no-checks-ran` (the stale guard run is an Actions check) and may arm, but GitHub then waits on main's required checks, which have not run, so nothing merges; the local floor needs a new record for the main base. Safe in every case, and both the refusal text and the guard's error now say to push or close/reopen after retargeting.
|
|
52
|
+
- The stale red guard check stays attached to a head SHA after retarget until a new push. It never adds a block that was not already there: that same head has no ci.yml run against main either.
|
|
53
|
+
|
|
54
|
+
## 3. Level-of-abstraction fit
|
|
55
|
+
|
|
56
|
+
safe-merge is the single act-time merge authority for agents (MergeRunner and the watcher both call it), so the refusal belongs there. The watcher skip is a signal-level filter in front of it, mirroring the `no-checks-ran` precedent (PR #2307). The GitHub-visible signal belongs in a workflow because the reported defect is what GitHub shows.
|
|
57
|
+
|
|
58
|
+
## 4. Signal vs authority compliance
|
|
59
|
+
|
|
60
|
+
The refusal holds blocking authority, but on a deterministic fact (the base ref name equals `main`), not a heuristic, and it can only produce "do not merge". Same pattern as `refused:draft` and `refused:no-checks-ran`. The watcher changes only skip or silence; they never cause a merge.
|
|
61
|
+
|
|
62
|
+
## 4b. Judgment-point check
|
|
63
|
+
|
|
64
|
+
No competing-signals judgment. Hard floor: a feature-branch base is never a landing.
|
|
65
|
+
|
|
66
|
+
## 5. Interactions
|
|
67
|
+
|
|
68
|
+
- `MergeRunner` passes `refused:*` through. The watcher skips stacked PRs before calling it, so the ladder is not consumed.
|
|
69
|
+
- Local Verify: unchanged; it may still verify a stacked PR on request (useful as an early signal); safe-merge simply will not merge it into the feature branch.
|
|
70
|
+
- `eli16-pr-gate`, `ux-impact-pr-gate`, `class-closure`, `decision-audit` remain main-only; unchanged.
|
|
71
|
+
- ci.yml concurrency block and test (`ci-workflow-concurrency.test.ts`) unchanged.
|
|
72
|
+
- Red-PR watchdog: a stacked PR previously raised could be cleared via the existing "recovered" path; harmless.
|
|
73
|
+
|
|
74
|
+
## 6. External surfaces
|
|
75
|
+
|
|
76
|
+
One new result string (`refused:non-main-base`), one new capability feature, one new candidate skip, one new GitHub check name ("Stacked PR — retarget to main before merging") on non-main-base PRs only, and job time limits. Open stacked PRs (#1930–#1939, phaseb) will show the red guard on their next push or edit. No config, routes or state.
|
|
77
|
+
|
|
78
|
+
## 6b. Operator-surface quality
|
|
79
|
+
|
|
80
|
+
The refusal and the check text both state the one action to take, with the exact command. No new attention items; one fewer kind (stacked PRs no longer raise stuck-red).
|
|
81
|
+
|
|
82
|
+
## 7. Multi-machine posture
|
|
83
|
+
|
|
84
|
+
Machine-local by design: safe-merge runs where invoked; the watcher runs on the lease holder. Both read GitHub, the shared truth. Workflows run on GitHub.
|
|
85
|
+
|
|
86
|
+
## 8. Rollback cost
|
|
87
|
+
|
|
88
|
+
Revert the commit. No state, migration or config.
|
|
89
|
+
|
|
90
|
+
## Conclusion
|
|
91
|
+
|
|
92
|
+
Option (c) closes the hole at zero CI cost; time limits close the 6-hour hang. Ship.
|
|
93
|
+
|
|
94
|
+
## Second-pass review (if required)
|
|
95
|
+
|
|
96
|
+
**Reviewer:** independent reviewer subagent, 2026-11-02
|
|
97
|
+
**First read: concern raised (accuracy only, no merge-safety defect).** (1) The refusal and guard texts said "retarget, let CI run", but ci.yml does not fire on a base change, so CI would never start. (2) The under-block bullet wrongly claimed `no-checks-ran` refuses a retargeted, unpushed head on `--auto`; the stale guard run is an Actions check, so `--auto` can arm, though GitHub still waits on main's unrun required checks and nothing merges. Both fixed: the texts now say to push or close/reopen after retargeting, and the under-block bullet is corrected. The reviewer confirmed: the refusal precedes head pin, floor choice, `--auto` arming and any `gh pr merge`; no caller merges into a non-main base or uses a repo with another merge branch; the guard YAML is valid and injection-safe (`env` only, `permissions: {}`); all 12 ci.yml jobs have timeouts at ~2x the measured slowest; `isStackedPr` cannot match a main or absent base; the tests would fail without the fix.
|
|
98
|
+
|
|
99
|
+
## Evidence pointers
|
|
100
|
+
|
|
101
|
+
- `tests/integration/safe-merge-non-main-base.test.ts`: real script, fake `gh` recording calls: stacked PR → exit 1 `refused:non-main-base` on `--auto` and `--admin`, only the PR read happened, no `gh pr merge`; a main PR passes the base check.
|
|
102
|
+
- `tests/unit/safe-merge-non-main-base.test.ts`: pure refusal (exact match, unreadable base refused), capabilities.
|
|
103
|
+
- `tests/unit/ci-workflow-timeouts.test.ts`: every ci.yml job has 1–120 min; heavy jobs keep headroom; ci.yml stays main-only; guard workflow shape and env-only base name.
|
|
104
|
+
- `tests/unit/green-pr-logic.test.ts`, `tests/unit/green-pr-red-watchdog.test.ts`: watcher skip and silence, base-scoped.
|
|
105
|
+
|
|
106
|
+
## Class-Closure Declaration (display-only mirror)
|
|
107
|
+
|
|
108
|
+
No agent-authored-artifact defect — not applicable (a CI/merge-path defect; the new tests are the regression guard).
|
|
109
|
+
|
|
110
|
+
## Addendum: the standards-coverage CI job pin
|
|
111
|
+
|
|
112
|
+
The first full local verify of this change failed one unit test, `tests/unit/standards-coverage-ratchet.test.ts` ("the live registry closes all six family audits"). `scripts/standards-coverage.mjs` pins the `standards-coverage` job in ci.yml to exactly the keys `name`, `runs-on`, `permissions`, `steps`. Adding `timeout-minutes: 15` to that job broke the pin, so the ratchet reported its own CI wiring as invalid.
|
|
113
|
+
|
|
114
|
+
Fix: the pin now expects `timeout-minutes` as part of the job's exact shape, and requires it to be a whole number from 1 to 60. The ratchet test fixture carries the key, and two new negative cases prove the check fails when the timeout is removed or set to 360.
|
|
115
|
+
|
|
116
|
+
- **Over-block:** a future change that raises this job above 60 minutes must also edit the pin. The job runs in about 2 minutes, so this is a visible, declared edit, as the pin intends.
|
|
117
|
+
- **Under-block:** none added. Every key the pin checked before is still checked.
|
|
118
|
+
- **Interactions:** `tests/unit/ci-workflow-timeouts.test.ts` checks the same key (1 to 120 minutes for every job). The tighter 60-minute cap here applies only to this one job and agrees with the value in ci.yml.
|
|
119
|
+
- **Rollback:** revert the commit.
|
|
120
|
+
- **Second-pass review (2026-11-03):** an independent reviewer concurred. A missing, fractional, zero, negative or over-60 timeout fails; no existing condition is weaker; `node scripts/standards-coverage.mjs --check` passes on the live ci.yml.
|