main · last commit
13 days ago ·
7g0stsfu
ah-xuc.2 internal/spec: Task Spec frontmatter parse, type-label defaults, validation
Past Stand
bd reopen ah-xuc.2
| Created by | Eugene Blikh |
| Owner | bigbes@gmail.com |
| Created | 2026-07-13T05:15:08Z |
| Started | 2026-07-13T05:44:24Z |
| Updated | 2026-07-13T06:22:47Z |
| Closed | 2026-07-13T06:22:47Z |
New pure package internal/spec (imports domain, config, yaml only — no board/store/runner I/O). Custom fields do not exist in Vikunja, so the machine-readable part of a task lives as YAML frontmatter at the head of the description; labels give per-type defaults.
Parse: frontmatter delimited by --- lines at the very start of the description (tolerate CRLF; no frontmatter = empty spec). Known fields: role, model, skills (list of names), timeout (duration string). Unknown fields are collected as warnings, never errors. Returns spec + body (description with frontmatter stripped) + warnings.
Resolve(cfg, labels, description): merge precedence config defaults < type:<name> label preset (cfg.TaskTypes) < frontmatter. More than one type:* label is a validation error; a type:* label naming an unknown task type is a validation error. Validation (bounce-class) errors: broken YAML, unknown role, skill name not a safe slug, skills requested while skills_dir unset, missing <skills_dir>/<name>/SKILL.md, SKILL.md frontmatter with an empty description, timeout unparseable or nonpositive. Output: Resolved{RoleName, Model, SkillPaths (absolute), Timeout, Body, Warnings}. Filesystem checks go through a small injected func so most tests need no real skills tree; add one real-FS test with t.TempDir() fixtures.
Validation errors must be a typed, human-readable list — the reconciler posts them verbatim in the Triage bounce comment — distinct from internal errors.
go test ./internal/spec/... green, go vet clean; table tests cover merge precedence for every field and each bounce class; frontmatter stripping keeps the body exact after the closing delimiter
ah-xuc.8
— reconcile: spec-driven claim, Triage bounce, parked buckets, per-run timeout
blocks
ah-xuc.8
— reconcile: spec-driven claim, Triage bounce, parked buckets, per-run timeout
blocks
closed
ah-xuc.9
— reconcile: publish review branch, watchdog on stale events, Telegram notifications
blocks
closed
ah-xuc.12
— docs: sync SPEC with Stage 2 behavior
blocks
closed
ah-xuc.10
— cmd/agenthubd: wire webhook secret and Telegram notifier
blocks
closed
ah-xuc.11
— e2e: Stage 2 flows — webhook poke, Triage bounce, skills, publish, watchdog, Telegram
blocks
closed
| id | ah-xuc.2 |
| content_hash | fa1ad68d45c1cb503c73e2f25b2c07769c319f1d2adc6eefbb30f03d70297a4a |
| title | internal/spec: Task Spec frontmatter parse, type-label defaults, validation |
| description | New pure package internal/spec (imports domain, config, yaml only — no board/store/runner I/O). Custom fields do not exist in Vikunja, so the machine-readable part of a task lives as YAML frontmatter at the head of the description; labels give per-type defaults. Parse: frontmatter delimited by --- lines at the very start of the description (tolerate CRLF; no frontmatter = empty spec). Known fields: role, model, skills (list of names), timeout (duration string). Unknown fields are collected as warnings, never errors. Returns spec + body (description with frontmatter stripped) + warnings. Resolve(cfg, labels, description): merge precedence config defaults < type:<name> label preset (cfg.TaskTypes) < frontmatter. More than one type:* label is a validation error; a type:* label naming an unknown task type is a validation error. Validation (bounce-class) errors: broken YAML, unknown role, skill name not a safe slug, skills requested while skills_dir unset, missing <skills_dir>/<name>/SKILL.md, SKILL.md frontmatter with an empty description, timeout unparseable or nonpositive. Output: Resolved{RoleName, Model, SkillPaths (absolute), Timeout, Body, Warnings}. Filesystem checks go through a small injected func so most tests need no real skills tree; add one real-FS test with t.TempDir() fixtures. Validation errors must be a typed, human-readable list — the reconciler posts them verbatim in the Triage bounce comment — distinct from internal errors. |
| design | |
| acceptance_criteria | go test ./internal/spec/... green, go vet clean; table tests cover merge precedence for every field and each bounce class; frontmatter stripping keeps the body exact after the closing delimiter |
| notes | |
| status | closed |
| priority | 2 |
| issue_type | feature |
| assignee | Eugene Blikh |
| estimated_minutes | NULL |
| created_at | 2026-07-13T05:15:08Z |
| created_by | Eugene Blikh |
| owner | bigbes@gmail.com |
| updated_at | 2026-07-13T06:22:47Z |
| closed_at | 2026-07-13T06:22:47Z |
| closed_by_session | |
| external_ref | NULL |
| spec_id | |
| compaction_level | 0 |
| compacted_at | NULL |
| compacted_at_commit | NULL |
| original_size | NULL |
| sender | |
| ephemeral | 0 |
| wisp_type | |
| pinned | 0 |
| is_template | 0 |
| mol_type | |
| work_type | |
| source_system | |
| metadata | �{} |
| source_repo | |
| close_reason | d714741 + eb5a4be (review-gap pinning); hostile adversarial review merge-ready (yaml alias bombs bounded, path traversal blocked, error taxonomy sound) |
| event_kind | |
| actor | |
| target | |
| payload | |
| await_type | |
| await_id | |
| timeout_ns | 0 |
| waiters | |
| hook_bead | |
| role_bead | |
| agent_state | |
| last_activity | NULL |
| role_type | |
| rig | |
| due_at | NULL |
| defer_until | NULL |
| no_history | 0 |
| started_at | 2026-07-13T05:44:24Z |
| is_blocked | 0 |
| id | 252a0719-62cd-54d5-8db4-9309eb609a4e |
| issue_id | ah-xuc.2 |
| type | parent-child |
| created_at | 2026-07-13T08:15:07Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | ah-xuc |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 356d9515-68da-5d7b-a5cd-bd71da198917 |
| issue_id | ah-xuc.8 |
| type | blocks |
| created_at | 2026-07-13T08:16:50Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | ah-xuc.2 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 8125fd31-7552-5d90-b0ce-82dad1547ce3 |
| issue_id | ah-xuc.2 |
| type | blocks |
| created_at | 2026-07-13T08:16:47Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | ah-xuc.1 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 019f59e6-8639-7603-80dc-7aee95e670a6 |
| issue_id | ah-xuc.2 |
| event_type | created |
| actor | Eugene Blikh |
| old_value | |
| new_value | |
| comment | NULL |
| created_at | 2026-07-13T08:15:07Z |
| id | 019f5a01-533d-7850-a7e2-b8893f559e5d |
| issue_id | ah-xuc.2 |
| event_type | claimed |
| actor | Eugene Blikh |
| old_value | {"id":"ah-xuc.2","title":"internal/spec: Task Spec frontmatter parse, type-label defaults, validation","description":"New pure package internal/spec (imports domain, config, yaml only — no board/store/runner I/O). Custom fields do not exist in Vikunja, so the machine-readable part of a task lives as YAML frontmatter at the head of the description; labels give per-type defaults.\n\nParse: frontmatter delimited by --- lines at the very start of the description (tolerate CRLF; no frontmatter = empty spec). Known fields: role, model, skills (list of names), timeout (duration string). Unknown fields are collected as warnings, never errors. Returns spec + body (description with frontmatter stripped) + warnings.\n\nResolve(cfg, labels, description): merge precedence config defaults \u003c type:\u003cname\u003e label preset (cfg.TaskTypes) \u003c frontmatter. More than one type:* label is a validation error; a type:* label naming an unknown task type is a validation error. Validation (bounce-class) errors: broken YAML, unknown role, skill name not a safe slug, skills requested while skills_dir unset, missing \u003cskills_dir\u003e/\u003cname\u003e/SKILL.md, SKILL.md frontmatter with an empty description, timeout unparseable or nonpositive. Output: Resolved{RoleName, Model, SkillPaths (absolute), Timeout, Body, Warnings}. Filesystem checks go through a small injected func so most tests need no real skills tree; add one real-FS test with t.TempDir() fixtures.\n\nValidation errors must be a typed, human-readable list — the reconciler posts them verbatim in the Triage bounce comment — distinct from internal errors.","acceptance_criteria":"go test ./internal/spec/... green, go vet clean; table tests cover merge precedence for every field and each bounce class; frontmatter stripping keeps the body exact after the closing delimiter","status":"open","priority":2,"issue_type":"feature","owner":"bigbes@gmail.com","created_at":"2026-07-13T05:15:08Z","created_by":"Eugene Blikh","updated_at":"2026-07-13T05:15:08Z"} |
| new_value | {"assignee":"Eugene Blikh","status":"in_progress"} |
| comment | NULL |
| created_at | 2026-07-13T08:44:24Z |
| id | 019f5a24-767f-74e9-bf1f-934005014f4d |
| issue_id | ah-xuc.2 |
| event_type | closed |
| actor | Eugene Blikh |
| old_value | |
| new_value | d714741 + eb5a4be (review-gap pinning); hostile adversarial review merge-ready (yaml alias bombs bounded, path traversal blocked, error taxonomy sound) |
| comment | NULL |
| created_at | 2026-07-13T09:22:46Z |
| id | 019f7cda-9356-73c8-abcf-cc32ba5f276c |
| issue_id | ah-xuc.2 |
| event_type | label_added |
| actor | Eugene Blikh |
| old_value | NULL |
| new_value | NULL |
| comment | Added label: milestone:stage-2 |
| created_at | 2026-07-20T03:08:47Z |
| id | 019f7cdc-1037-753b-9a5c-02717d1fc487 |
| issue_id | ah-xuc.2 |
| event_type | label_removed |
| actor | Eugene Blikh |
| old_value | NULL |
| new_value | NULL |
| comment | Removed label: milestone:stage-2 |
| created_at | 2026-07-20T03:10:24Z |
No comments.
Close reason