@bongos/core 1.19.837 → 1.19.838
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/.bongos-core.json +45 -20
- package/docs/adr/0302-the-third-identical-failure-stops-the-session-and-asks.md +74 -0
- package/docs/adr/README.md +1 -0
- package/docs/file-map.md +2 -0
- package/docs/module-api-changelog.md +2 -0
- package/modules/agents/migrations/agents_003_output_ref_idx.sql +41 -0
- package/modules/agents/module.json +1 -1
- package/modules/agents/pollers/event-router.js +737 -0
- package/modules/discord/module.json +1 -1
- package/modules/discord/routes/discord.js +25 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/plain-cards.js +2 -0
- package/src/module-api.js +1 -1
- package/tests/agents_event_router.mjs +523 -0
- package/tests/hooks_drain.mjs +1 -1
- package/tests/host_topology_skips.mjs +1 -0
- package/tests/stuck_detector.mjs +233 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.838",
|
|
6
|
+
"core_contract": "1.19.838",
|
|
7
|
+
"source_commit": "f5c78584166eedac7972dcb10f61e55d7c1685e7",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-17T17:02:39.487Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
12
|
+
"docs_redacted": 494,
|
|
13
13
|
"agent_docs_stubbed": 26,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 2257,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2777,
|
|
20
|
+
"tree_sha256": "61bef3a77f3f90a904e83ae13d78fa314c21c944451e91a369fb047fc78d9b7a",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -1994,10 +1994,15 @@
|
|
|
1994
1994
|
"mode": "0000644",
|
|
1995
1995
|
"sha256": "02f7e793bdf3665cf371f273dda6b84701918dc8fd031fac2893a19ed9f0bd9a"
|
|
1996
1996
|
},
|
|
1997
|
+
{
|
|
1998
|
+
"path": "docs/adr/0302-the-third-identical-failure-stops-the-session-and-asks.md",
|
|
1999
|
+
"mode": "0000644",
|
|
2000
|
+
"sha256": "08ea781a488d7454ca49b17e9540bb4c7bb9f1925aedf8ad4634057a89dd0d22"
|
|
2001
|
+
},
|
|
1997
2002
|
{
|
|
1998
2003
|
"path": "docs/adr/README.md",
|
|
1999
2004
|
"mode": "0000644",
|
|
2000
|
-
"sha256": "
|
|
2005
|
+
"sha256": "5c20d4bf4c0202a391a617d99daaa97d8a566d9d5c8534b5bd060faa8f8afe02"
|
|
2001
2006
|
},
|
|
2002
2007
|
{
|
|
2003
2008
|
"path": "docs/api-reference.md",
|
|
@@ -2552,7 +2557,7 @@
|
|
|
2552
2557
|
{
|
|
2553
2558
|
"path": "docs/file-map.md",
|
|
2554
2559
|
"mode": "0000644",
|
|
2555
|
-
"sha256": "
|
|
2560
|
+
"sha256": "b575f34143de0be30fadfd63bea76f77305fa175beee3960291414ff6b55d611"
|
|
2556
2561
|
},
|
|
2557
2562
|
{
|
|
2558
2563
|
"path": "docs/handoff-template.md",
|
|
@@ -2562,7 +2567,7 @@
|
|
|
2562
2567
|
{
|
|
2563
2568
|
"path": "docs/module-api-changelog.md",
|
|
2564
2569
|
"mode": "0000644",
|
|
2565
|
-
"sha256": "
|
|
2570
|
+
"sha256": "aed7cd21803eab964c3d296c5f938e8c94b9e05fb865ce3bb5780574a5fdcebb"
|
|
2566
2571
|
},
|
|
2567
2572
|
{
|
|
2568
2573
|
"path": "docs/modules-contract.md",
|
|
@@ -3709,10 +3714,20 @@
|
|
|
3709
3714
|
"mode": "0000644",
|
|
3710
3715
|
"sha256": "b576e8518bc8c9af9d5a1a86ace812f292fc2df1225cdfce8578d11703350391"
|
|
3711
3716
|
},
|
|
3717
|
+
{
|
|
3718
|
+
"path": "modules/agents/migrations/agents_003_output_ref_idx.sql",
|
|
3719
|
+
"mode": "0000644",
|
|
3720
|
+
"sha256": "7a9763f90da032c81aa0b1a8461a2e13b58d9f529c1b857b048648feeadc6fdd"
|
|
3721
|
+
},
|
|
3712
3722
|
{
|
|
3713
3723
|
"path": "modules/agents/module.json",
|
|
3714
3724
|
"mode": "0000644",
|
|
3715
|
-
"sha256": "
|
|
3725
|
+
"sha256": "4eea1864848b1217fef12070a981fda974d7105449d6a46bdf9ed04068b57c5e"
|
|
3726
|
+
},
|
|
3727
|
+
{
|
|
3728
|
+
"path": "modules/agents/pollers/event-router.js",
|
|
3729
|
+
"mode": "0000644",
|
|
3730
|
+
"sha256": "de64902d694acfc7d32aaf4d8629921f64cf851d600deb077a278b528d34c57d"
|
|
3716
3731
|
},
|
|
3717
3732
|
{
|
|
3718
3733
|
"path": "modules/agents/routes/agents.js",
|
|
@@ -4227,7 +4242,7 @@
|
|
|
4227
4242
|
{
|
|
4228
4243
|
"path": "modules/discord/module.json",
|
|
4229
4244
|
"mode": "0000644",
|
|
4230
|
-
"sha256": "
|
|
4245
|
+
"sha256": "437fa0e5174b2cbdd3c1949a3d048a8c8c09defce85afd04a27c0c635031db1b"
|
|
4231
4246
|
},
|
|
4232
4247
|
{
|
|
4233
4248
|
"path": "modules/discord/pollers/discord-bot.js",
|
|
@@ -4242,7 +4257,7 @@
|
|
|
4242
4257
|
{
|
|
4243
4258
|
"path": "modules/discord/routes/discord.js",
|
|
4244
4259
|
"mode": "0000644",
|
|
4245
|
-
"sha256": "
|
|
4260
|
+
"sha256": "b1316f763acef47e6f6a01b61d7d92868e54b5ded091919ad1d2bd8991f10ab8"
|
|
4246
4261
|
},
|
|
4247
4262
|
{
|
|
4248
4263
|
"path": "modules/discord/ship-broadcast.js",
|
|
@@ -7852,12 +7867,12 @@
|
|
|
7852
7867
|
{
|
|
7853
7868
|
"path": "package-lock.json",
|
|
7854
7869
|
"mode": "0000644",
|
|
7855
|
-
"sha256": "
|
|
7870
|
+
"sha256": "9baa1aa306e1c7925d66fc09484dc2c214ad13fa47e4d71c39fc6d7ca2d6e8a6"
|
|
7856
7871
|
},
|
|
7857
7872
|
{
|
|
7858
7873
|
"path": "package.json",
|
|
7859
7874
|
"mode": "0000644",
|
|
7860
|
-
"sha256": "
|
|
7875
|
+
"sha256": "9b0fe6c23bdb7eb915bcb6d049e341258d1daa654a791355ac8ca92bfd58a02b"
|
|
7861
7876
|
},
|
|
7862
7877
|
{
|
|
7863
7878
|
"path": "public-docs/index.html",
|
|
@@ -8717,7 +8732,7 @@
|
|
|
8717
8732
|
{
|
|
8718
8733
|
"path": "scripts/gds/plain-cards.js",
|
|
8719
8734
|
"mode": "0000644",
|
|
8720
|
-
"sha256": "
|
|
8735
|
+
"sha256": "63344839b3cb2cba39757b5501759aaef8e1bf100468d7304a56d4e709f2f8cf"
|
|
8721
8736
|
},
|
|
8722
8737
|
{
|
|
8723
8738
|
"path": "scripts/gds/portability-smoke-art.sh",
|
|
@@ -9787,7 +9802,7 @@
|
|
|
9787
9802
|
{
|
|
9788
9803
|
"path": "src/module-api.js",
|
|
9789
9804
|
"mode": "0000644",
|
|
9790
|
-
"sha256": "
|
|
9805
|
+
"sha256": "3363fefd57cbb3a31327b1c613ebdd4a325e26071a575237a7e0ec467a3f74c7"
|
|
9791
9806
|
},
|
|
9792
9807
|
{
|
|
9793
9808
|
"path": "src/module-loader/catalog.js",
|
|
@@ -9924,6 +9939,11 @@
|
|
|
9924
9939
|
"mode": "0000644",
|
|
9925
9940
|
"sha256": "eea8f9e0bdf2c84fabc81e16c30e4026a7a336c1e705d614e68b805957b9b74a"
|
|
9926
9941
|
},
|
|
9942
|
+
{
|
|
9943
|
+
"path": "tests/agents_event_router.mjs",
|
|
9944
|
+
"mode": "0000644",
|
|
9945
|
+
"sha256": "919ca0ea3fe5f78a194781f6b634b9da23212073cf0c7cbe8ae36a65cc3fecdb"
|
|
9946
|
+
},
|
|
9927
9947
|
{
|
|
9928
9948
|
"path": "tests/agents_routes.mjs",
|
|
9929
9949
|
"mode": "0000644",
|
|
@@ -11682,12 +11702,12 @@
|
|
|
11682
11702
|
{
|
|
11683
11703
|
"path": "tests/hooks_drain.mjs",
|
|
11684
11704
|
"mode": "0000644",
|
|
11685
|
-
"sha256": "
|
|
11705
|
+
"sha256": "84ccd5167165bbf12aba03cdf444b0d94f1e7cc4b4dccbc37ed59afd01cf39cf"
|
|
11686
11706
|
},
|
|
11687
11707
|
{
|
|
11688
11708
|
"path": "tests/host_topology_skips.mjs",
|
|
11689
11709
|
"mode": "0000644",
|
|
11690
|
-
"sha256": "
|
|
11710
|
+
"sha256": "22ac76bc38e6b52262a2afb664b6f883066daaa2864ad71d971f7ff2a6995d28"
|
|
11691
11711
|
},
|
|
11692
11712
|
{
|
|
11693
11713
|
"path": "tests/hub_disconnect_ui.mjs",
|
|
@@ -13514,6 +13534,11 @@
|
|
|
13514
13534
|
"mode": "0000644",
|
|
13515
13535
|
"sha256": "eafd4354dc95fae94d720ed4cda05638eb5719c3ab0e3af084e7bf9d41b1be35"
|
|
13516
13536
|
},
|
|
13537
|
+
{
|
|
13538
|
+
"path": "tests/stuck_detector.mjs",
|
|
13539
|
+
"mode": "0000644",
|
|
13540
|
+
"sha256": "005839daeb067c0de9c93e92f9bfc733c031fe572bf383cb29ea8105b56b8cd3"
|
|
13541
|
+
},
|
|
13517
13542
|
{
|
|
13518
13543
|
"path": "tests/subdomain_auth.mjs",
|
|
13519
13544
|
"mode": "0000644",
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# ADR 0302 — The third identical failure stops the session and asks
|
|
2
|
+
|
|
3
|
+
**Status:** accepted · **Date:** 2026-09-17 · **Task:** [task 1003990](https://cloudbongos.com/builders#/task/1003990) (goal 1000095 — BONGOS-V2)
|
|
4
|
+
|
|
5
|
+
**Related:** [ADR 0301](0301-a-red-pr-names-its-failing-tests-in-a-commit-status.md) (a red PR names its failing tests) · [ADR 0291](0291-the-accessibility-dimension-scores-the-transcript-not-the-diff.md) (accessibility is scored after the ship) · [ADR 0162](0162-review-gates-retired-rank-consistent-ci-only.md) (no new gates on the ship path) · [ADR 0043](0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md) (cooperative, fail-open hook layer)
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
The 2026-09-17 investigation of a non-technical builder's stalls found sessions that looped
|
|
10
|
+
without noticing: one pull request re-shipped into the same red check **nine times in four
|
|
11
|
+
hours**, and **45 of 169 claim attempts** in 4.5 days were refusals — the same task id retried
|
|
12
|
+
minutes apart. Each retry costs money the builder watches tick up, and they have no way to tell
|
|
13
|
+
that the agent is going round in a circle (idea 1000281).
|
|
14
|
+
|
|
15
|
+
Abandoned task 1002828 asked for a written bail-out rule. A rule in a memory file loses to the
|
|
16
|
+
next retry for the same reason the `git stash` ban did: the agent is not looking at it at the
|
|
17
|
+
moment it matters. Nothing else watches a session mid-flight — the accessibility score is
|
|
18
|
+
computed after the ship.
|
|
19
|
+
|
|
20
|
+
## Decision
|
|
21
|
+
|
|
22
|
+
1. **Count walls, per session, in a hook.** `.claude/hooks/stuck-detector.js` runs after every
|
|
23
|
+
shell tool call (`PostToolUse` and `PostToolUseFailure`, `Bash|PowerShell`). On the **third**
|
|
24
|
+
identical wall — and each one after — it injects one instruction: stop retrying, diagnose
|
|
25
|
+
(the path is named), or run `/ask-for-help`.
|
|
26
|
+
2. **The failure signature is the `[otb-plain]` card** (task 1003989). Every failure a builder
|
|
27
|
+
can be parked behind already prints one; its "What happened" line is static per failure code,
|
|
28
|
+
and its "By design" line already says whether a retry can ever help, which picks the
|
|
29
|
+
instruction's wording. Signature = that line + the task id in the command + the
|
|
30
|
+
`the PR is RED` line when present, so a red check that names *different* failing tests each
|
|
31
|
+
run reads as progress, not a wall. Only a builder CLI **run** (`node …scripts/gds/*.js`,
|
|
32
|
+
`bongos <verb>`) is read: `cat` or `git diff` over a file that quotes a card prints the
|
|
33
|
+
same text and is not a failure.
|
|
34
|
+
3. **A waiting card is not a wall.** Cards whose next step is "Nothing to do…" (`land_pending`,
|
|
35
|
+
a pending check, a pending join request) tell the session to poll; counting them would turn
|
|
36
|
+
the detector against the behaviour the card asks for. The set is pinned by test.
|
|
37
|
+
4. **The guards count through the same helper.** `git-guard.js` and `worktree-guard.js` call
|
|
38
|
+
`stuck-strikes.js` when they block — keyed on the rule, and on the file, respectively — and
|
|
39
|
+
append the instruction to the reason they already return. Three *different* wrong-tree files,
|
|
40
|
+
each corrected on the next call, is the guard working and is not counted.
|
|
41
|
+
5. **It never blocks, and it echoes nothing.** `additionalContext` only, exit 0, silent without
|
|
42
|
+
a card. Signatures are hashed before they touch `os.tmpdir()`; the instruction interpolates a
|
|
43
|
+
count and a digits-only task id, never text a tool printed.
|
|
44
|
+
|
|
45
|
+
## Alternatives rejected
|
|
46
|
+
|
|
47
|
+
- **Count any repeated failing command.** Red → green on a test *is* the same command failing
|
|
48
|
+
repeatedly; the detector would fire on ordinary work and become wallpaper.
|
|
49
|
+
- **Block the fourth attempt.** That is a new gate on the ship path (ADR 0162), and a wrong
|
|
50
|
+
signature match would strand a builder behind the tool meant to unstick them.
|
|
51
|
+
- **Server-side detection.** The server sees refused claims but not guard blocks or local red
|
|
52
|
+
runs, and cannot speak into the session at the moment of the retry.
|
|
53
|
+
- **Require `scripts/gds/plain-cards.js` from the hook.** Hooks are instance topology and the
|
|
54
|
+
script may live in the installed package; reading the printed card keeps the hook
|
|
55
|
+
dependency-free. The cost is a text coupling to the card's layout, pinned by test.
|
|
56
|
+
|
|
57
|
+
## Consequences
|
|
58
|
+
|
|
59
|
+
- Whether a non-zero exit routes to `PostToolUse` or `PostToolUseFailure` is the harness's
|
|
60
|
+
business; the hook is wired on both and reads the output from any of the four fields either
|
|
61
|
+
event has used. Only one event fires per call, so nothing is counted twice.
|
|
62
|
+
- The count is per session and lives in the OS temp dir as an **append-only** log of hashed
|
|
63
|
+
signatures — tool calls run in parallel and three hooks share the file, so a
|
|
64
|
+
read-modify-write would let one process wipe another's counts. A builder who opens a fresh
|
|
65
|
+
session after being told to stop starts from zero — acceptable: the instruction's job is to
|
|
66
|
+
break the loop inside one context, and the refusal itself still stands.
|
|
67
|
+
- Strikes do not decay inside a session: two hits, real progress, then a third hit hours later
|
|
68
|
+
still draws the instruction. It costs one paragraph the agent can weigh, and a time window
|
|
69
|
+
short enough to matter would have missed PR 922's runs, which were ~27 minutes apart.
|
|
70
|
+
- A box that cannot read which test failed gets a RED line with no names, so three red runs
|
|
71
|
+
share a signature whatever their causes. That is the PR 922 case the detector exists for;
|
|
72
|
+
the instruction says to run the suite locally when the status names nothing.
|
|
73
|
+
- A failure with no plain card is invisible to the detector. `tests/plain_cards.mjs` already
|
|
74
|
+
reds when a CLI gains a failure code without one, so the two stay in step.
|
package/docs/adr/README.md
CHANGED
|
@@ -393,3 +393,4 @@ This keeps the decision history honest and traceable.
|
|
|
393
393
|
| 0299 | [**The nod queue stays scoped to routed filings; the backlog walk is the widening** ([task 1003748](https://cloudbongos.com/builders#/task/1003748), goal 1000089). `listRoutedAwaitingNod` filters `origin='route'`, and on 2026-09-08 showed 11 of 232 backlog rows. Re-measured after `/backlog-review` (task 1003746) shipped: 115 backlog rows = 109 dep-gated + 2 spikes (not a person's decision) + 1 stranded + 3 awaiting a nod, all four walked by `/backlog-review`. **Decision: do not widen the card.** The omitted population already has a walkable review with the dependency predicate any widening needed; the copy says *reported* work, so the name is honest; a card slice would be a second copy of the walk's four-bucket partition. Revisit if the un-routed nod bucket outgrows a daily walk (then a count + link, derived from the same partition) or if the walk stops being run.](0299-the-nod-queue-stays-scoped-to-routed-filings.md) | ideas / backlog / attention |
|
|
394
394
|
| 0300 | [**A missing protected-surface registry is a broken install, not a module opt-out** ([task 1003662](https://cloudbongos.com/builders#/task/1003662), goal 1000091). Filed as a bug with a remedy attached: `require('./module-scope-map')` throws when `modules/government/protected-surfaces.json` is absent, so make it degrade to an empty protected set + a warning, matching `resolveOptional`. The throw reproduces, and the rest is wrong four times over. **The throw is not in the named file** — `module-scope-map.js` has no throw and no file read; it requires `permission-path-check.js`, whose `loadRegistry()` throws at module scope. **It is a written contract, not an oversight** — that file's header says FAIL-CLOSED in capitals and already pre-answers the layering worry (the read is `fs`, never `require`, so ADR 0083's one-way rule holds; static data, not code; `route-rank-check.js` reads `modules/*/routes/*.js` the same way). **Disabling the module cannot cause it** — enablement is a runtime flag, never a file deletion, and the read never consults it. **"Not yet materialized" cannot either** — no `files[]` allowlist, so `npm pack --dry-run` puts the 13,274-byte registry in the tarball; per ADR 0108 §1 you cannot have `@bongos/core` without it. The `resolveOptional` precedent does not transfer: that is the module **seam/port** resolver for a missing runtime *capability*, whereas this is the static data the boundary is made of, read where there is no server and no DB (a git hook, a CI job) — borrowing it converts "the boundary is unreadable" into "there is no boundary". **Decision: fail-closed stays, no behavior change, the remedy is rejected — and the one genuine defect is fixed: the message now names the cause and the fix** (reinstall the core; do not empty the set), because stating a refusal without a remedy is exactly how a reader concludes the module is optional and files this task. The asymmetry is the point: a false "nothing is protected" is silent, permanent and grants authority; a false "this install is broken" is loud and grants nothing. Revisit only if a core-only checkout without `modules/` becomes legitimate — and then the question is *where the registry lives*, not whether it is optional.](0300-a-missing-protected-surface-registry-is-a-broken-install.md) | governance / permissions |
|
|
395
395
|
| 0301 | [**A red PR names its failing tests in a commit status, and says so when it cannot see** ([task 1003988](https://cloudbongos.com/builders#/task/1003988), goal 1000095). One pull request took nine red CI runs in four hours because the builder box could not learn which test failed: without Checks:read GitHub nulls every check-run node, the server dropped the holes silently, and the red PR was reported as a review-or-pending wait. Now the merge state carries checks_unreadable and a red, unreadable rollup reads failing_check_unreadable; the unit workflow posts the failing test names as a unit-report commit STATUS (readable without the permission) from a separate job that holds the only write token and checks out no PR code; the server returns it as failing_tests, reduced to test-list vocabulary because the PR controls the workflow that wrote it.](0301-a-red-pr-names-its-failing-tests-in-a-commit-status.md) | GDS / shipping pipeline |
|
|
396
|
+
| 0302 | [**The third identical failure stops the session and asks** ([task 1003990](https://cloudbongos.com/builders#/task/1003990), goal 1000095). Sessions looped without noticing: one PR re-shipped into the same red check nine times, and 45 of 169 claim attempts were the same refusal retried minutes apart. A PostToolUse hook now counts walls per session — the signature is the `[otb-plain]` card's "What happened" line + the task id + the RED line, so a red check naming different failing tests each run reads as progress — and on the third identical one injects a single instruction: stop retrying, diagnose (path named), or /ask-for-help. Waiting cards ("Nothing to do…") are never counted; git-guard and worktree-guard count their own blocks through the same helper; it never blocks a tool call and echoes nothing a tool printed. Rejected: counting any repeated failing command (red→green is that), blocking the fourth attempt (a new gate, ADR 0162), server-side detection (cannot see guard blocks or speak into the session).](0302-the-third-identical-failure-stops-the-session-and-asks.md) | GDS / sessions / hooks |
|
package/docs/file-map.md
CHANGED
|
@@ -490,6 +490,8 @@ To install on a new machine, symlink each routine's directory under `~/.claude/s
|
|
|
490
490
|
├── conductor.js ← UserPromptSubmit: MAS Conductor advisory + dispatch directive (#427/#439); self-gates on OTB_CONDUCTOR_OFF / OTB_SUBAGENT
|
|
491
491
|
├── session-cards.js ← UserPromptSubmit: deterministic delivery of READ-ONLY in-session cards (builder-start, status) — pre-renders the card + injects a one-step render directive (task 1288)
|
|
492
492
|
├── lifecycle-card.js ← PostToolUse: deterministic delivery of MUTATING lifecycle cards (claim/ship/release) — the write-side mirror of session-cards.js (task 1288)
|
|
493
|
+
├── stuck-detector.js ← PostToolUse + PostToolUseFailure (Bash|PowerShell): the third time one session hits the same wall — the same `[otb-plain]` card for the same task id, or the same red check — it injects ONE instruction: stop retrying, diagnose (path named), or /ask-for-help. Never blocks; silent with no card; kill-switch BONGOS_STUCK_DETECTOR_OFF=1 (task 1003990)
|
|
494
|
+
├── stuck-strikes.js ← shared helper, not a hook: the per-session strike counter (hashed signatures in os.tmpdir()) + the static instruction text; stuck-detector.js, git-guard.js and worktree-guard.js all count through it (task 1003990)
|
|
493
495
|
├── pre-compact.js ← PreCompact: thin reader around eviction-policy.js — emits an eviction directive (blocks to drop + one-line recovery stubs) at the compaction seam (task 1349)
|
|
494
496
|
├── eviction-policy.js ← pure deterministic in-session compaction classifier (transcript turns → eviction set + replacement stubs); no I/O, unit-tested in tests/eviction_policy.mjs; consumed by pre-compact.js (task 1348)
|
|
495
497
|
└── stop-refcheck.js ← Stop: deterministic backstop that catches a bare `#NNN` Bongos ref in live session text (autolinks to a 404 GitHub issue) and asks for the clickable form (follow-on to task 929)
|
|
@@ -2148,5 +2148,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2148
2148
|
landed since 1.19.835 with no explicit bump. run 35247495964. (task 1002620)
|
|
2149
2149
|
1.19.837 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2150
2150
|
landed since 1.19.836 with no explicit bump. run 35248928789. (task 1002620)
|
|
2151
|
+
1.19.838 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2152
|
+
landed since 1.19.837 with no explicit bump. run 35250225228. (task 1002620)
|
|
2151
2153
|
---------------------------------------------------------------------------
|
|
2152
2154
|
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
-- agents_003_output_ref_idx.sql — the index the DEPTH GUARD reads (task 1002494).
|
|
2
|
+
--
|
|
3
|
+
-- agents_001 gave `agents_runs` three indexes, each built for a question someone
|
|
4
|
+
-- was already asking: per-agent history, walk-forward from a trigger, and the
|
|
5
|
+
-- monthly spend rollup. `output_ref` was not one of them, because until now
|
|
6
|
+
-- nothing read it as a KEY — it was a pointer you followed after you already had
|
|
7
|
+
-- the row.
|
|
8
|
+
--
|
|
9
|
+
-- The event-router reads it the other way round. Its loop guard asks "does any
|
|
10
|
+
-- run's output_ref name this ship?" (`WHERE output_ref = ANY($1::text[])`) on
|
|
11
|
+
-- EVERY fan-out that gets past the touches[] pre-filter — and `agents_runs` is
|
|
12
|
+
-- append-only, growing with every fire AND every refusal, so without this the
|
|
13
|
+
-- guard is a sequential scan over a table that only ever gets longer. The guard
|
|
14
|
+
-- is also FAIL-CLOSED: a read slow enough to time out reads as "attributed" and
|
|
15
|
+
-- silently stops agents firing at all, which is the failure mode that looks like
|
|
16
|
+
-- nothing is wrong.
|
|
17
|
+
--
|
|
18
|
+
-- PARTIAL, on `output_ref IS NOT NULL`. Most rows have none — every no-go is a
|
|
19
|
+
-- row (a refusal that leaves no trace is indistinguishable from a fire that
|
|
20
|
+
-- never happened), and a successful fire with nothing to report writes none
|
|
21
|
+
-- either, which is the outcome most fires should have. The lookup only ever
|
|
22
|
+
-- matches a non-null value, so the nulls are dead weight in the index exactly as
|
|
23
|
+
-- agents_001's own spend index argues about its own nulls.
|
|
24
|
+
--
|
|
25
|
+
-- NOT UNIQUE, deliberately. Two agents may each report on the same ship, and the
|
|
26
|
+
-- `discord` sink's pointer is `discord:<channel>:<taskId>` — stable by
|
|
27
|
+
-- construction, so a re-post of the same subject collides by design. A unique
|
|
28
|
+
-- index would turn a legitimate second observation into an insert failure inside
|
|
29
|
+
-- a fire that already cost money.
|
|
30
|
+
--
|
|
31
|
+
-- Module migrations are ADDITIVE and NAMESPACED (ADR 0083 §Decision #5): the
|
|
32
|
+
-- object is agents_-prefixed, there is no down-migration, and the filename is
|
|
33
|
+
-- agents_-prefixed (ADR 0108 §5). Idempotent: safe to re-run.
|
|
34
|
+
|
|
35
|
+
BEGIN;
|
|
36
|
+
|
|
37
|
+
CREATE INDEX IF NOT EXISTS agents_runs_output_ref_idx
|
|
38
|
+
ON agents_runs (output_ref)
|
|
39
|
+
WHERE output_ref IS NOT NULL;
|
|
40
|
+
|
|
41
|
+
COMMIT;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"coreVersion": "^1.19.0",
|
|
6
6
|
"default": false,
|
|
7
7
|
"maintenance": { "status": "core-maintained" },
|
|
8
|
-
"contributes": { "routes": ["agents"], "migrations": true },
|
|
8
|
+
"contributes": { "routes": ["agents"], "pollers": ["event-router"], "migrations": true },
|
|
9
9
|
"spend": { "requiresPayer": true },
|
|
10
10
|
"provides": [],
|
|
11
11
|
"consumes": ["grade"]
|