Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ After `./scripts/setup.sh`, recommended one-shot startup:
Use this when you want the full tmux-backed operator workflow, browser PTT, terminal mirror, hidden mobile recovery, and the safest default bridge wiring.

- `run-operator-once.sh` / `run-operator-stack.sh` launch `face-app`, and `face-app` starts `tts-worker` by default unless `FACE_TTS_ENABLED=0` is set. `qwen3` / `qwen3-realtime` profiles work by passing `TTS_ENGINE=qwen3` into that spawned worker path.
- Profile shorthand:
- `--profile default`: Kokoro TTS + batch ASR only
- `--profile realtime`: Kokoro TTS + Voxtral realtime ASR + Parakeet fallback
- `--profile qwen3`: Qwen3 TTS + batch ASR only
- `--profile qwen3-realtime`: Qwen3 TTS + Voxtral realtime ASR + Parakeet fallback
- When you use this app to work on another repository, put a project-local `AGENTS.md` in that target repository too. Start from `doc/examples/AGENTS.sample.md`, then customize the repo-specific build/test/run rules there.
- For another repository, you can start the operator in either of these equivalent styles:
- run from this repository and pass `--repo /path/to/target-repo`
Expand Down Expand Up @@ -606,6 +611,11 @@ tailscale serve --bg 8765
これは、tmux 連携、browser PTT、terminal mirror、隠し復旧、bridge の安全な既定配線まで含む、いちばん実用的な構成です。

- `run-operator-once.sh` / `run-operator-stack.sh` は `face-app` を起動し、その `face-app` が既定で `tts-worker` を子起動します。`FACE_TTS_ENABLED=0` を指定しない限り、別ターミナルでの TTS 起動は不要です。`qwen3` / `qwen3-realtime` profile は、この子起動 worker に `TTS_ENGINE=qwen3` を渡して切り替えます。
- profile の意味:
- `--profile default`: Kokoro TTS + batch ASR のみ
- `--profile realtime`: Kokoro TTS + Voxtral realtime ASR + Parakeet fallback
- `--profile qwen3`: Qwen3 TTS + batch ASR のみ
- `--profile qwen3-realtime`: Qwen3 TTS + Voxtral realtime ASR + Parakeet fallback
- このアプリを使って別の作業リポジトリを扱う場合は、その target repository 側にも project-local な `AGENTS.md` を置いてください。`doc/examples/AGENTS.sample.md` を出発点にして、その repo 固有の build/test/run ルールを追記するのが簡単です。
- 別の作業リポジトリで使う起動方法は、次の 2 通りが実用的です。
- このリポジトリ側から `--repo /path/to/target-repo` を付けて起動する
Expand Down
2 changes: 1 addition & 1 deletion asr-worker/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "asr-worker"
version = "1.11.0"
version = "1.12.0"
description = "Local ASR worker for english-trainer (Parakeet EN/JA routing)"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
2 changes: 1 addition & 1 deletion asr-worker/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions doc/examples/AGENTS.sample.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Paste this into your project `AGENTS.md` and customize.
- Helpers report to the owner, not directly to the user.
- `agent.focus` changes visibility only; it does not transfer ownership.
- Review helpers should default to read-only missions.
- Use helpers when the work splits cleanly: implementation, review/findings, or one bounded investigation.
- Prefer staying single-agent for tiny one-file edits or narrow wording changes where helper overhead would dominate.
- Prefer one bounded helper mission at a time such as "one finding or done", then follow up only if needed.
- If a helper reports late after timing out, treat the report as real work product first; do not assume the delivery path is fully broken.

## Helper reporting discipline (recommended)

Expand All @@ -40,6 +44,10 @@ Paste this into your project `AGENTS.md` and customize.
- After the first report succeeds, inspect the owner-provided target files before optional `/skills`, slash commands, or unrelated repo exploration unless blocked without them.
- After the first report succeeds, continue the work and later report `done` or `review_findings`.
- Once you have the bounded answer for the current pass, send the final `done` or `review_findings` report before extra prompts, `/skills`, or follow-up exploration.
- If this is a narrow review or investigation pass, return the first qualifying finding immediately instead of continuing to hunt for more.
- If `max_findings` is `1` or the completion criteria say "one finding or done", stop after the first qualifying result and report it immediately.
- If no qualifying finding appears within the scoped pass or timebox, send `done` with a concise no-findings summary instead of lingering silently.
- After your final `done` or `review_findings` report, stop and wait for the owner instead of continuing exploration on your own.
- If the owner gave `target_paths`, `completion_criteria`, `timebox_minutes`, or `max_findings`, treat them as active mission constraints.
- If the owner gave `target_paths`, read those exact stream-root/source-repo paths first instead of hunting for mirrored copies inside your helper worktree.

Expand Down
9 changes: 9 additions & 0 deletions doc/examples/AGENT_RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ This preserves freshness even for similar text.
- Helpers report to the owner, not to the user. Only the current user-facing owner asks the user for input or approval.
- `agent.focus` changes visibility only; it does not transfer ownership.
- Review helpers should default to read-only missions unless the owner explicitly chooses otherwise.
- Prefer spinning up a reviewer helper when the owner expects non-trivial code edits, broad config/docs changes, or a risky cross-cutting patch.
- Prefer spinning up an investigation helper when one bounded question can be answered independently while the owner continues another path.
- Prefer staying single-agent when the task is a tiny one-file edit, a narrowly scoped wording change, or anything where mission overhead would exceed the likely parallelism gain.
- Prefer one bounded helper mission at a time over a broad "review everything" request. Ask helpers for one finding or done, then follow up only if needed.
- If a helper acknowledges late (`acked_late`) after a timeout, treat that as evidence the mission eventually reached the helper. Review or resolve the report before concluding the delivery path is broken.

## 9. Helper reporting discipline

Expand All @@ -130,6 +135,10 @@ This preserves freshness even for similar text.
- After the first report succeeds, inspect the owner-provided target files before optional `/skills`, slash commands, or unrelated repo exploration unless you are blocked without them.
- After the first report succeeds, continue the requested work. On completion, report `done` or `review_findings`.
- Once you have a bounded answer that satisfies the current completion criteria, send the final `done` or `review_findings` report before any extra prompts, `/skills`, or follow-up exploration.
- If this is a narrow review or investigation pass, return the first qualifying finding immediately instead of continuing to hunt for more.
- If `max_findings` is `1` or the completion criteria say "one finding or done", stop after the first qualifying result and report it immediately.
- If no qualifying finding appears within the scoped pass or timebox, send `done` with a concise no-findings summary instead of lingering silently.
- After your final `done` or `review_findings` report, stop and wait for the owner instead of continuing exploration on your own.
- If the owner provided `target_paths`, stay on those paths first.
- Treat owner-provided `target_paths` as stream-root/source-repo anchored, even when they point outside your helper worktree.
- If the owner provided `completion_criteria`, follow them exactly.
Expand Down
14 changes: 14 additions & 0 deletions doc/guides/operator-stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ Use `./scripts/run-operator-once.sh --profile qwen3-realtime` when you want the

Use `./scripts/run-operator-stack.sh` directly only when you intentionally want to manage tmux pane targeting and startup wiring yourself.

Profile shorthand for `run-operator-once.sh`:

- `--profile default`: Kokoro TTS + batch ASR only
- `--profile realtime`: Kokoro TTS + Voxtral realtime ASR + Parakeet fallback
- `--profile qwen3`: Qwen3 TTS + batch ASR only
- `--profile qwen3-realtime`: Qwen3 TTS + Voxtral realtime ASR + Parakeet fallback

### Quick start

Minimal face-only path:
Expand Down Expand Up @@ -323,6 +330,13 @@ Wrong pane is mirrored on mobile:

`run-operator-once.sh` を使うと、これらのうち重要な接続先は自動で安全に埋まります。

`run-operator-once.sh` の profile 対応:

- `--profile default`: Kokoro TTS + batch ASR のみ
- `--profile realtime`: Kokoro TTS + Voxtral realtime ASR + Parakeet fallback
- `--profile qwen3`: Qwen3 TTS + batch ASR のみ
- `--profile qwen3-realtime`: Qwen3 TTS + Voxtral realtime ASR + Parakeet fallback

### ASR モード

ASR は 2 系統あります。
Expand Down
56 changes: 28 additions & 28 deletions face-app/dist/agent_assignment_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,43 +143,43 @@ export function renderAssignmentPrompt(assignment) {
const streamRoot = deriveStreamRoot(assignment.stream_id);
const targetPaths = formatTargetPaths(assignment.target_paths);
const targetPathDescription = describeTargetPaths(targetPaths, streamRoot);
const protocolLines = [
`1. Before reading repo files, skills, or running broad exploration, call the agent.report MCP tool (shown in some clients as minimum_headroom.agent_report) with stream_id=${assignment.stream_id}, mission_id=${assignment.mission_id}, owner_agent_id=${assignment.owner_agent_id}, from_agent_id=${assignment.agent_id}, kind=progress, summary='Mission accepted'.`,
'2. Wait until that first report call succeeds.',
'3. If blocked or uncertain, send blocked or question to the owner instead of asking the user directly.',
'4. Inspect the target paths before optional skill lookup, slash commands, or unrelated repo exploration unless blocked without them.',
'5. Send done or review_findings as soon as the current completion criteria are satisfied.',
'6. If this is a narrow review or investigation pass, return the first qualifying finding immediately instead of hunting for more.',
'7. If no qualifying finding appears within the stated scope or timebox, send done with a short no-findings summary instead of lingering.',
'8. After your final done/review_findings report, stop and wait for the owner.'
];
const shapingLines = [
`- Stream root: ${streamRoot ?? '(not available)'}.`,
`- Target paths are stream-root anchored: ${targetPathDescription}.`,
'- Read the exact target path under the stream root even if it sits outside your helper worktree.',
`- Timebox: ${assignment.timebox_minutes ?? '(not specified)'} minute(s).`,
`- Completion criteria: ${assignment.completion_criteria ?? '(not specified)'}.`,
`- Max findings this pass: ${assignment.max_findings ?? '(not specified)'}.`,
'- If max_findings is 1 or the completion criteria say "one finding or done", stop after the first qualifying result and report it immediately.',
'- If the scope is still ambiguous after the first report, send question instead of broad repo exploration.'
];
const explicitPrompt = asNonEmptyString(assignment.prompt_text);
if (explicitPrompt) {
const lines = [
`Owner assignment for helper agent ${assignment.agent_id}.`,
'Bootstrap protocol (follow in order):',
`1. Before reading repo files, skills, or running broad exploration, call the agent.report MCP tool (shown in some clients as minimum_headroom.agent_report) with stream_id=${assignment.stream_id}, mission_id=${assignment.mission_id}, owner_agent_id=${assignment.owner_agent_id}, from_agent_id=${assignment.agent_id}, kind=progress, summary='Mission accepted'.`,
'2. Wait until that first report call succeeds.',
'3. After the first report succeeds, use the minimum-headroom-ops skill if it is available and relevant.',
'4. If you cannot accept the mission as written, send blocked or question to the owner instead of asking the user directly.',
'5. Keep the first pass narrow. Do not broaden the scope silently.',
'6. When the work is complete, send done or review_findings back to the owner.',
'7. After the first report succeeds, inspect the target paths before optional skill lookup, slash commands, or unrelated repo exploration unless the mission is blocked without them.',
'8. As soon as you have a bounded answer that satisfies the completion criteria, send the final done/review_findings report before any further prompts, /skills, or extra exploration.',
'Immediate protocol:',
...protocolLines,
'Execution shaping:',
`- Stream root for this mission: ${streamRoot ?? '(not available)'}.`,
`- If target_paths are given, treat them as stream-root anchored paths first: ${targetPathDescription}.`,
'- If a target path is outside your helper worktree but still under the stream root, inspect it there directly instead of broad repo exploration.',
`- If a timebox is given, stop and report by then: ${assignment.timebox_minutes ?? '(not specified)'} minute(s).`,
`- If completion criteria are given, follow them exactly: ${assignment.completion_criteria ?? '(not specified)'}.`,
`- If max_findings is given, return no more than that many findings on this pass: ${assignment.max_findings ?? '(not specified)'}.`,
'- If the scope is still ambiguous after the first report, send question instead of broad repo exploration.',
...shapingLines,
'Mission body:',
explicitPrompt
];
return lines.join('\n');
}
const lines = [
`Owner assignment for helper agent ${assignment.agent_id}.`,
'Bootstrap protocol (follow in order):',
`1. Before reading repo files, skills, or running broad exploration, call the agent.report MCP tool (shown in some clients as minimum_headroom.agent_report) with stream_id=${assignment.stream_id}, mission_id=${assignment.mission_id}, owner_agent_id=${assignment.owner_agent_id}, from_agent_id=${assignment.agent_id}, kind=progress, summary='Mission accepted'.`,
'2. Wait until that first report call succeeds.',
'3. After the first report succeeds, use the minimum-headroom-ops skill if it is available and relevant.',
'4. If blocked or uncertain, report blocked or question to the owner instead of asking the user directly.',
'5. Keep the first pass narrow. Do not broaden the scope silently.',
'6. When the work is complete, send done or review_findings back to the owner.',
'7. After the first report succeeds, inspect the target paths before optional skill lookup, slash commands, or unrelated repo exploration unless the mission is blocked without them.',
'8. As soon as you have a bounded answer that satisfies the completion criteria, send the final done/review_findings report before any further prompts, /skills, or extra exploration.'
'Immediate protocol:',
...protocolLines
];
if (streamRoot) {
lines.push(`Stream root: ${streamRoot}`);
Expand Down Expand Up @@ -215,10 +215,10 @@ export function renderAssignmentPrompt(assignment) {
lines.push('Scoping rules:');
lines.push('- Start with the minimum files or commands needed to answer the goal.');
lines.push('- If target paths are given, do not roam outside them without explaining why in your next report.');
lines.push('- When a target path lives outside your helper worktree but under the stream root, inspect that exact path instead of guessing a mirrored location.');
lines.push('- Read the target paths before optional /skills or slash-command detours unless you are blocked without them.');
lines.push('- Prefer returning one concrete result quickly unless the owner explicitly asked for a broader sweep.');
lines.push('- Once you have the bounded result for this pass, report it immediately before any extra prompts or follow-up exploration.');
lines.push('- If max_findings is 1 or the completion criteria say "one finding or done", stop after the first qualifying result and report it immediately.');
lines.push('- If no qualifying finding appears within the scoped pass, send done with a concise no-findings summary instead of waiting silently.');
lines.push('- After your final done/review_findings report, stop and wait for the owner instead of continuing exploration on your own.');
lines.push('- If the mission is ambiguous after the first report, send question instead of exploring broadly.');
lines.push('Begin now.');
return lines.join('\n');
Expand Down
6 changes: 4 additions & 2 deletions face-app/dist/agent_assignment_state.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from 'node:fs';
import path from 'node:path';

const SCHEMA_VERSION = 1;
const DELIVERY_STATES = new Set(['pending', 'sent_to_tmux', 'acked', 'failed', 'timeout']);
const DELIVERY_STATES = new Set(['pending', 'sent_to_tmux', 'acked', 'acked_late', 'failed', 'timeout']);

function toLogger(log) {
if (!log) {
Expand Down Expand Up @@ -219,6 +219,7 @@ function buildSummary(assignments) {
pending: 0,
sent_to_tmux: 0,
acked: 0,
acked_late: 0,
failed: 0,
timeout: 0
},
Expand All @@ -232,6 +233,7 @@ function buildSummary(assignments) {
pending: 0,
sent_to_tmux: 0,
acked: 0,
acked_late: 0,
failed: 0,
timeout: 0
};
Expand Down Expand Up @@ -548,7 +550,7 @@ export function createAgentAssignmentStateStore(options = {}) {
assignment.last_report_kind = kind;
assignment.last_report_at = ts;
assignment.last_error = null;
assignment.delivery_state = 'acked';
assignment.delivery_state = assignment.delivery_state === 'timeout' ? 'acked_late' : 'acked';
assignment.acked_at = ts;
assignment.ack_deadline_at = 0;
assignment.updated_at = ts;
Expand Down
Loading
Loading