@tyhld/conductor 0.12.83 → 0.12.85
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/autoupdate-flags.js +62 -0
- package/dist/cli.js +17 -1
- package/dist/headless.js +84 -1
- package/dist/relay.js +51 -0
- package/dist/selfcheck.js +743 -0
- package/dist/view-stream.js +33 -8
- package/package.json +2 -1
- package/scripts/dist-source.sh +60 -10
- package/scripts/hooks/skill_sync_notify.py +8 -1
- package/scripts/hooks/test_skill_sync_notify.py +8 -0
- package/scripts/tyhld-selfcheck.sh +58 -0
- package/scripts/update-guard.sh +2 -1
- package/systemd/tyhld-selfcheck.service +23 -0
- package/systemd/tyhld-selfcheck.timer +19 -0
package/dist/view-stream.js
CHANGED
|
@@ -411,6 +411,7 @@ export class FollowSession {
|
|
|
411
411
|
waitingNoted = false;
|
|
412
412
|
oldRelayNoted = false;
|
|
413
413
|
unreadableNoted = false;
|
|
414
|
+
troubleNoted = false;
|
|
414
415
|
/** 道具の呼び出し(id)→ 道具の名前。結果の行を日本語でまとめるために覚えておく。 */
|
|
415
416
|
toolNames = new Map();
|
|
416
417
|
constructor(deps) {
|
|
@@ -431,19 +432,43 @@ export class FollowSession {
|
|
|
431
432
|
rawPath(commandId, attempt) {
|
|
432
433
|
return (this.deps.rawPath ?? rawLogPath)(commandId, attempt);
|
|
433
434
|
}
|
|
434
|
-
/**
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
435
|
+
/**
|
|
436
|
+
* 何かでつまずいても、英語の難しい文のまま落ちないようにする。
|
|
437
|
+
* ★黙って固まらない・理由と次の1手を日本語で出す(えふさん確定の決まり)。
|
|
438
|
+
*/
|
|
439
|
+
safely(what, fn) {
|
|
440
|
+
try {
|
|
441
|
+
fn();
|
|
440
442
|
}
|
|
441
|
-
|
|
442
|
-
this.
|
|
443
|
+
catch (err) {
|
|
444
|
+
if (this.troubleNoted)
|
|
445
|
+
return;
|
|
446
|
+
this.troubleNoted = true;
|
|
447
|
+
const why = err instanceof Error ? err.message : String(err);
|
|
448
|
+
this.out(`※${what}でつまずきました(${clip(maskSecrets(why), 80)})。`);
|
|
449
|
+
this.out(' 次の1手:Ctrl+C で閉じて、もう一度開いてください。何度も出るならサポートへこの画面をお送りください。');
|
|
443
450
|
}
|
|
444
451
|
}
|
|
452
|
+
/** 開いたときの1回:いまの状態 → これまでの流れ → 以後は poll で続く。 */
|
|
453
|
+
open() {
|
|
454
|
+
this.safely('画面の用意', () => {
|
|
455
|
+
this.out(this.header());
|
|
456
|
+
const active = this.active();
|
|
457
|
+
if (active !== null) {
|
|
458
|
+
this.beginFollow(active, { announce: false, backlog: true });
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
this.noteWaiting();
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
445
465
|
/** 1周ぶん。便の切れ目と、増えた記録だけを出す。 */
|
|
446
466
|
poll() {
|
|
467
|
+
this.safely('様子の読み取り', () => {
|
|
468
|
+
this.pollOnce();
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
pollOnce() {
|
|
447
472
|
const active = this.active();
|
|
448
473
|
if (active === null) {
|
|
449
474
|
if (this.cur !== null) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tyhld/conductor",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.85",
|
|
4
4
|
"description": "采配くん管制の見守りアプリ(conductor-agent)。各PCで常駐し、中央(devlog-tracker)へ定期的に生存報告(heartbeat)を送る常駐CLI。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"scripts/update-guard.sh",
|
|
23
23
|
"scripts/dist-source.sh",
|
|
24
24
|
"scripts/conductor-run.sh",
|
|
25
|
+
"scripts/tyhld-selfcheck.sh",
|
|
25
26
|
"scripts/kc.sh",
|
|
26
27
|
"scripts/codex",
|
|
27
28
|
"!scripts/codex/__pycache__",
|
package/scripts/dist-source.sh
CHANGED
|
@@ -208,18 +208,66 @@ except Exception:
|
|
|
208
208
|
pass' "$pj" 2>/dev/null
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
#
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
# 配布物を動かしている node と【同じ場所の npm】を返す(見つからなければ空・返り 1)。
|
|
212
|
+
# 【なぜ要るか(実機 2026-10-02・ノートPC・便 3ed9e2b2 の発見1)】
|
|
213
|
+
# 毎時同期(tyhld-guard-sync)は systemd の中で動く。そこの PATH には nvm の node も npm も無く、
|
|
214
|
+
# /usr/bin/npm も /usr/local/bin/npm も無い機があった。裸の `npm view` が毎回「見つからない」で
|
|
215
|
+
# 失敗し、それを「回線」と記録していた=番人・鉄則が1度も配られていなかった。
|
|
216
|
+
# 【どう決めるか】配布物の置き場から node を決め(dist_node_for=常駐と同じ node)、
|
|
217
|
+
# その node の隣(同じ bin)の npm を使う。node が近道(/usr/local/bin/node → nvm)なら実体を辿る。
|
|
218
|
+
# それでも無いときだけ PATH の npm を使う(人が打ったとき)。
|
|
219
|
+
dist_npm_for() {
|
|
220
|
+
local root="$1" node real n
|
|
221
|
+
node="$(dist_node_for "$root" 2>/dev/null)" || node=''
|
|
222
|
+
if [[ -n "$node" ]]; then
|
|
223
|
+
for n in "$node" "$(readlink -f "$node" 2>/dev/null)"; do
|
|
224
|
+
[[ -n "$n" && -x "$(dirname "$n")/npm" ]] || continue
|
|
225
|
+
printf '%s' "$(dirname "$n")/npm"
|
|
226
|
+
return 0
|
|
227
|
+
done
|
|
228
|
+
fi
|
|
229
|
+
real="$(type -P npm 2>/dev/null || true)"
|
|
230
|
+
[[ -n "$real" ]] && { printf '%s' "$real"; return 0; }
|
|
231
|
+
return 1
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
#: 公開版の問い合わせができなかった理由(dist_published_query が入れる)。
|
|
235
|
+
#: no-npm … 問い合わせに使う npm が見つからない
|
|
236
|
+
#: unverifiable … npm は在るが、問い合わせに失敗した(回線・取得先・npm の不調のどれか)
|
|
237
|
+
DIST_PUBLISHED_ERR=''
|
|
238
|
+
#: 問い合わせに使った npm(記録と画面に出す)。
|
|
239
|
+
DIST_NPM=''
|
|
240
|
+
|
|
241
|
+
# 公開 npm が「いま配っている版」を DIST_PUBLISHED に入れる(取れなければ空+DIST_PUBLISHED_ERR)。
|
|
242
|
+
# ★固定の下限は使わない(便 9858450b)。★$(…) の中で呼ばない(結果を変数で返すため)。
|
|
243
|
+
dist_published_query() {
|
|
244
|
+
local root="${1:-}" v
|
|
245
|
+
DIST_PUBLISHED=''; DIST_PUBLISHED_ERR=''; DIST_NPM=''
|
|
246
|
+
# ★検査用の入口。空文字を入れれば「問い合わせに失敗した」を作れる(網を切らずに確かめる)。
|
|
214
247
|
if [[ -n "${CONDUCTOR_DIST_PUBLISHED+x}" ]]; then
|
|
215
|
-
|
|
248
|
+
DIST_PUBLISHED="$CONDUCTOR_DIST_PUBLISHED"
|
|
249
|
+
[[ -n "$DIST_PUBLISHED" ]] || DIST_PUBLISHED_ERR='unverifiable'
|
|
216
250
|
return 0
|
|
217
251
|
fi
|
|
218
|
-
|
|
219
|
-
|
|
252
|
+
DIST_NPM="$(dist_npm_for "$root")" || DIST_NPM=''
|
|
253
|
+
if [[ -z "$DIST_NPM" ]]; then
|
|
254
|
+
DIST_PUBLISHED_ERR='no-npm'
|
|
255
|
+
return 0
|
|
256
|
+
fi
|
|
257
|
+
# ★npm は `#!/usr/bin/env node` で始まる。PATH の先頭に同じ場所を足して、同じ node で動かす。
|
|
258
|
+
v="$(PATH="$(dirname "$DIST_NPM"):${PATH:-}" "$DIST_NPM" view "$CONDUCTOR_PKG" version "$CONDUCTOR_REGISTRY_ARG" 2>/dev/null | tr -d '[:space:]')"
|
|
220
259
|
if [[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
|
221
|
-
|
|
260
|
+
DIST_PUBLISHED="${BASH_REMATCH[0]}"
|
|
261
|
+
else
|
|
262
|
+
DIST_PUBLISHED_ERR='unverifiable'
|
|
222
263
|
fi
|
|
264
|
+
return 0
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
# 公開 npm が「いま配っている版」(取れなければ空)。★昔からの呼び方を残す。
|
|
268
|
+
dist_published_version() {
|
|
269
|
+
dist_published_query "${1:-}"
|
|
270
|
+
printf '%s' "$DIST_PUBLISHED"
|
|
223
271
|
}
|
|
224
272
|
|
|
225
273
|
# 配ってよい中身の置き場を決める。
|
|
@@ -228,7 +276,8 @@ dist_published_version() {
|
|
|
228
276
|
# 理由の語(記録にそのまま載る)
|
|
229
277
|
# not-installed … 配布物がこの機に入っていない
|
|
230
278
|
# no-version … 入っている配布物の版が読めない
|
|
231
|
-
#
|
|
279
|
+
# no-npm … 公開 npm に問い合わせる npm が見つからない(配布物の node の隣にも PATH にも無い)
|
|
280
|
+
# unverifiable … npm は在るが、公開 npm への問い合わせに失敗した(回線・取得先・npm の不調)
|
|
232
281
|
# version-drift … 入っている版が公開 npm のいまの版と違う
|
|
233
282
|
dist_source_resolve() {
|
|
234
283
|
DIST_ROOT=''; DIST_VERSION=''; DIST_PUBLISHED=''; DIST_REASON=''
|
|
@@ -244,10 +293,11 @@ dist_source_resolve() {
|
|
|
244
293
|
DIST_REASON='no-version'
|
|
245
294
|
return 1
|
|
246
295
|
fi
|
|
247
|
-
|
|
296
|
+
dist_published_query "$root"
|
|
248
297
|
if [[ -z "$DIST_PUBLISHED" ]]; then
|
|
249
298
|
# ★ここで「まあいいか」と配らない。問い合わせられない=正規版かどうか分からない、である。
|
|
250
|
-
|
|
299
|
+
# ★理由は「npm が無い」と「問い合わせに失敗した」を分ける(回線と言い切らない)。
|
|
300
|
+
DIST_REASON="${DIST_PUBLISHED_ERR:-unverifiable}"
|
|
251
301
|
return 1
|
|
252
302
|
fi
|
|
253
303
|
if [[ "$DIST_VERSION" != "$DIST_PUBLISHED" ]]; then
|
|
@@ -121,8 +121,15 @@ def recovery_steps(reason):
|
|
|
121
121
|
if reason in ('version-drift', 'not-installed', 'incomplete'):
|
|
122
122
|
return [f'再開のしかた: この PC で次の順に打ってください。① {REINSTALL}',
|
|
123
123
|
f' ② {RESYNC}']
|
|
124
|
+
if reason == 'no-npm':
|
|
125
|
+
# ★回線のせいにしない(便 b7bd5e43)。常駐の中から npm が見つからなかっただけ。
|
|
126
|
+
# 人が打つと、常駐が使う置き場の控え(~/.tyhld/bin/runtime-root)が書き直され、
|
|
127
|
+
# 次からはその node の隣の npm で問い合わせられる。
|
|
128
|
+
return ['再開のしかた: 公開 npm に問い合わせる npm が、この PC の常駐からは見つかりませんでした'
|
|
129
|
+
'(回線の問題ではありません)。この PC で次の1行を打ってください。',
|
|
130
|
+
f' {RESYNC}']
|
|
124
131
|
if reason == 'unverifiable':
|
|
125
|
-
return ['再開のしかた: 公開 npm
|
|
132
|
+
return ['再開のしかた: 公開 npm への問い合わせに失敗しました(回線・取得先・npm の不調のどれか)。'
|
|
126
133
|
'この PC の通信(回線・取得先の設定)を確かめてから、次を打ってください。',
|
|
127
134
|
f' {RESYNC}']
|
|
128
135
|
return [f'再開のしかた: この PC で次の1行を打ってください。 {RESYNC}']
|
|
@@ -305,6 +305,14 @@ with tempfile.TemporaryDirectory() as tmp:
|
|
|
305
305
|
'npm install -g' in net, False)
|
|
306
306
|
check_true('公開npmに聞けない: 配り直しの1行は載る', 'APPLY=1 bash' in net)
|
|
307
307
|
|
|
308
|
+
# ★npm が見つからないだけのときに「回線」と言い切らない(便 b7bd5e43)。
|
|
309
|
+
nonpm = body_for('no-npm')
|
|
310
|
+
check_true('npmが無い: npm が見つからないと書く', 'npm が' in nonpm and '見つかりませんでした' in nonpm)
|
|
311
|
+
check_true('npmが無い: 回線の問題ではないと書く', '回線の問題ではありません' in nonpm)
|
|
312
|
+
check('npmが無い: 通信を確かめさせない', '通信(回線' in nonpm, False)
|
|
313
|
+
check('npmが無い: 入れ直しは案内しない', 'npm install -g' in nonpm, False)
|
|
314
|
+
check_true('npmが無い: 配り直しの1行は載る', 'APPLY=1 bash' in nonpm)
|
|
315
|
+
|
|
308
316
|
plain = body_for('write-failed', what='craftsman-skill')
|
|
309
317
|
check('書けなかった: 入れ直しは案内しない', 'npm install -g' in plain, False)
|
|
310
318
|
check_true('書けなかった: 配り直しの1行だけ', 'APPLY=1 bash' in plain)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# tyhld-selfcheck — この機の自己診断を1回流す入口(便 b7bd5e43・設計 3ed9e2b2 の A1)。
|
|
3
|
+
#
|
|
4
|
+
# 【置き場】~/.tyhld/bin/tyhld-selfcheck(★職人は書けない場所)。隣に dist-source.sh が要る
|
|
5
|
+
# (常駐の入口 conductor-run と同じ置き場・同じ探し方)。置くのは自社PCの導入台本(次の便 A3)か人。
|
|
6
|
+
# ★お客さまの機の導入台本(sales-template/install.sh・setup.sh)は置かない。
|
|
7
|
+
#
|
|
8
|
+
# 【使い方】
|
|
9
|
+
# ~/.tyhld/bin/tyhld-selfcheck --now … 人が1回だけ流す(きっかけ manual)
|
|
10
|
+
# ~/.tyhld/bin/tyhld-selfcheck --trigger daily … 毎日のタイマー(tyhld-selfcheck.timer)
|
|
11
|
+
# ~/.tyhld/bin/tyhld-selfcheck --trigger after-conductor … 更新係が conductor を上げた直後(次の便)
|
|
12
|
+
# ほかに after-claude / after-rollback。--json で機械が読む形、--no-send で管制へ送らない。
|
|
13
|
+
# 終了コード: 0=PASS / 1=FAIL / 2=使い方の誤り / 78=動かす采配くんが見つからない
|
|
14
|
+
#
|
|
15
|
+
# 【決め】
|
|
16
|
+
# ・動かすのは常駐と同じ「公開済みの配布物」(作業ツリーは動かさない=dist_runtime_resolve)。
|
|
17
|
+
# ・副作用なし(commit・push・PR・合流・配備・公開をしない)。中身は src/selfcheck.ts。
|
|
18
|
+
# ・接続設定は systemd が EnvironmentFile で渡す。人が打ったときは ~/.conductor.env から
|
|
19
|
+
# CONDUCTOR_URL と CONDUCTOR_TOKEN の2つだけを読む(★値は画面に出さない)。
|
|
20
|
+
set -u
|
|
21
|
+
|
|
22
|
+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
. "$HERE/dist-source.sh"
|
|
24
|
+
|
|
25
|
+
ARGS=()
|
|
26
|
+
SAW_TRIGGER=0
|
|
27
|
+
while (( $# > 0 )); do
|
|
28
|
+
case "$1" in
|
|
29
|
+
--now) ;; # きっかけ manual(既定)。書かれていても同じ
|
|
30
|
+
--trigger) SAW_TRIGGER=1; ARGS+=("$1" "${2:-}"); shift ;;
|
|
31
|
+
*) ARGS+=("$1") ;;
|
|
32
|
+
esac
|
|
33
|
+
shift
|
|
34
|
+
done
|
|
35
|
+
(( SAW_TRIGGER == 1 )) || ARGS+=(--trigger manual)
|
|
36
|
+
|
|
37
|
+
if ! dist_runtime_resolve; then
|
|
38
|
+
echo "[tyhld-selfcheck] 流せません: 動かす采配くんを確かめられません(${DIST_REASON})。" >&2
|
|
39
|
+
echo "[tyhld-selfcheck] 人の手番: npm install -g @tyhld/conductor --@tyhld:registry=https://registry.npmjs.org" >&2
|
|
40
|
+
exit 78
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# 接続設定(2つだけ)。★systemd から呼ばれたときは既に入っているので読まない。
|
|
44
|
+
ENV_FILE="${HOME:-}/.conductor.env"
|
|
45
|
+
if [[ ( -z "${CONDUCTOR_URL:-}" || -z "${CONDUCTOR_TOKEN:-}" ) && -r "$ENV_FILE" ]]; then
|
|
46
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
47
|
+
line="${line#export }"
|
|
48
|
+
case "$line" in
|
|
49
|
+
CONDUCTOR_URL=*|CONDUCTOR_TOKEN=*|CONDUCTOR_MACHINE=*)
|
|
50
|
+
key="${line%%=*}"; val="${line#*=}"
|
|
51
|
+
val="${val%\"}"; val="${val#\"}"; val="${val%\'}"; val="${val#\'}"
|
|
52
|
+
[[ -n "${!key:-}" ]] || export "$key=$val"
|
|
53
|
+
;;
|
|
54
|
+
esac
|
|
55
|
+
done < "$ENV_FILE"
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
exec "$DIST_NODE" "$DIST_ROOT/dist/cli.js" selfcheck "${ARGS[@]}"
|
package/scripts/update-guard.sh
CHANGED
|
@@ -347,7 +347,8 @@ if ! dist_source_resolve; then
|
|
|
347
347
|
case "$DIST_REASON" in
|
|
348
348
|
not-installed) warn " この機に @tyhld/conductor が入っていません。" ;;
|
|
349
349
|
no-version) warn " 入っている配布物の版が読めません。" ;;
|
|
350
|
-
|
|
350
|
+
no-npm) warn " 公開 npm に問い合わせる npm が見つかりません(配布物を動かす node の隣にも、PATH にもありません)。" ;;
|
|
351
|
+
unverifiable) warn " 公開 npm への問い合わせに失敗しました(npm: ${DIST_NPM:-不明}。回線・取得先・npm の不調のどれか)。" ;;
|
|
351
352
|
version-drift) warn " 入っている版 ${DIST_VERSION} が、公開 npm のいまの版 ${DIST_PUBLISHED} と違います。" ;;
|
|
352
353
|
esac
|
|
353
354
|
warn " 人の手番: npm install -g @tyhld/conductor --@tyhld:registry=https://registry.npmjs.org"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# tyhld-selfcheck.service — この機の自己診断を1回流す(便 b7bd5e43・設計 3ed9e2b2 の A1)。
|
|
2
|
+
#
|
|
3
|
+
# 【何をするか】~/.tyhld/bin/tyhld-selfcheck --trigger daily を1回流すだけ(中身は src/selfcheck.ts)。
|
|
4
|
+
# ・6項目(conductor 起動/Claude Code 起動/管制との通信/囲い/GitHub・npm/小さな headless 試験)+番人
|
|
5
|
+
# ・副作用なし(commit・push・PR・合流・配備・公開をしない)。結果は手元の控えと管制へ。
|
|
6
|
+
# ・正常時は何も知らせない(知らせるかどうかは管制が決める)。
|
|
7
|
+
#
|
|
8
|
+
# 【★自社PCだけ】置いて有効にするのは自社PCの導入台本(次の便 A3)か人の窓。
|
|
9
|
+
# sales-template/install.sh・setup.sh はこのタイマーを置かない(お客さまの機には入れない)。
|
|
10
|
+
# .timer から毎日1回呼ばれる(tyhld-selfcheck.timer)。
|
|
11
|
+
|
|
12
|
+
[Unit]
|
|
13
|
+
Description=tyhld: daily self-check (conductor / Claude Code / central / sandbox / network / headless)
|
|
14
|
+
After=network-online.target
|
|
15
|
+
Wants=network-online.target
|
|
16
|
+
|
|
17
|
+
[Service]
|
|
18
|
+
Type=oneshot
|
|
19
|
+
EnvironmentFile=%h/.conductor.env
|
|
20
|
+
ExecStart=/bin/bash %h/.tyhld/bin/tyhld-selfcheck --trigger daily
|
|
21
|
+
# 小さな試験の上限(3分)+外への問い合わせの分。
|
|
22
|
+
TimeoutStartSec=15min
|
|
23
|
+
Nice=10
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# tyhld-selfcheck.timer — 上の自己診断を毎日1回起動する(ADR-026 の9・便 b7bd5e43)。
|
|
2
|
+
#
|
|
3
|
+
# - OnCalendar=daily 12:30 … 昼に1回(電源が入っている時間帯に寄せる)。
|
|
4
|
+
# - Persistent=true … PCが消えていて取りこぼした分は、次回起動後に1度だけ追い実行。
|
|
5
|
+
# - RandomizedDelaySec … 複数の機が同じ時刻に Claude を呼ばないよう30分ばらす。
|
|
6
|
+
# ★管制は「26時間来ない機」を🟡にする想定(設計 3ed9e2b2 の 2/4)。
|
|
7
|
+
#
|
|
8
|
+
# ★自社PCだけ。有効にするのは自社PCの導入台本(次の便 A3)か人の窓(お客さまの機には入れない)。
|
|
9
|
+
|
|
10
|
+
[Unit]
|
|
11
|
+
Description=tyhld: daily self-check
|
|
12
|
+
|
|
13
|
+
[Timer]
|
|
14
|
+
OnCalendar=*-*-* 12:30:00
|
|
15
|
+
Persistent=true
|
|
16
|
+
RandomizedDelaySec=30min
|
|
17
|
+
|
|
18
|
+
[Install]
|
|
19
|
+
WantedBy=timers.target
|