peertable 0.4.13 → 0.4.14
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/README.ja.md +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
- package/room/client.mjs +2 -1
- package/skill/scripts/parent-watch-logic.mjs +11 -0
- package/skill/scripts/parent-watch.mjs +31 -5
- package/skill/templates/parent.md +4 -2
package/README.ja.md
CHANGED
|
@@ -107,7 +107,7 @@ Codex では、スキルが所有する room MCP block をプロジェクトの
|
|
|
107
107
|
|
|
108
108
|
動いており、**自分自身の開発に使っている**。2026-08-08 に end-to-end 検証済み——オーケストレーターなしの完全な一周(2 メンバーが相談し、claim し、インターフェースを交渉し、見つけた罠を共有して小さなプロジェクトを出荷)を**外部介入ゼロ**で完走。2026-08-13の実席ライフサイクルでは、作業席が親を通じてsession contextを保ったままmodel / effortを変更し、再起動後はroomと工程正本から再着任した。2026-08-14にはGrok 4.6席の着席、room参加、同一sessionの4.6↔4.5変更、DM起床を実機で確認した。2026-08-17にGrok席はidle待ち、broadcastは本文を残し、tmuxの無い親でbridge cursorが止まらないよう直した。
|
|
109
109
|
|
|
110
|
-
現在のnpm releaseは **peertable 0.4.
|
|
110
|
+
現在のnpm releaseは **peertable 0.4.14**。
|
|
111
111
|
|
|
112
112
|
設計文書と決定履歴(**91 決定**)は [docs/plan.md](docs/plan.md)。
|
|
113
113
|
|
package/README.md
CHANGED
|
@@ -143,7 +143,7 @@ It interviews you, names the members, scaffolds `.team/` (charter + roles, isola
|
|
|
143
143
|
|
|
144
144
|
Working, and used to build itself. First verified end-to-end on 2026-08-08 with a full no-orchestrator loop: two members consulted, claimed, negotiated an interface, shared a discovered pitfall, and shipped a small project with **zero external intervention**. A 2026-08-13 real-seat lifecycle verified in-place model/effort changes and restart recovery. On 2026-08-14, a Grok 4.6 seat joined the room, changed 4.6↔4.5 in the same session, and woke on a direct message in a live acceptance run. On 2026-08-17 the wake-up path was corrected so Grok seats wait for idle, broadcasts keep their body, and a parent without a tmux seat cannot stall the bridge cursor.
|
|
145
145
|
|
|
146
|
-
The current npm release is **peertable 0.4.
|
|
146
|
+
The current npm release is **peertable 0.4.14**.
|
|
147
147
|
|
|
148
148
|
The design document and decision log (**91 decisions**, in Japanese) live in [docs/plan.md](docs/plan.md).
|
|
149
149
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "peertable",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.14",
|
|
4
4
|
"description": "A round table of peer agents. No orchestrator at the head. Turn Claude Code, Codex, and Grok sessions into a team of equal, long-lived peers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/room/client.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
11
11
|
|
|
12
12
|
// client.mjs 側のハードコード版数。package.json の version と一致していることを
|
|
13
13
|
// diagnostics の version_consistency が見る(2 つの版数源の drift 検出。決定45)
|
|
14
|
-
const MCP_VERSION = '0.4.
|
|
14
|
+
const MCP_VERSION = '0.4.14'
|
|
15
15
|
const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
|
|
16
16
|
|
|
17
17
|
const USAGE = `usage:
|
|
@@ -297,6 +297,7 @@ async function runDiagnostics(asJson) {
|
|
|
297
297
|
'scripts/seat-identity.mjs',
|
|
298
298
|
'scripts/pid-alive.mjs',
|
|
299
299
|
'scripts/parent-watch.mjs',
|
|
300
|
+
'scripts/parent-watch-logic.mjs',
|
|
300
301
|
'scripts/seat-credential.mjs',
|
|
301
302
|
'scripts/ensure-room-mcp.mjs',
|
|
302
303
|
'scripts/leave-seat.sh',
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function latticeStaffingChanged(previous, next) {
|
|
2
|
+
if (!next || next.error) return false
|
|
3
|
+
if (!previous || previous.error) return true
|
|
4
|
+
return previous.ready !== next.ready || previous.active !== next.active
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function addressedToParent(message, parent) {
|
|
8
|
+
return message?.from !== parent
|
|
9
|
+
&& (message?.to === 'all' || message?.to === parent
|
|
10
|
+
|| (Array.isArray(message?.to_names) && message.to_names.includes(parent)))
|
|
11
|
+
}
|
|
@@ -11,6 +11,7 @@ import { execFileSync } from 'node:child_process'
|
|
|
11
11
|
import { existsSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs'
|
|
12
12
|
import { join } from 'node:path'
|
|
13
13
|
import { resolveLatticeExecutable } from './seat-usage.mjs'
|
|
14
|
+
import { addressedToParent as messageAddressedToParent, latticeStaffingChanged } from './parent-watch-logic.mjs'
|
|
14
15
|
|
|
15
16
|
const args = process.argv.slice(2)
|
|
16
17
|
const project = args.shift()
|
|
@@ -154,9 +155,17 @@ function releaseLock() {
|
|
|
154
155
|
acquireLock()
|
|
155
156
|
process.on('exit', releaseLock)
|
|
156
157
|
|
|
157
|
-
const addressedToParent = message => message
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
const addressedToParent = message => messageAddressedToParent(message, parent)
|
|
159
|
+
|
|
160
|
+
function exitWhenParentStdinCloses() {
|
|
161
|
+
if (mode !== '--follow') return
|
|
162
|
+
const stdin = process.stdin
|
|
163
|
+
if (!stdin || stdin.destroyed) return
|
|
164
|
+
const quit = () => process.exit(0)
|
|
165
|
+
stdin.on('end', quit)
|
|
166
|
+
stdin.on('close', quit)
|
|
167
|
+
if (typeof stdin.resume === 'function') stdin.resume()
|
|
168
|
+
}
|
|
160
169
|
|
|
161
170
|
async function writeEvent(event) {
|
|
162
171
|
await new Promise((resolve, reject) => {
|
|
@@ -180,8 +189,7 @@ async function acceptLatticeState(next) {
|
|
|
180
189
|
})
|
|
181
190
|
return true
|
|
182
191
|
}
|
|
183
|
-
const changed =
|
|
184
|
-
&& previous.ready + previous.active !== next.ready + next.active
|
|
192
|
+
const changed = latticeStaffingChanged(previous, next)
|
|
185
193
|
state = { ...state, lattice: next, last_event_at: now() }
|
|
186
194
|
saveState(state)
|
|
187
195
|
if (!changed) return false
|
|
@@ -241,11 +249,29 @@ if (mode === '--next' && (!Number.isFinite(nextWindowMs) || nextWindowMs < 100))
|
|
|
241
249
|
process.exit(2)
|
|
242
250
|
}
|
|
243
251
|
|
|
252
|
+
exitWhenParentStdinCloses()
|
|
253
|
+
|
|
244
254
|
let consecutiveFailures = 0
|
|
255
|
+
let snapshotSent = false
|
|
245
256
|
for (;;) {
|
|
246
257
|
const deadline = mode === '--next' ? Date.now() + nextWindowMs : Number.POSITIVE_INFINITY
|
|
247
258
|
try {
|
|
248
259
|
if (await catchUp()) process.exit(0)
|
|
260
|
+
if (mode === '--follow' && !snapshotSent) {
|
|
261
|
+
snapshotSent = true
|
|
262
|
+
const lattice = state.lattice
|
|
263
|
+
await writeEvent({
|
|
264
|
+
schema: 'peertable.parent-watch-event.v1',
|
|
265
|
+
type: 'parent_watch_snapshot',
|
|
266
|
+
parent,
|
|
267
|
+
last_seq: state.last_seq,
|
|
268
|
+
ready: lattice?.ready ?? null,
|
|
269
|
+
active: lattice?.active ?? null,
|
|
270
|
+
body: lattice && !lattice.error
|
|
271
|
+
? staffingBody(lattice)
|
|
272
|
+
: '親番犬を張り直した。room の親宛と工程件数を追従する。',
|
|
273
|
+
})
|
|
274
|
+
}
|
|
249
275
|
const controller = new AbortController()
|
|
250
276
|
const remaining = Number.isFinite(deadline) ? Math.max(1, deadline - Date.now()) : null
|
|
251
277
|
const timer = remaining === null ? null : setTimeout(() => controller.abort(), remaining)
|
|
@@ -54,8 +54,10 @@ export は親 shell に伝播しないため**、これをしないまま `latti
|
|
|
54
54
|
張り替え時は旧Monitorを止めてから起動する。
|
|
55
55
|
|
|
56
56
|
どちらも`parent-join.sh`が先に作る`.team/parent-watch.json`のcursorを共有する。watcher不在中のDMは
|
|
57
|
-
次回起動時にcatch-upされ、親以外宛・親自身の発言・ping
|
|
58
|
-
|
|
57
|
+
次回起動時にcatch-upされ、親以外宛・親自身の発言・pingでは親を起こさない。Lattice の ready 件数と
|
|
58
|
+
active 件数は合計ではなくそれぞれ変化したら起こす(実装が全部閉じて親手番1件だけになっても起こす)。
|
|
59
|
+
`--follow` は親セッションの stdin が閉じたら終了する。切れた番犬が seq だけ進めて親が起きない状態を作らない。
|
|
60
|
+
`watch_error`が届いたら通常のDMとして扱わず、番犬の再着卓を行う。
|
|
59
61
|
|
|
60
62
|
## 試験結果の監査
|
|
61
63
|
|