ace-hitl 0.8.0

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.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/.ace-defaults/hitl/config.yml +3 -0
  3. data/.ace-defaults/nav/protocols/skill-sources/ace-hitl.yml +13 -0
  4. data/.ace-defaults/nav/protocols/wfi-sources/ace-hitl.yml +13 -0
  5. data/CHANGELOG.md +128 -0
  6. data/README.md +42 -0
  7. data/Rakefile +10 -0
  8. data/docs/demo/ace-hitl-scope-and-answer.tape.yml +37 -0
  9. data/docs/demo/fixtures/demo-context.md +7 -0
  10. data/docs/usage.md +112 -0
  11. data/exe/ace-hitl +18 -0
  12. data/handbook/README.md +14 -0
  13. data/handbook/skills/as-hitl/SKILL.md +29 -0
  14. data/handbook/workflow-instructions/hitl.wf.md +110 -0
  15. data/lib/ace/hitl/atoms/hitl_file_pattern.rb +20 -0
  16. data/lib/ace/hitl/atoms/hitl_id_formatter.rb +15 -0
  17. data/lib/ace/hitl/cli/commands/create.rb +76 -0
  18. data/lib/ace/hitl/cli/commands/list.rb +63 -0
  19. data/lib/ace/hitl/cli/commands/show.rb +79 -0
  20. data/lib/ace/hitl/cli/commands/update.rb +127 -0
  21. data/lib/ace/hitl/cli/commands/wait.rb +74 -0
  22. data/lib/ace/hitl/cli.rb +62 -0
  23. data/lib/ace/hitl/models/hitl_event.rb +32 -0
  24. data/lib/ace/hitl/molecules/hitl_answer_editor.rb +25 -0
  25. data/lib/ace/hitl/molecules/hitl_config_loader.rb +50 -0
  26. data/lib/ace/hitl/molecules/hitl_creator.rb +207 -0
  27. data/lib/ace/hitl/molecules/hitl_display_formatter.rb +53 -0
  28. data/lib/ace/hitl/molecules/hitl_loader.rb +113 -0
  29. data/lib/ace/hitl/molecules/hitl_resolver.rb +30 -0
  30. data/lib/ace/hitl/molecules/hitl_scanner.rb +42 -0
  31. data/lib/ace/hitl/molecules/resume_dispatcher.rb +99 -0
  32. data/lib/ace/hitl/molecules/worktree_scope_resolver.rb +77 -0
  33. data/lib/ace/hitl/organisms/hitl_manager.rb +462 -0
  34. data/lib/ace/hitl/version.rb +7 -0
  35. data/lib/ace/hitl.rb +24 -0
  36. metadata +164 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 96a4def785b91ef54a793fc989a19dc9e716dbf806129d82351bcf487245383c
4
+ data.tar.gz: 8f611901bbe6fc4ebf003baab73f0dff2de801c98f260011ceeeb4b655465af3
5
+ SHA512:
6
+ metadata.gz: 7a84118d6cbdd5fed6e868e0b2eff28dcdcc8cc41692feea61dfcd79bd37e84cc42f81d4dd63af122a42007770995cc85b0fbf29d6408d83cf5668997f803052
7
+ data.tar.gz: 857c322f44dab838002765b159112906d42f7708a308037fb5f5618c47cc21b5cd6547fec3b55e23ed7fc7306b583c8b17e9b94e71d822929290054c2bf612b3
@@ -0,0 +1,3 @@
1
+ hitl:
2
+ root_dir: .ace-local/hitl
3
+ default_kind: clarification
@@ -0,0 +1,13 @@
1
+ ---
2
+ # Skill Sources Protocol Configuration for ace-hitl gem
3
+ # This enables canonical skill discovery from the installed ace-hitl gem
4
+
5
+ name: ace-hitl
6
+ type: gem
7
+ description: Canonical skills from ace-hitl gem
8
+ priority: 10
9
+
10
+ config:
11
+ relative_path: handbook/skills
12
+ pattern: "*/SKILL.md"
13
+ enabled: true
@@ -0,0 +1,13 @@
1
+ ---
2
+ # WFI Sources Protocol Configuration for ace-hitl gem
3
+ # This enables workflow discovery from the installed ace-hitl gem
4
+
5
+ name: ace-hitl
6
+ type: gem
7
+ description: HITL workflow instructions from ace-hitl gem
8
+ priority: 10
9
+
10
+ config:
11
+ relative_path: handbook/workflow-instructions
12
+ pattern: "*.wf.md"
13
+ enabled: true
data/CHANGELOG.md ADDED
@@ -0,0 +1,128 @@
1
+ # Changelog
2
+
3
+ All notable changes to `ace-hitl` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.8.0] - 2026-04-02
11
+
12
+ ### Changed
13
+
14
+ - Changed `ace-hitl list` default status behavior to include all statuses in the selected folder scope when `--status` is omitted (instead of implicitly filtering to `pending`).
15
+ - Updated list row rendering to task-like compact output with leading status icons for each HITL event.
16
+
17
+ ### Technical
18
+
19
+ - Updated list command/docs/workflow wording and command-level tests to reflect explicit pending filtering (`--status pending`) and icon-led row assertions.
20
+
21
+ ## [0.7.0] - 2026-04-02
22
+
23
+ ### Changed
24
+
25
+ - Renamed the canonical HITL object terminology from "item" to "event" across CLI help/output, package docs, and workflow instructions.
26
+ - Performed immediate API/contract cutover for `HitlManager` resolution payloads from `:item` to `:event`.
27
+
28
+ ### Added
29
+
30
+ - Added a list-output stats footer (`HITL Events: ...`) for `ace-hitl list`, including empty-result output and filtered `X of Y` summaries.
31
+ - Added explicit lifecycle event naming contract documentation under the `hitl.event.*` namespace.
32
+
33
+ ## [0.6.0] - 2026-04-02
34
+
35
+ ### Changed
36
+
37
+ - Switched the default HITL runtime root from `.ace-hitl` to `.ace-local/hitl` to align with ACE local-artifact layout conventions.
38
+
39
+ ### Technical
40
+
41
+ - Updated scope and status test fixtures that embedded legacy `.ace-hitl` paths to use `.ace-local/hitl`.
42
+
43
+ ## [0.5.0] - 2026-04-02
44
+
45
+ ### Added
46
+
47
+ - Added `ace-hitl wait <id>` polling support with per-event lease metadata (`waiter_*`) so agents wait only on their own HITL question IDs by default.
48
+ - Added requester session metadata capture (`requester_provider`, `requester_model`, `requester_session_id`) from assignment session traces during HITL creation.
49
+ - Added resume fallback dispatch plumbing for answered items through provider session resume and command fallback paths.
50
+
51
+ ### Changed
52
+
53
+ - Extended `ace-hitl update` with `--resume` to dispatch answer handoff only when no active waiter lease is detected.
54
+ - Updated HITL workflow and usage docs to make polling the default reliability path and resume dispatch the explicit fallback path.
55
+
56
+ ### Technical
57
+
58
+ - Added CLI/manager regression coverage for wait timeout/success paths and resume dispatch skip/dispatch behavior.
59
+
60
+ ## [0.4.3] - 2026-04-02
61
+
62
+ ### Changed
63
+
64
+ - Switched `ace-hitl` configuration loading to ACE shared namespace resolution (`Ace::Support::Config`), with defaults fallback behavior for resilience.
65
+ - Added a package-owned `handbook/` skeleton (`agents/`, `guides/`, `skills/`, `templates/`, `workflow-instructions/`) for architectural consistency.
66
+
67
+ ### Fixed
68
+
69
+ - Collapsed combined `ace-hitl update` metadata and answer mutations into one locked read/mutate/write cycle to avoid double write passes.
70
+
71
+ ### Technical
72
+
73
+ - Added `ace-support-config` as a runtime dependency in `ace-hitl.gemspec`.
74
+
75
+ ## [0.4.2] - 2026-04-01
76
+
77
+ ### Fixed
78
+
79
+ - Made `ace-hitl update` honor scoped multi-worktree resolution semantics (`--scope`) consistent with `show`.
80
+ - Prevented duplicate HITL IDs during rapid event creation by regenerating IDs when collisions are detected.
81
+ - Narrowed loader exception handling so programming errors surface instead of being silently treated as not-found.
82
+
83
+ ### Technical
84
+
85
+ - Added CLI regression coverage for scoped `update` behavior and ID collision avoidance.
86
+
87
+ ## [0.4.1] - 2026-04-01
88
+
89
+ ### Technical
90
+
91
+ - Updated CLI version contract tests to assert the current `Ace::Hitl::VERSION` (`0.4.0`) after the 0.4.0 release line.
92
+
93
+ ## [0.4.0] - 2026-04-01
94
+
95
+ ### Added
96
+
97
+ - Added smart multi-worktree scope resolution for `ace-hitl list` and `ace-hitl show` with explicit `--scope current|all`.
98
+ - Added context-aware default scope behavior: linked worktrees default to current scope, main checkout defaults to all-scope operator view.
99
+ - Added strict all-scope ambiguity handling for `show` with candidate path reporting.
100
+
101
+ ### Changed
102
+
103
+ - Changed `ace-hitl list` default behavior to show only `pending` items when `--status` is omitted.
104
+ - Changed `ace-hitl show` to perform local-first lookup with implicit all-scope fallback only when scope is not explicitly provided.
105
+ - Changed show output to include explicit resolved-location details for cross-worktree item resolution.
106
+ - Updated usage and README documentation to describe local-first HITL semantics versus global `ace-overseer` dashboard usage.
107
+
108
+ ## [0.3.0] - 2026-04-01
109
+
110
+ ### Added
111
+
112
+ - Implemented full HITL event store behavior with package-owned model/molecules/manager flow.
113
+ - Added complete CLI behavior for `create`, `list`, `show`, and `update` with filtering and mutation options.
114
+ - Added usage documentation for end-to-end item management flows.
115
+
116
+ ### Fixed
117
+
118
+ - Corrected answer section updates to handle empty `## Answer` blocks and persist answer text reliably.
119
+ - Updated CLI tests to align with current package version and answer-write behavior.
120
+
121
+ ## [0.2.0] - 2026-04-01
122
+
123
+ ### Added
124
+
125
+ - Initial package skeleton for `ace-hitl`.
126
+ - Root and package executables (`bin/ace-hitl`, `ace-hitl/exe/ace-hitl`).
127
+ - Minimal CLI registry for `list`, `show`, `create`, and `update`.
128
+ - Baseline docs and config scaffold.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # ace-hitl
2
+
3
+ `ace-hitl` manages ACE human-in-the-loop (HITL) events in `.ace-local/hitl/`.
4
+
5
+ Canonical workflow and skill for agents:
6
+
7
+ - Workflow: `wfi://hitl`
8
+ - Skill: `as-hitl`
9
+
10
+ ## Commands
11
+
12
+ - `ace-hitl create` creates a HITL event
13
+ - `ace-hitl list` lists HITL events with filters (`--scope current|all`, all statuses by default)
14
+ - `ace-hitl show` renders event details, path, or raw content (`--scope current|all`)
15
+ - `ace-hitl update` updates frontmatter, answer content, and folder location
16
+ - `ace-hitl wait` polls a specific HITL event until answered (`--poll-every`, `--timeout`)
17
+
18
+ `ace-hitl` is a blocker-resolution tool, not a global dashboard:
19
+
20
+ - linked worktree default: local (`--scope current`)
21
+ - main checkout default: operator view (`--scope all`)
22
+
23
+ Use `ace-overseer status` for a global worktree dashboard.
24
+
25
+ ## Examples
26
+
27
+ ```bash
28
+ ace-hitl list
29
+ ace-hitl list --scope all
30
+ ace-hitl create "Which auth strategy?" --kind decision --question "JWT or sessions?"
31
+ ace-hitl show abc123 --content
32
+ ace-hitl show abc123 --scope current
33
+ ace-hitl update abc123 --answer "Use JWT with server-side refresh tokens."
34
+ ace-hitl wait abc123
35
+ ace-hitl update abc123 --answer "Use JWT with server-side refresh tokens." --resume
36
+ ```
37
+
38
+ ## Ownership Boundary
39
+
40
+ `ace-hitl` owns HITL-specific event semantics and markdown contract.
41
+
42
+ `ace-support-items` remains generic support infrastructure and should not absorb HITL-specific domain behavior.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rake/testtask"
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.pattern = "test/**/*_test.rb"
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,37 @@
1
+ ---
2
+ description: Showcase ace-hitl scope-aware CLI surface and answer markdown preservation regression coverage
3
+ tags:
4
+ - ace-hitl
5
+ - feature-demo
6
+ - scope
7
+ settings:
8
+ font_size: 16
9
+ width: 1100
10
+ height: 620
11
+ format: gif
12
+ setup:
13
+ - sandbox
14
+ - copy-fixtures
15
+ scenes:
16
+ - name: Demo context
17
+ commands:
18
+ - type: cat fixtures/demo-context.md
19
+ sleep: 4s
20
+ - name: Show scope-aware list/show CLI flags
21
+ commands:
22
+ - type: clear
23
+ sleep: 1s
24
+ - type: ace-hitl list --help
25
+ sleep: 5s
26
+ - type: ace-hitl show --help
27
+ sleep: 5s
28
+ - name: Verify ambiguity and heading-preservation behavior
29
+ commands:
30
+ - type: clear
31
+ sleep: 1s
32
+ - type: ace-test test/commands/hitl_cli_test.rb --filter test_show_scope_all_errors_on_ambiguous_ref_with_candidates
33
+ sleep: 5s
34
+ - type: ace-test test/commands/hitl_cli_test.rb --filter test_update_answer_preserves_markdown_headings_in_answer_body
35
+ sleep: 5s
36
+ teardown:
37
+ - cleanup
@@ -0,0 +1,7 @@
1
+ # ace-hitl scope + answer integrity demo
2
+
3
+ This demo highlights two user-facing outcomes from PR #275:
4
+ - `ace-hitl list/show` expose explicit scope controls for multi-worktree reads.
5
+ - Answer updates preserve markdown headings inside `## Answer` content.
6
+
7
+ Verification commands in the demo run focused CLI-contract tests.
data/docs/usage.md ADDED
@@ -0,0 +1,112 @@
1
+ ---
2
+ doc-type: user
3
+ title: ace-hitl Usage Guide
4
+ purpose: Practical CLI usage reference for ace-hitl event creation, triage, and resolution
5
+ flows.
6
+ ace-docs:
7
+ last-updated: '2026-04-02'
8
+ last-checked: '2026-04-02'
9
+ ---
10
+
11
+ # ace-hitl Usage
12
+
13
+ Canonical handbook resources:
14
+
15
+ - Workflow: `wfi://hitl`
16
+ - Skill: `as-hitl`
17
+
18
+ Runtime store default: `.ace-local/hitl/` (legacy `.ace-hitl/` is no longer used as default).
19
+
20
+ ## Create
21
+
22
+ ```bash
23
+ ace-hitl create "Which auth strategy?" \
24
+ --kind decision \
25
+ --question "JWT or sessions?" \
26
+ --question "Refresh token storage?" \
27
+ --assignment 8qr5kx \
28
+ --step 020 \
29
+ --step-name implement-auth \
30
+ --resume "/as-assign-drive 8qr5kx"
31
+ ```
32
+
33
+ Common completion-attention handoff:
34
+
35
+ ```bash
36
+ ace-hitl create "Review completed assignment results" \
37
+ --kind approval \
38
+ --question "Please confirm next action for 8qr5kx." \
39
+ --assignment 8qr5kx \
40
+ --step completion \
41
+ --step-name assignment-complete \
42
+ --resume "/as-assign-drive 8qr5kx"
43
+ ```
44
+
45
+ ## List
46
+
47
+ `ace-hitl list` is local-first by default:
48
+
49
+ - in a linked worktree: behaves like `--scope current`
50
+ - in the main checkout: behaves like `--scope all`
51
+ - if `--status` is omitted: includes all statuses in the selected folder scope
52
+
53
+ ```bash
54
+ ace-hitl list
55
+ ace-hitl list --scope current
56
+ ace-hitl list --scope all
57
+ ace-hitl list --status pending
58
+ ace-hitl list --kind decision
59
+ ace-hitl list --kind clarification --status pending
60
+ ace-hitl list --tags auth,security
61
+ ace-hitl list --in archive
62
+ ```
63
+
64
+ ## Show
65
+
66
+ `ace-hitl show` also accepts `--scope current|all`.
67
+ Without `--scope`, lookup is local-first; if not found and smart scope is active, it retries across all worktrees.
68
+ When lookup resolves outside the current worktree, output includes an explicit `Resolved Location:` line.
69
+ When using `--scope all`, ambiguous matches return an error with candidate paths so the operator can select the intended event explicitly.
70
+
71
+ ```bash
72
+ ace-hitl show abc123
73
+ ace-hitl show abc123 --scope current
74
+ ace-hitl show abc123 --scope all
75
+ ace-hitl show abc123 --path
76
+ ace-hitl show abc123 --content
77
+ ```
78
+
79
+ ## Update
80
+
81
+ ```bash
82
+ ace-hitl update abc123 --set status=in-progress
83
+ ace-hitl update abc123 --add tags=reviewed
84
+ ace-hitl update abc123 --remove tags=stale
85
+ ace-hitl update abc123 --answer "Use JWT with server-side refresh tokens."
86
+ ace-hitl update abc123 --move-to archive
87
+ ace-hitl update abc123 --move-to next
88
+ ace-hitl update abc123 --answer "close the assignment" --resume
89
+ ```
90
+
91
+ ## Wait (Polling Default)
92
+
93
+ Wait only for a specific HITL id. This is the default reliability path for the requester agent.
94
+
95
+ ```bash
96
+ ace-hitl wait abc123
97
+ ace-hitl wait abc123 --poll-every 600 --timeout 14400
98
+ ace-hitl wait abc123 --scope current
99
+ ```
100
+
101
+ ## Lifecycle Event Names
102
+
103
+ Canonical namespace for HITL lifecycle signaling:
104
+
105
+ - `hitl.event.created`
106
+ - `hitl.event.answered`
107
+ - `hitl.event.wait_started`
108
+ - `hitl.event.wait_timed_out`
109
+ - `hitl.event.resume_dispatched`
110
+ - `hitl.event.resume_skipped_waiter_active`
111
+ - `hitl.event.resume_failed`
112
+ - `hitl.event.archived`
data/exe/ace-hitl ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/ace/hitl"
5
+
6
+ args = ARGV.empty? ? ["--help"] : ARGV
7
+
8
+ trap("INT") { exit 130 }
9
+
10
+ begin
11
+ Ace::Hitl::HitlCLI.start(args)
12
+ rescue Ace::Support::Cli::Error => e
13
+ warn e.message
14
+ exit(e.exit_code)
15
+ rescue ArgumentError => e
16
+ warn "Error: #{e.message}"
17
+ exit(1)
18
+ end
@@ -0,0 +1,14 @@
1
+ # ace-hitl Handbook
2
+
3
+ Package-owned handbook skeleton for HITL workflows, skills, and guides.
4
+
5
+ - `agents/`: package-local agent definitions
6
+ - `workflow-instructions/`: canonical HITL workflows (`.wf.md`)
7
+ - `skills/`: canonical skill definitions (`SKILL.md`)
8
+ - `guides/`: package-specific guidance docs (`.g.md`)
9
+ - `templates/`: reusable prompt/doc templates
10
+
11
+ Current canonical entries:
12
+
13
+ - `wfi://hitl`
14
+ - `as-hitl`
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: as-hitl
3
+ description: Manage human-attention blockers and completion handoffs with ace-hitl
4
+ # bundle: wfi://hitl
5
+ # agent: general-purpose
6
+ user-invocable: true
7
+ allowed-tools:
8
+ - Bash(ace-hitl:*)
9
+ - Bash(ace-assign:*)
10
+ - Bash(ace-bundle:*)
11
+ - Read
12
+ argument-hint: "[create|list|show|update] [options]"
13
+ last_modified: 2026-04-02
14
+ source: ace-hitl
15
+ integration:
16
+ targets:
17
+ - claude
18
+ - codex
19
+ - gemini
20
+ - opencode
21
+ - pi
22
+ providers: {}
23
+ skill:
24
+ kind: workflow
25
+ execution:
26
+ workflow: wfi://hitl
27
+ ---
28
+
29
+ Load and run `ace-bundle wfi://hitl` in the current project, then follow the loaded workflow as the source of truth and execute it end-to-end instead of only summarizing it.
@@ -0,0 +1,110 @@
1
+ ---
2
+ doc-type: workflow
3
+ title: HITL Workflow
4
+ purpose: Standardize human-attention handling for blocked and completed work using ace-hitl events.
5
+ ace-docs:
6
+ last-updated: '2026-04-02'
7
+ last-checked: '2026-04-02'
8
+ ---
9
+
10
+ # HITL Workflow
11
+
12
+ ## Goal
13
+
14
+ Use `ace-hitl` as the canonical contract whenever agent flow needs explicit human attention.
15
+
16
+ ## When To Use HITL
17
+
18
+ Create a HITL event in exactly two cases:
19
+
20
+ 1. **Blocker requiring human judgment** (ambiguity, product decision, policy/approval gate).
21
+ 2. **Work is complete but explicit user attention is required** before follow-up actions.
22
+
23
+ Do not create HITL events for routine status updates that do not require user action.
24
+
25
+ ## Commands
26
+
27
+ ### 1) Create a blocker HITL
28
+
29
+ ```bash
30
+ ace-hitl create "Need product decision" \
31
+ --kind decision \
32
+ --question "Should retries be visible?" \
33
+ --assignment <assignment-id> \
34
+ --step <step-number> \
35
+ --step-name <step-name> \
36
+ --resume "/as-assign-drive <assignment-id>"
37
+ ```
38
+
39
+ If the active assignment step is blocked, fail it using canonical format:
40
+
41
+ ```bash
42
+ ace-assign fail --message "HITL: <hitl-id> <hitl-path>" --assignment "<assignment-id>"
43
+ ```
44
+
45
+ ### 2) Create a completion-attention HITL
46
+
47
+ ```bash
48
+ ace-hitl create "Review completed assignment results" \
49
+ --kind approval \
50
+ --question "Please confirm next action for <assignment-id>." \
51
+ --assignment <assignment-id> \
52
+ --step completion \
53
+ --step-name assignment-complete \
54
+ --resume "/as-assign-drive <assignment-id>"
55
+ ```
56
+
57
+ ### 3) Discover HITL work
58
+
59
+ ```bash
60
+ ace-hitl list
61
+ ace-hitl list --scope current
62
+ ace-hitl list --scope all
63
+ ace-hitl list --status pending
64
+ ```
65
+
66
+ ### 4) Resolve and archive
67
+
68
+ ```bash
69
+ ace-hitl show <hitl-id>
70
+ ace-hitl update <hitl-id> --answer "<human decision>"
71
+ ```
72
+
73
+ Polling is the default reliability path for the requesting agent:
74
+
75
+ ```bash
76
+ ace-hitl wait <hitl-id>
77
+ ```
78
+
79
+ If the waiter is no longer active, operator fallback can dispatch resume:
80
+
81
+ ```bash
82
+ ace-hitl update <hitl-id> --answer "<human decision>" --resume
83
+ ```
84
+
85
+ ## Completion Contract
86
+
87
+ After answer is applied:
88
+
89
+ - Continue normal assignment retry/resume flow.
90
+ - Keep `ace-assign` mechanics unchanged (no paused assignment state).
91
+ - Archive HITL event after resolution.
92
+
93
+ ## Event Names
94
+
95
+ Canonical lifecycle namespace: `hitl.event.*`
96
+
97
+ - `hitl.event.created`
98
+ - `hitl.event.answered`
99
+ - `hitl.event.wait_started`
100
+ - `hitl.event.wait_timed_out`
101
+ - `hitl.event.resume_dispatched`
102
+ - `hitl.event.resume_skipped_waiter_active`
103
+ - `hitl.event.resume_failed`
104
+ - `hitl.event.archived`
105
+
106
+ ## Success Criteria
107
+
108
+ - Blockers always produce canonical `HITL: <id> <path>` failure reason.
109
+ - Human-required completion handoffs generate approval HITL events.
110
+ - Resolved HITL events are archived only after successful resume dispatch.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ace
4
+ module Hitl
5
+ module Atoms
6
+ class HitlFilePattern
7
+ FILE_EXTENSION = ".hitl.s.md"
8
+ FILE_GLOB = "*#{FILE_EXTENSION}"
9
+
10
+ def self.folder_name(id, slug)
11
+ slug.nil? || slug.empty? ? id : "#{id}-#{slug}"
12
+ end
13
+
14
+ def self.filename(id, slug)
15
+ "#{folder_name(id, slug)}#{FILE_EXTENSION}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ace/b36ts"
4
+
5
+ module Ace
6
+ module Hitl
7
+ module Atoms
8
+ class HitlIdFormatter
9
+ def self.generate(time = Time.now.utc)
10
+ Ace::B36ts.encode(time, format: :"2sec")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ace/support/cli"
4
+
5
+ module Ace
6
+ module Hitl
7
+ module CLI
8
+ module Commands
9
+ class Create < Ace::Support::Cli::Command
10
+ include Ace::Support::Cli::Base
11
+
12
+ desc "Create HITL event"
13
+
14
+ argument :title, required: false, desc: "HITL event title"
15
+
16
+ option :kind, type: :string, aliases: %w[-k], desc: "Kind: clarification, decision, approval"
17
+ option :question, type: :string, repeat: true, aliases: %w[-Q], desc: "Question line (repeatable)"
18
+ option :tags, type: :string, aliases: %w[-T], desc: "Comma-separated tags"
19
+ option :assignment, type: :string, desc: "Assignment reference"
20
+ option :step, type: :string, desc: "Step number"
21
+ option :"step-name", type: :string, desc: "Step name"
22
+ option :resume, type: :string, desc: "Resume instructions"
23
+ option :"move-to", type: :string, aliases: %w[-m], desc: "Target folder (archive, next)"
24
+
25
+ option :quiet, type: :boolean, aliases: %w[-q], desc: "Suppress non-essential output"
26
+ option :verbose, type: :boolean, aliases: %w[-v], desc: "Show verbose output"
27
+ option :debug, type: :boolean, aliases: %w[-d], desc: "Show debug output"
28
+
29
+ def call(title: nil, **options)
30
+ unless title && !title.strip.empty?
31
+ raise Ace::Support::Cli::Error.new("Title required")
32
+ end
33
+
34
+ kind = options[:kind]
35
+ validate_kind!(kind) if kind
36
+
37
+ questions = Array(options[:question]).map(&:strip).reject(&:empty?)
38
+ tags = parse_tags(options[:tags])
39
+
40
+ manager = Ace::Hitl::Organisms::HitlManager.new
41
+ event = manager.create(
42
+ title,
43
+ kind: kind,
44
+ questions: questions,
45
+ tags: tags,
46
+ assignment: options[:assignment],
47
+ step: options[:step],
48
+ step_name: options[:"step-name"],
49
+ resume_instructions: options[:resume],
50
+ move_to: options[:"move-to"]
51
+ )
52
+
53
+ folder_info = event.special_folder ? " (#{event.special_folder})" : ""
54
+ puts "HITL event created: #{event.id} #{event.title}#{folder_info}"
55
+ puts " Path: #{event.file_path}"
56
+ end
57
+
58
+ private
59
+
60
+ def validate_kind!(kind)
61
+ allowed = %w[clarification decision approval]
62
+ return if allowed.include?(kind)
63
+
64
+ raise Ace::Support::Cli::Error.new("Invalid kind '#{kind}'. Allowed: #{allowed.join(", ")}")
65
+ end
66
+
67
+ def parse_tags(raw)
68
+ return [] unless raw
69
+
70
+ raw.split(",").map(&:strip).reject(&:empty?)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end