merge: integrate orchestration branch

This commit is contained in:
Keisuke Hirata 2026-06-20 21:16:54 +09:00
commit 448a24a975
No known key found for this signature in database
10 changed files with 511 additions and 20 deletions

View File

@ -0,0 +1 @@
{"id":"orch-plan-20260620-120740-1","ticket_id":"00001KVJA7V2R","kind":"accepted_plan","accepted_plan":{"summary":"`WebFetch` が `application/pdf` を `pdf-extract` により page-delimited Markdown-ish text (`pdf_text_by_pages`) として返せるようにする。既存 HTML/text/JSON/XML behavior と network safety/output bounds は維持し、semantic Markdown/OCR/native dependency は導入しない。","branch":"impl/00001KVJA7V2R-webfetch-pdf-text","worktree":"/home/hare/Projects/yoi/.worktree/00001KVJA7V2R-webfetch-pdf-text","role_plan":"Orchestrator は Profile scope review と並行して専用 implementation worktree `.worktree/00001KVJA7V2R-webfetch-pdf-text` を作成し、Coder をその child worktree への narrow write scope で起動する。Coder 実装後、Reviewer が WebFetch safety bounds、PDF binary path separation、metadata/output truncation、dependency/Nix impact、HTML/text regression を確認する。"},"author":"yoi-orchestrator","at":"2026-06-20T12:07:40Z"}

View File

@ -1,8 +1,8 @@
--- ---
title: 'WebFetch: PDF を page-delimited text として取得できるようにする' title: 'WebFetch: PDF を page-delimited text として取得できるようにする'
state: 'queued' state: 'inprogress'
created_at: '2026-06-20T10:46:48Z' created_at: '2026-06-20T10:46:48Z'
updated_at: '2026-06-20T12:06:29Z' updated_at: '2026-06-20T12:09:50Z'
assignee: null assignee: null
readiness: 'implementation_ready' readiness: 'implementation_ready'
risk_flags: ['security', 'dependency', 'public-api', 'output-bounds'] risk_flags: ['security', 'dependency', 'public-api', 'output-bounds']

View File

@ -29,4 +29,79 @@ Intake 済み。Orchestrator は implementation routing として扱える。実
Ticket を `workspace-panel` が queued にしました。 Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-20T12:08:15Z -->
## Decision
Routing decision: implementation_ready_parallel
Reason:
- Panel Queue により、この Ticket は Orchestrator routing 対象として明示許可された。
- User standing directive: blocker が無いものは並列実行する。現在の `00001KVJABS1A` は Profile scope review 中であり、WebFetch PDF 実装とは domain/file conflict がないため並列化できる。
- Ticket body は調査済みの PDF extraction 方針、`pdf-extract` 採用理由、binary path 分離、page-delimited Markdown-ish output、metadata、bounds、non-goals、validation を実装可能な粒度で定義している。
- 未解決 relation blocker はない。
- Orchestrator worktree は clean、matching branch/worktree はなし。
- Risk domain は security / dependency / public-api / output-bounds だが、Ticket は existing WebFetch network safety、`max_response_bytes` / `max_output_bytes`、unsupported binary rejection、no OCR/semantic Markdown/native dependency を明示している。bounded context check 後も implementation 前に必要な追加 human decision は見つからなかった。
Evidence checked:
- Ticket `00001KVJA7V2R` body / thread / relations / artifacts。
- `TicketRelationQuery(00001KVJA7V2R)`: no blockers。
- `TicketOrchestrationPlanQuery(00001KVJA7V2R)`: no previous plan records; accepted plan recorded now。
- Workspace state:
- Orchestrator worktree clean at `36b9ed45`
- queued: `00001KVJA7V2R`, `00001KVJDJD02`
- inprogress: `00001KVJABS1A` review only。
- no matching WebFetch PDF branch/worktree。
IntentPacket:
Intent:
- Extend `WebFetch` so `application/pdf` can be fetched and returned as bounded, page-delimited text suitable for LLM reading。
- Use `pdf_extract::extract_text_from_mem_by_pages()` and present output as Markdown-ish page sections, not semantic PDF-to-Markdown。
Binding decisions / invariants:
- Keep WebFetch as fetch/extraction tool; no summarization or research orchestration。
- PDF bytes must not go through the UTF-8 text / `reject_binary()` path。
- Preserve private/local host rejection, bounded redirects, Content-Length / `max_response_bytes`, `max_output_bytes`, embedded credential rejection, untrusted content warning。
- Initial supported MIME is `application/pdf` only; no extension sniffing or `application/octet-stream` PDF guessing。
- No Poppler/Pdfium/subprocess/native dependency/OCR/scanned-PDF support/table reconstruction/cache。
- Existing HTML/text/JSON/XML behavior and `html_extraction` metadata must not regress。
- New metadata should use `pdf_extraction` with method/pages/readable/diagnostic information。
Requirements / acceptance criteria:
- Valid PDF returns `## Page 1`, `## Page 2`, etc. page-delimited bounded text。
- `transformed_as` communicates `pdf_text_by_pages` or equivalent, not semantic Markdown。
- `output_truncated` is correct when PDF text exceeds `max_output_bytes`
- Malformed/encrypted/textless PDFs do not panic; return diagnostic error or readable=false metadata。
- Non-PDF unsupported binary remains rejected。
- Focused WebFetch tests and relevant cargo/fmt/diff validation pass。
Next action:
- Record `queued -> inprogress` and commit Ticket records before creating implementation worktree and spawning Coder。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-20T12:08:34Z from: queued to: inprogress reason: orchestrator_acceptance_parallel_webfetch_pdf field: state -->
## State changed
Ticket body/thread, relation metadata, Orchestrator worktree state, visible Pods, existing branch/worktree, and bounded WebFetch/PDF context were checked. There is no unresolved blocking dependency, no conflicting inprogress implementation, and no missing planning decision. Accepting this queued Ticket for parallel implementation before worktree/Pod side effects.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-20T12:09:50Z -->
## Implementation report
Implementation orchestration start:
- Acceptance records were committed on Orchestrator branch: `e752a720 ticket: accept webfetch pdf and intake gate`
- Created implementation worktree `/home/hare/Projects/yoi/.worktree/00001KVJA7V2R-webfetch-pdf-text` on branch `impl/00001KVJA7V2R-webfetch-pdf-text` at `e752a720`
- Spawned Coder Pod `yoi-coder-00001KVJA7V2R` with write scope limited to the implementation worktree and read-only root scope only for runtime workspace identity。
- Coder task explicitly forbids root/original workspace implementation, semantic PDF Markdown/OCR/native dependency scope creep, merge, Ticket close, and cleanup。
Next action:
- Wait for Coder implementation report, then inspect branch diff/validation evidence and route to Reviewer。
--- ---

View File

@ -1,8 +1,8 @@
--- ---
title: 'Profile launch should preserve override scope allowances' title: 'Profile launch should preserve override scope allowances'
state: 'inprogress' state: 'closed'
created_at: '2026-06-20T10:48:57Z' created_at: '2026-06-20T10:48:57Z'
updated_at: '2026-06-20T12:06:19Z' updated_at: '2026-06-20T12:13:32Z'
assignee: null assignee: null
queued_by: 'workspace-panel' queued_by: 'workspace-panel'
queued_at: '2026-06-20T11:52:33Z' queued_at: '2026-06-20T11:52:33Z'

View File

@ -0,0 +1,35 @@
## Resolution
`00001KVJABS1A` を完了しました。
実装内容:
- Profile launch policy が `manifest.scope` を wholesale replacement しないように修正しました。
- 既に解決済みの Profile / workspace override scope に対して、launch-policy default rules を missing rules として append するようにしました。
- `.yoi/override.local.toml` 等で指定された追加 `scope.allow` / `scope.deny` は保持されます。
- Normal launch の workspace root write scope と `.worktree` write deny は維持されます。
- Ticket role launch の default direct scope / delegation defaults は維持されます。
- Final manifest/snapshot と tool-visible scope が同じ final effective scope を見るように維持しました。
- Restore path は existing `resolved_manifest_snapshot` を使う挙動のままで、override 再評価は追加していません。
主な commit:
- `0717aae3 pod: preserve profile override scope`
- `a1386881 merge: profile override scope`
Review:
- r1 は `approve`
- Reviewer は scope merge semantics、no authority broadening、workspace write / `.worktree` deny preservation、Ticket role defaults、snapshot/tool-visible scope consistency、restore non-goal preservation を確認しました。
最終 validation:
- `cargo fmt --all --check`
- `git diff --check HEAD^1..HEAD`
- `cargo test -p pod entrypoint::tests::`
- `cargo check -p pod`
Known unrelated note:
- Full `cargo test -p pod` は branch 外の既存 prompt-guidance assertion failure で失敗するため final gate にしませんでした。Reviewer はこの failure が `crates/pod/src/entrypoint.rs` の diff に起因しないことを確認済みです。
Nix validation:
- Not run because no dependency/package/source-filter files changed。
Validation log:
- `/run/user/1000/yoi/yoi-orchestrator/bash-output/bash-WNUQvw.log`

View File

@ -152,3 +152,154 @@ Next action:
- Dispatch Reviewer for r1 review against Ticket requirements, with focus on scope allow/deny merge semantics, authority boundary/no broadening beyond explicit override + defaults, workspace write / `.worktree` deny preservation, Ticket role policy preservation, snapshot/tool-visible scope consistency, and whether the full `cargo test -p pod` failure is unrelated/pre-existing。 - Dispatch Reviewer for r1 review against Ticket requirements, with focus on scope allow/deny merge semantics, authority boundary/no broadening beyond explicit override + defaults, workspace write / `.worktree` deny preservation, Ticket role policy preservation, snapshot/tool-visible scope consistency, and whether the full `cargo test -p pod` failure is unrelated/pre-existing。
--- ---
<!-- event: plan author: yoi-orchestrator at: 2026-06-20T12:07:00Z -->
## Plan
Review dispatch:
- Spawned Reviewer Pod `yoi-reviewer-00001KVJABS1A-r1` against implementation branch `impl/00001KVJABS1A-profile-override-scope`
- Review target commit: `0717aae3 pod: preserve profile override scope`
- Review baseline: `72e9f2f1`
- Reviewer task focuses on scope allow/deny merge semantics, no authority broadening beyond explicit override + launch defaults, workspace write / `.worktree` deny preservation, Ticket role launch/delegation constraints, metadata snapshot/effective scope consistency, restore non-goal, and reported full `cargo test -p pod` failure triage。
- Reviewer is instructed not to edit source, commit, merge, close the Ticket, or use TicketReview directly; it will report verdict/evidence back to Orchestrator。
---
<!-- event: review author: yoi-reviewer-00001KVJABS1A-r1 at: 2026-06-20T12:12:10Z status: approve -->
## Review: approve
Verdict: `approve`
確認範囲:
- Ticket contract / Orchestrator IntentPacket。
- Implementation diff: `72e9f2f1..0717aae3`
- 変更ファイル: `crates/pod/src/entrypoint.rs` のみ。
- Launch-policy change、snapshot/tool-visible scope path、restore path、focused tests を確認。
Approval evidence:
- `append_missing_rules` / `apply_scope_launch_defaults` により、launch-policy defaults は既に解決済みの Profile / override scope を置換せず、missing rules として append される。
- Normal launch は workspace-root write scope と `.worktree` write deny を引き続き append する。
- Ticket role launch は role-specific default direct scope と delegation defaults を引き続き適用する。
- `resolve_manifest()``apply_profile_launch_policy()` 後の final manifest を返す。
- `Pod::from_manifest_with_context``manifest.scope` から tool-visible scope を作る。
- Pod metadata snapshot serialization は final manifest を使う。
- Restore path は existing `resolved_manifest_snapshot` がある場合それを使うため、この変更で restore 時に override を再評価する挙動は入っていない。
- Focused tests は override-local `scope.allow` survival、normal profile launch defaults、Orchestrator role default scope/delegation preservation を cover している。
Blocking issues: none。
Non-blocking concerns / follow-ups:
- Full `cargo test -p pod` は以下 2 件の prompt-guidance assertion failure で失敗する。
- `prompt::catalog::tests::pod_orchestration_guidance_section_renders_resource_body`
- `prompt::system::tests::pod_orchestration_guidance_is_included_for_pod_management_tools`
- Missing asserted text: `"worktree status, diff, and test results"`
- Reviewer判断: この branch diff は `crates/pod/src/entrypoint.rs` のみであり、prompt rendering/assertion paths / prompt resources / catalog tests を変更していないため、この failure は unrelated/pre-existing。
Reviewer validation:
- `cargo fmt --all --check`: passed。
- `git diff --check 72e9f2f1..HEAD`: passed。
- `cargo test -p pod entrypoint::tests::`: passed, 22 tests。
- `cargo check -p pod`: passed。
- `cargo test -p pod`: unrelated prompt assertion failures only; 410 passed, 2 failed。
Worktree status at review end: clean。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-20T12:13:03Z -->
## Implementation report
Merge and final validation report:
Merged implementation branch into Orchestrator branch:
- Merge commit: `a1386881 merge: profile override scope`
- Implementation commit included:
- `0717aae3 pod: preserve profile override scope`
Reviewer outcome:
- r1 approved with no blocking issues。
- Reviewer confirmed explicit Profile/workspace override `scope.allow` preservation, no wholesale `manifest.scope` replacement, workspace root write / `.worktree` deny default preservation, Ticket role launch/delegation defaults, final snapshot/tool-visible scope consistency, and restore non-goal preservation。
Orchestrator validation after merge passed:
- `cargo fmt --all --check`
- `git diff --check HEAD^1..HEAD`
- `cargo test -p pod entrypoint::tests::`
- `cargo check -p pod`
Validation log:
- `/run/user/1000/yoi/yoi-orchestrator/bash-output/bash-WNUQvw.log`
Known unrelated validation note:
- Full `cargo test -p pod` was not used as a final gate because Reviewer confirmed unrelated/pre-existing prompt-guidance assertion failures outside this branch's diff。
Nix validation:
- Not run because this Ticket changed only Rust source in `crates/pod/src/entrypoint.rs` and no dependency/package/source-filter files changed。
Final state:
- Orchestrator worktree clean at `a1386881` after validation。
- Implementation worktree remains available for cleanup after Ticket completion records are committed。
- WebFetch PDF and Intake investigation gate Coder Pods continue in parallel。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-20T12:13:11Z from: inprogress to: done reason: merged_reviewed_validated field: state -->
## State changed
Implementation was merged into Orchestrator branch at `a1386881`, review approved, and final Orchestrator validation passed: `cargo fmt --all --check`, `git diff --check HEAD^1..HEAD`, `cargo test -p pod entrypoint::tests::`, and `cargo check -p pod`.
---
<!-- event: state_changed author: hare at: 2026-06-20T12:13:32Z from: done to: closed reason: closed field: state -->
## State changed
Ticket を closed にしました。
---
<!-- event: close author: hare at: 2026-06-20T12:13:32Z status: closed -->
## 完了
## Resolution
`00001KVJABS1A` を完了しました。
実装内容:
- Profile launch policy が `manifest.scope` を wholesale replacement しないように修正しました。
- 既に解決済みの Profile / workspace override scope に対して、launch-policy default rules を missing rules として append するようにしました。
- `.yoi/override.local.toml` 等で指定された追加 `scope.allow` / `scope.deny` は保持されます。
- Normal launch の workspace root write scope と `.worktree` write deny は維持されます。
- Ticket role launch の default direct scope / delegation defaults は維持されます。
- Final manifest/snapshot と tool-visible scope が同じ final effective scope を見るように維持しました。
- Restore path は existing `resolved_manifest_snapshot` を使う挙動のままで、override 再評価は追加していません。
主な commit:
- `0717aae3 pod: preserve profile override scope`
- `a1386881 merge: profile override scope`
Review:
- r1 は `approve`
- Reviewer は scope merge semantics、no authority broadening、workspace write / `.worktree` deny preservation、Ticket role defaults、snapshot/tool-visible scope consistency、restore non-goal preservation を確認しました。
最終 validation:
- `cargo fmt --all --check`
- `git diff --check HEAD^1..HEAD`
- `cargo test -p pod entrypoint::tests::`
- `cargo check -p pod`
Known unrelated note:
- Full `cargo test -p pod` は branch 外の既存 prompt-guidance assertion failure で失敗するため final gate にしませんでした。Reviewer はこの failure が `crates/pod/src/entrypoint.rs` の diff に起因しないことを確認済みです。
Nix validation:
- Not run because no dependency/package/source-filter files changed。
Validation log:
- `/run/user/1000/yoi/yoi-orchestrator/bash-output/bash-WNUQvw.log`
---

View File

@ -0,0 +1 @@
{"id":"orch-plan-20260620-120740-1","ticket_id":"00001KVJDJD02","kind":"accepted_plan","accepted_plan":{"summary":"Intake role prompt / ticket-intake workflow に Ticket 化前の最小調査ゲートを明示し、曖昧な依頼では既存 Ticket/docs/code/workflow 調査・draft提示・spike/requirements_sync判断を TicketCreate より前に行うよう model-facing instructionを補強する。","branch":"impl/00001KVJDJD02-intake-investigation-gate","worktree":"/home/hare/Projects/yoi/.worktree/00001KVJDJD02-intake-investigation-gate","role_plan":"Orchestrator は Profile scope review / WebFetch PDF 実装と並行して専用 implementation worktree `.worktree/00001KVJDJD02-intake-investigation-gate` を作成し、Coder をその child worktree への narrow write scope で起動する。Coder 実装後、Reviewer が prompt/workflow authority、Ticket化前調査 gate、draft/user-agreement/spike semantics、stale vocabulary removal、Intake role boundariesを確認する。"},"author":"yoi-orchestrator","at":"2026-06-20T12:07:40Z"}

View File

@ -1,8 +1,8 @@
--- ---
title: 'Intake workflow に Ticket 化前の調査ゲートを明示する' title: 'Intake workflow に Ticket 化前の調査ゲートを明示する'
state: 'queued' state: 'inprogress'
created_at: '2026-06-20T11:45:00Z' created_at: '2026-06-20T11:45:00Z'
updated_at: '2026-06-20T12:06:37Z' updated_at: '2026-06-20T12:16:24Z'
assignee: null assignee: null
readiness: 'implementation_ready' readiness: 'implementation_ready'
risk_flags: ['prompt-context', 'workflow-source', 'role-behavior', 'ticket-authority'] risk_flags: ['prompt-context', 'workflow-source', 'role-behavior', 'ticket-authority']

View File

@ -13,4 +13,135 @@ LocalTicketBackend によって作成されました。
Ticket を `workspace-panel` が queued にしました。 Ticket を `workspace-panel` が queued にしました。
---
<!-- event: decision author: yoi-orchestrator at: 2026-06-20T12:08:15Z -->
## Decision
Routing decision: implementation_ready_parallel
Reason:
- Panel Queue により、この Ticket は Orchestrator routing 対象として明示許可された。
- User standing directive: blocker が無いものは並列実行する。現在の `00001KVJABS1A` review と WebFetch PDF work とは別 domain の prompt/workflow resource修正であり、直接 conflict はないため並列化できる。
- Ticket body は Intake role prompt / workflow の弱点、Ticket 化前調査 gate、draft-before-create、user agreement gate、spike/requirements_sync handling、stale vocabulary removal、Intake boundaries を実装可能な粒度で定義している。
- 未解決 relation blocker はない。
- Orchestrator worktree は clean、matching branch/worktree はなし。
- Risk domain は prompt-context / workflow-source / role-behavior / ticket-authority だが、Ticket は Intake が coder/reviewer/helper Pod を起動しないこと、implementation routing/merge/closeをしないこと、user agreement without official Ticket create ruleを維持することを明示している。bounded context check 後も implementation 前に必要な追加 human decision は見つからなかった。
Evidence checked:
- Ticket `00001KVJDJD02` body / thread / relations / artifacts。
- `TicketRelationQuery(00001KVJDJD02)`: no blockers。
- `TicketOrchestrationPlanQuery(00001KVJDJD02)`: no previous plan records; accepted plan recorded now。
- Workspace state:
- Orchestrator worktree clean at `36b9ed45`
- queued: `00001KVJA7V2R`, `00001KVJDJD02`
- inprogress: `00001KVJABS1A` review only。
- no matching Intake workflow branch/worktree。
IntentPacket:
Intent:
- Strengthen Intake model-facing role/workflow guidance so ambiguous requests go through a minimum investigation gate before official Ticket creation。
- Make Intake separate user claims, confirmed facts, unverified hypotheses, and undecided points in drafts/Tickets。
Binding decisions / invariants:
- Intake remains non-scheduler and must not spawn coder/reviewer/read-only investigation helper Pods。
- Intake must not create implementation worktrees, route implementation/review, merge, or close。
- User agreement before official Ticket creation remains required。
- Do not save user claims, confirmed facts, unverified hypotheses, and undecided points as if they are all requirements。
- Preserve prompt/workflow resource boundaries between bundled resources and workspace override; explain intended differences if they remain。
- Remove or replace stale `Action required` / `Attention required` vocabulary in draft templates with current Ticket-operation language。
Requirements / acceptance criteria:
- Intake prompt/workflow explicitly states when to inspect existing Tickets / workflows / relevant files before TicketCreate。
- If investigation is needed, Intake can stop at draft / `spike_needed` / `requirements_sync_needed` rather than official Ticket creation。
- `resources/prompts/role/intake.md`, `resources/workflows/ticket-intake-workflow.md`, and `.yoi/workflow/ticket-intake-workflow.md` are reconciled or their differences are intentional/clear。
- Ticket作成前 user agreement rule is preserved。
- Validation includes prompt/workflow diff review and `git diff --check`; run TicketDoctor if Ticket consistency needs checking。
Next action:
- Record `queued -> inprogress` and commit Ticket records before creating implementation worktree and spawning Coder。
---
<!-- event: state_changed author: yoi-orchestrator at: 2026-06-20T12:08:34Z from: queued to: inprogress reason: orchestrator_acceptance_parallel_intake_investigation_gate field: state -->
## State changed
Ticket body/thread, relation metadata, Orchestrator worktree state, visible Pods, existing branch/worktree, and bounded Intake prompt/workflow context were checked. There is no unresolved blocking dependency, no conflicting inprogress implementation, and no missing planning decision. Accepting this queued Ticket for parallel implementation before worktree/Pod side effects.
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-20T12:09:50Z -->
## Implementation report
Implementation orchestration start:
- Acceptance records were committed on Orchestrator branch: `e752a720 ticket: accept webfetch pdf and intake gate`
- Created implementation worktree `/home/hare/Projects/yoi/.worktree/00001KVJDJD02-intake-investigation-gate` on branch `impl/00001KVJDJD02-intake-investigation-gate` at `e752a720`
- Spawned Coder Pod `yoi-coder-00001KVJDJD02` with write scope limited to the implementation worktree and read-only root scope only for runtime workspace identity。
- Coder task explicitly forbids root/original workspace implementation, Intake helper Pod spawning behavior changes, implementation routing/merge/close scope creep, merge, Ticket close, and cleanup。
Next action:
- Wait for Coder implementation report, then inspect branch diff/validation evidence and route to Reviewer。
---
<!-- event: implementation_report author: yoi-orchestrator at: 2026-06-20T12:16:24Z -->
## Implementation report
Coder implementation report received from `yoi-coder-00001KVJDJD02`.
Implementation commit:
- `1143ae1c workflow: add intake investigation gate`
Changed areas reported:
- `resources/prompts/role/intake.md`:
- Added explicit minimum investigation gate before `TicketCreate` / material refinement。
- Reinforced user agreement before official Ticket creation。
- Added separation of user claims, confirmed facts, unverified hypotheses, and undecided points。
- Preserved Intake non-scheduler boundaries: no coder/reviewer/helper Pods, no worktrees, no routing/merge/close。
- `resources/workflows/ticket-intake-workflow.md`:
- Expanded bundled workflow from thin pointer into concrete reusable Intake procedure。
- Added Ticket化前の最小調査ゲート。
- Added `spike_needed` / `requirements_sync_needed` draft stop behavior。
- Replaced stale `Action required` / `Attention required` draft wording with `Next Ticket operation`
- Added recommended Ticket body sections for claims/facts/hypotheses/open questions。
- Documented bundled-vs-workspace workflow boundary。
- `.yoi/workflow/ticket-intake-workflow.md`:
- Reconciled workspace override with bundled workflow while preserving dogfooding-specific details。
- Added explicit local investigation gate conditions and outputs。
- Updated draft template and Ticket body guidance。
- Clarified that workspace override may add Objective/split/local policy details but must not weaken bundled invariants。
Coder validation reported:
- `git diff --check`: passed。
- Stale vocabulary grep for `Action required` / `Attention required` in touched prompt/workflow files: no matches。
- Investigation-gate grep confirmed new terms are present:
- `minimum investigation gate`
- `Ticket 化前の最小調査ゲート`
- `spike_needed`
- `requirements_sync_needed`
- `Confirmed facts / sources`
- `Unverified hypotheses`
- `Undecided points / open questions`
- Workflow/prompt test search: no dedicated workflow prompt tests found; only unrelated Dashboard test reference。
- No code tests run because changes are prompt/workflow Markdown only。
Known risks / deferrals:
- No runtime schema/code changes were made。
- `.yoi/workflow/ticket-intake-workflow.md` intentionally remains a more detailed workspace override; bundled workflow is compact reusable baseline。
- `TicketDoctor` not run by Coder; no Ticket record structure was changed。
Orchestrator evidence checked before review dispatch:
- Implementation worktree is clean。
- HEAD is `1143ae1c`
- Diff from acceptance `e752a720..HEAD` is one implementation commit touching 3 files, 186 insertions / 19 deletions。
- `git diff --check e752a720..HEAD` produced no diagnostics。
Next action:
- Dispatch Reviewer for r1 review against Ticket requirements, with focus on model-facing Intake behavior, Ticket化前 investigation gate clarity, user-agreement preservation, stale vocabulary removal, bundled/workspace workflow boundary, and Intake non-scheduler boundaries。
--- ---

View File

@ -320,6 +320,21 @@ fn workspace_worktree_delegation(workspace_root: &Path) -> ScopeConfig {
} }
} }
fn append_missing_rules(target: &mut Vec<ScopeRule>, defaults: Vec<ScopeRule>) {
for rule in defaults {
if !target.contains(&rule) {
target.push(rule);
}
}
}
fn apply_scope_launch_defaults(scope: &mut ScopeConfig, defaults: ScopeConfig) {
// Profile resolution has already applied explicit profile/workspace override scope rules.
// Launch policy contributes runtime defaults on top rather than replacing those grants.
append_missing_rules(&mut scope.allow, defaults.allow);
append_missing_rules(&mut scope.deny, defaults.deny);
}
fn apply_profile_launch_policy( fn apply_profile_launch_policy(
manifest: &mut PodManifest, manifest: &mut PodManifest,
workspace_root: &Path, workspace_root: &Path,
@ -333,24 +348,28 @@ fn apply_profile_launch_policy(
}; };
match role { match role {
Some(TicketRole::Orchestrator) => { Some(TicketRole::Orchestrator) => {
manifest.scope = workspace_scope(workspace_root, Permission::Read, &[]); let default_scope = workspace_scope(workspace_root, Permission::Read, &[]);
apply_scope_launch_defaults(&mut manifest.scope, default_scope);
manifest.delegation_scope = workspace_worktree_delegation(workspace_root); manifest.delegation_scope = workspace_worktree_delegation(workspace_root);
} }
Some(TicketRole::Intake) | Some(TicketRole::Reviewer) => { Some(TicketRole::Intake) | Some(TicketRole::Reviewer) => {
manifest.scope = workspace_scope(workspace_root, Permission::Read, &[]); let default_scope = workspace_scope(workspace_root, Permission::Read, &[]);
apply_scope_launch_defaults(&mut manifest.scope, default_scope);
manifest.delegation_scope = ScopeConfig::default(); manifest.delegation_scope = ScopeConfig::default();
} }
Some(TicketRole::Coder) => { Some(TicketRole::Coder) => {
manifest.scope = workspace_scope(workspace_root, Permission::Write, &[]); let default_scope = workspace_scope(workspace_root, Permission::Write, &[]);
apply_scope_launch_defaults(&mut manifest.scope, default_scope);
manifest.delegation_scope = ScopeConfig::default(); manifest.delegation_scope = ScopeConfig::default();
} }
None => { None => {
let worktree_root = workspace_root.join(".worktree"); let worktree_root = workspace_root.join(".worktree");
manifest.scope = workspace_scope( let default_scope = workspace_scope(
workspace_root, workspace_root,
Permission::Write, Permission::Write,
std::slice::from_ref(&worktree_root), std::slice::from_ref(&worktree_root),
); );
apply_scope_launch_defaults(&mut manifest.scope, default_scope);
manifest.delegation_scope = workspace_worktree_delegation(workspace_root); manifest.delegation_scope = workspace_worktree_delegation(workspace_root);
} }
} }
@ -665,6 +684,22 @@ permission = "write"
) )
} }
fn scope_rule(target: &Path, permission: Permission) -> ScopeRule {
ScopeRule {
target: target.to_path_buf(),
permission,
recursive: true,
}
}
fn assert_scope_contains(rules: &[ScopeRule], target: &Path, permission: Permission) {
let expected = scope_rule(target, permission);
assert!(
rules.contains(&expected),
"expected scope rules to contain {expected:?}; got {rules:?}"
);
}
#[test] #[test]
fn user_manifest_flag_is_not_accepted() { fn user_manifest_flag_is_not_accepted() {
let err = Cli::try_parse_from(["yoi pod", "--user-manifest", "manifest.toml"]).unwrap_err(); let err = Cli::try_parse_from(["yoi pod", "--user-manifest", "manifest.toml"]).unwrap_err();
@ -754,6 +789,68 @@ permission = "write"
assert_eq!(manifest.worker.language, "manifest"); assert_eq!(manifest.worker.language, "manifest");
} }
#[test]
fn profile_launch_preserves_workspace_override_scope_allow_in_final_manifest() {
let tmp = TempDir::new().unwrap();
let workspace = tmp.path().join("runtime-workspace");
let external = tmp.path().join("external-readable");
let yoi_dir = workspace.join(".yoi");
std::fs::create_dir_all(&workspace).unwrap();
std::fs::create_dir_all(&external).unwrap();
std::fs::create_dir_all(&yoi_dir).unwrap();
write(
&yoi_dir.join("override.local.toml"),
&format!(
r#"
[[scope.allow]]
target = "{}"
permission = "read"
recursive = true
"#,
external.display()
),
);
let profile = tmp.path().join("profile.lua");
write(
&profile,
r#"
local yoi = require("yoi")
return yoi.profile {
slug = "override-scope",
model = { scheme = "anthropic", model_id = "test-model" },
}
"#,
);
let cli = Cli::try_parse_from([
"yoi pod",
"--workspace",
workspace.to_str().unwrap(),
"--profile",
profile.to_str().unwrap(),
])
.unwrap();
let (manifest, _loader) = resolve_manifest(&cli).unwrap();
let snapshot = serde_json::to_value(&manifest).unwrap();
let snapshot_scope: ScopeConfig =
serde_json::from_value(snapshot["scope"].clone()).unwrap();
assert_scope_contains(&manifest.scope.allow, &external, Permission::Read);
assert_scope_contains(&manifest.scope.allow, &workspace, Permission::Write);
assert_scope_contains(
&manifest.scope.deny,
&workspace.join(".worktree"),
Permission::Write,
);
assert_scope_contains(&snapshot_scope.allow, &external, Permission::Read);
assert_scope_contains(&snapshot_scope.allow, &workspace, Permission::Write);
assert_scope_contains(
&snapshot_scope.deny,
&workspace.join(".worktree"),
Permission::Write,
);
}
#[test] #[test]
fn profile_uses_selected_profile() { fn profile_uses_selected_profile() {
let tmp = TempDir::new().unwrap(); let tmp = TempDir::new().unwrap();
@ -883,15 +980,15 @@ permission = "write"
assert!(called); assert!(called);
assert_eq!(manifest.pod.name, "runtime-workspace"); assert_eq!(manifest.pod.name, "runtime-workspace");
assert_eq!(manifest.scope.allow.len(), 1); assert_eq!(manifest.scope.allow.len(), 2);
assert_eq!(manifest.scope.allow[0].target, workspace); assert_scope_contains(&manifest.scope.allow, tmp.path(), Permission::Write);
assert_eq!(manifest.scope.allow[0].permission, Permission::Write); assert_scope_contains(&manifest.scope.allow, &workspace, Permission::Write);
assert_eq!(manifest.scope.deny.len(), 1); assert_eq!(manifest.scope.deny.len(), 1);
assert_eq!( assert_scope_contains(
manifest.scope.deny[0].target, &manifest.scope.deny,
tmp.path().join("runtime-workspace/.worktree") &tmp.path().join("runtime-workspace/.worktree"),
Permission::Write,
); );
assert_eq!(manifest.scope.deny[0].permission, Permission::Write);
assert_eq!(manifest.delegation_scope.allow.len(), 2); assert_eq!(manifest.delegation_scope.allow.len(), 2);
assert_eq!( assert_eq!(
manifest.delegation_scope.allow[0].target, manifest.delegation_scope.allow[0].target,
@ -944,9 +1041,9 @@ permission = "write"
}) })
.unwrap(); .unwrap();
assert_eq!(manifest.scope.allow.len(), 1); assert_eq!(manifest.scope.allow.len(), 2);
assert_eq!(manifest.scope.allow[0].target, workspace); assert_scope_contains(&manifest.scope.allow, tmp.path(), Permission::Write);
assert_eq!(manifest.scope.allow[0].permission, Permission::Read); assert_scope_contains(&manifest.scope.allow, &workspace, Permission::Read);
assert!(manifest.scope.deny.is_empty()); assert!(manifest.scope.deny.is_empty());
assert_eq!(manifest.delegation_scope.allow.len(), 2); assert_eq!(manifest.delegation_scope.allow.len(), 2);
assert_eq!( assert_eq!(