feat: add dispatch_allow option to create_project_from_template #43

Closed
opened 2026-07-03 18:45:21 +00:00 by mathias · 1 comment
Owner

Goal

Add an optional dispatch_allow boolean parameter to the create_project_from_template tool. When true, inject a .dispatch-allow file into the generated repo so the new project is immediately opt-in for headless dispatch (per dispatch#3) without a manual follow-up commit.

Default false — creating a project stays dispatch-ineligible unless explicitly requested.

Context

create_project_from_template (internal/tools/create_project_from_template.go) currently does placeholder substitution over the generated tree but injects no new files. Dispatch eligibility requires a .dispatch-allow file on the default branch (see dispatch-sandbox/.dispatch-allow). Today that must be added by hand after creation. This closes that gap.

template_name already exists — do not add it.

Acceptance criteria

  • New optional arg dispatch_allow (bool, default false) in the input schema and createProjectArgs.
  • When true: after the substitution loop completes, inject .dispatch-allow at repo root on the resolved branch via the existing upsertRetry path (so it inherits the same infra#179 partial-failure handling).
  • The injected file content mirrors the sandbox convention: a short comment explaining that presence = dispatch-eligible, referencing dispatch#3.
  • The injected path is reported in files_substituted (or an equivalent field) so the caller sees it landed.
  • If injection fails because the branch isn't writable in time, it degrades exactly like substitution does today: surfaced in partial_failure, not a hard crash.
  • When dispatch_allow is false or omitted, behavior is byte-for-byte unchanged.
  • Descriptor description updated to mention the new arg.
  • Table-driven test coverage in create_project_from_template_test.go for both true (file injected) and false/omitted (no file) paths, following the existing test idiom (testify).
  • task check passes.

Out of scope

  • No change to template_name, substitution logic, or the infra#179 root cause.
  • Not solving the async-generate slowness — only ensuring .dispatch-allow rides the same best-effort path as everything else.
## Goal Add an optional `dispatch_allow` boolean parameter to the `create_project_from_template` tool. When `true`, inject a `.dispatch-allow` file into the generated repo so the new project is immediately opt-in for headless dispatch (per dispatch#3) without a manual follow-up commit. Default `false` — creating a project stays dispatch-ineligible unless explicitly requested. ## Context `create_project_from_template` (`internal/tools/create_project_from_template.go`) currently does placeholder substitution over the generated tree but injects no new files. Dispatch eligibility requires a `.dispatch-allow` file on the default branch (see `dispatch-sandbox/.dispatch-allow`). Today that must be added by hand after creation. This closes that gap. `template_name` already exists — do **not** add it. ## Acceptance criteria - New optional arg `dispatch_allow` (bool, default `false`) in the input schema and `createProjectArgs`. - When `true`: after the substitution loop completes, inject `.dispatch-allow` at repo root on the resolved `branch` via the existing `upsertRetry` path (so it inherits the same infra#179 partial-failure handling). - The injected file content mirrors the sandbox convention: a short comment explaining that presence = dispatch-eligible, referencing dispatch#3. - The injected path is reported in `files_substituted` (or an equivalent field) so the caller sees it landed. - If injection fails because the branch isn't writable in time, it degrades exactly like substitution does today: surfaced in `partial_failure`, not a hard crash. - When `dispatch_allow` is `false` or omitted, behavior is byte-for-byte unchanged. - Descriptor description updated to mention the new arg. - Table-driven test coverage in `create_project_from_template_test.go` for both `true` (file injected) and `false`/omitted (no file) paths, following the existing test idiom (testify). - `task check` passes. ## Out of scope - No change to `template_name`, substitution logic, or the infra#179 root cause. - Not solving the async-generate slowness — only ensuring `.dispatch-allow` rides the same best-effort path as everything else.
Author
Owner

Done in v0.3.0 (commit on main).

  • dispatch_allow bool added to input schema + createProjectArgs, default false.
  • When true: after the substitution loop, .dispatch-allow is injected at repo root on the resolved branch via the existing upsertRetry path — inherits the infra#179 branch-readiness / partial_failure handling. A stalled injection surfaces in partial_failure, no crash.
  • Injected path reported in files_substituted.
  • File content mirrors the sandbox convention (presence = dispatch-eligible, references dispatch#3).
  • false/omitted path is byte-for-byte unchanged (guarded block).
  • Descriptor description updated.
  • Table-driven test TestCreateProject_DispatchAllow covers true / false / omitted.
  • task check passes (lint 0 issues, tests green with -race, govulncheck clean).
Done in v0.3.0 (commit on `main`). - `dispatch_allow` bool added to input schema + `createProjectArgs`, default `false`. - When `true`: after the substitution loop, `.dispatch-allow` is injected at repo root on the resolved `branch` via the existing `upsertRetry` path — inherits the infra#179 branch-readiness / `partial_failure` handling. A stalled injection surfaces in `partial_failure`, no crash. - Injected path reported in `files_substituted`. - File content mirrors the sandbox convention (presence = dispatch-eligible, references dispatch#3). - `false`/omitted path is byte-for-byte unchanged (guarded block). - Descriptor description updated. - Table-driven test `TestCreateProject_DispatchAllow` covers true / false / omitted. - `task check` passes (lint 0 issues, tests green with `-race`, govulncheck clean).
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/gitea-mcp#43