kingdom-cli 0.2__tar.gz → 0.2.1__tar.gz

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 (75) hide show
  1. {kingdom_cli-0.2/src/kingdom_cli.egg-info → kingdom_cli-0.2.1}/PKG-INFO +45 -23
  2. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/README.md +44 -22
  3. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/pyproject.toml +2 -1
  4. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/agent.py +81 -0
  5. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/cli.py +985 -201
  6. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/config.py +104 -30
  7. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/council/base.py +14 -7
  8. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/council/council.py +11 -3
  9. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/harness.py +2 -0
  10. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/state.py +100 -20
  11. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/thread.py +26 -8
  12. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/ticket.py +27 -5
  13. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/tui/app.py +417 -147
  14. kingdom_cli-0.2.1/src/kingdom/tui/chat.tcss +116 -0
  15. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/tui/poll.py +23 -9
  16. kingdom_cli-0.2.1/src/kingdom/tui/terminal.py +43 -0
  17. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/tui/widgets.py +61 -81
  18. {kingdom_cli-0.2 → kingdom_cli-0.2.1/src/kingdom_cli.egg-info}/PKG-INFO +45 -23
  19. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom_cli.egg-info/SOURCES.txt +3 -0
  20. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_agent.py +67 -0
  21. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli.py +169 -2
  22. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli_council.py +137 -2
  23. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli_peasant.py +257 -2
  24. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli_ticket.py +647 -0
  25. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli_ticket_current.py +2 -2
  26. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_config.py +90 -25
  27. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_done.py +57 -0
  28. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_harness.py +27 -0
  29. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_init.py +73 -0
  30. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_state.py +174 -0
  31. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_thread.py +149 -0
  32. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_tui.py +742 -59
  33. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_tui_clipboard.py +66 -1
  34. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_tui_integration.py +239 -22
  35. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_tui_poll.py +85 -14
  36. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_tui_reply.py +58 -16
  37. kingdom_cli-0.2.1/tests/test_tui_terminal.py +82 -0
  38. kingdom_cli-0.2.1/tests/test_tui_thinking_persistence.py +191 -0
  39. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_tui_widgets.py +8 -0
  40. kingdom_cli-0.2/tests/test_tui_thinking_persistence.py +0 -159
  41. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/LICENSE +0 -0
  42. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/setup.cfg +0 -0
  43. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/__init__.py +0 -0
  44. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/__main__.py +0 -0
  45. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/breakdown.py +0 -0
  46. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/council/__init__.py +0 -0
  47. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/council/bundle.py +0 -0
  48. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/council/worker.py +0 -0
  49. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/design.py +0 -0
  50. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/parsing.py +0 -0
  51. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/session.py +0 -0
  52. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/skill/SKILL.md +0 -0
  53. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/skill/__init__.py +0 -0
  54. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/skill/references/__init__.py +0 -0
  55. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/skill/references/council.md +0 -0
  56. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/skill/references/peasants.md +0 -0
  57. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/skill/references/tickets.md +0 -0
  58. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/synthesis.py +0 -0
  59. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/tui/__init__.py +0 -0
  60. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom/tui/clipboard.py +0 -0
  61. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom_cli.egg-info/dependency_links.txt +0 -0
  62. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom_cli.egg-info/entry_points.txt +0 -0
  63. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom_cli.egg-info/requires.txt +0 -0
  64. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/src/kingdom_cli.egg-info/top_level.txt +0 -0
  65. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_breakdown.py +0 -0
  66. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli_design_breakdown.py +0 -0
  67. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli_status.py +0 -0
  68. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_cli_whoami.py +0 -0
  69. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_council.py +0 -0
  70. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_design.py +0 -0
  71. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_parsing.py +0 -0
  72. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_session.py +0 -0
  73. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_skill.py +0 -0
  74. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_synthesis.py +0 -0
  75. {kingdom_cli-0.2 → kingdom_cli-0.2.1}/tests/test_ticket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kingdom-cli
3
- Version: 0.2
3
+ Version: 0.2.1
4
4
  Summary: A markdown file-based CLI for software development with multi-agent council design, markdown tickets, and background worker loops.
5
5
  Author: James Robinson-Bohnslav
6
6
  License-Expression: Apache-2.0
@@ -48,49 +48,71 @@ Gastown minus the polecats.
48
48
  uv tool install kingdom-cli
49
49
  ```
50
50
 
51
- ## Getting Started
51
+ ## Workflow Scales
52
+
53
+ `kd` scales down gracefully. You pick the parts of the workflow that fit the size of the work.
54
+
55
+ ### Full workflow (new features)
52
56
 
53
- 1. Initialize the project on your current branch:
57
+ Design with the council, break into tickets, dispatch peasants, review, and merge.
54
58
 
55
59
  ```bash
56
- kd start
60
+ kd start # initialize branch session
61
+ kd chat --new # discuss design with the council TUI
62
+ kd design approve # lock in the design
63
+ kd breakdown # generate tickets from the design
64
+ kd peasant start <id> # dispatch parallel workers
65
+ kd done # archive and clean up
57
66
  ```
58
67
 
59
- 2. Configure council agent CLIs in `.kd/config.json` (check effective config with `kd config show`).
68
+ ### Medium workflow (refactors, smaller features)
60
69
 
61
- 3. Design with the council in the TUI:
70
+ Pull tickets into a branch, work them directly or with peasants. No design phase needed.
62
71
 
63
72
  ```bash
64
- kd chat --new
73
+ kd start
74
+ kd tk pull <id> <id> # pull backlog tickets onto this branch
75
+ kd tk start <id> # work tickets one at a time
76
+ kd tk close <id>
77
+ kd done
65
78
  ```
66
79
 
67
- 4. Break your design into markdown tickets:
80
+ ### Lightweight workflow (bug fixes)
81
+
82
+ Work a single ticket, close it, make a PR. Or batch several bug-fix tickets on one branch.
68
83
 
69
84
  ```bash
70
- kd breakdown
85
+ kd start
86
+ kd tk create "fix: login redirect loop"
87
+ kd tk start <id>
88
+ # ... fix the bug ...
89
+ kd tk close <id>
90
+ kd done
71
91
  ```
72
92
 
73
- 5. Review and refine tickets:
93
+ Design docs, council sessions, and peasant workers are all optional. A branch with one ticket and no design doc is a perfectly valid `kd` workflow.
94
+
95
+ ## Getting Started
74
96
 
75
97
  ```bash
76
- kd ticket list
77
- kd ticket show <id>
98
+ kd init # one-time: create .kd/ directory
99
+ kd start # start a session on the current branch
78
100
  ```
79
101
 
80
- 6. Execute tickets:
81
- - Serial: tell Claude Code or Codex to work tickets directly, or run `kd work <id>`.
82
- - Parallel: dispatch peasants in worktrees.
102
+ Configure council agent CLIs in `.kd/config.json` (check effective config with `kd config show`).
83
103
 
84
- ```bash
85
- kd peasant start <id>
86
- kd peasant status
87
- ```
104
+ ## Chat Modes
88
105
 
89
- 7. Close out the session:
106
+ The council chat TUI (`kd chat`) supports four modes, configured via `council.chat.mode`:
90
107
 
91
- ```bash
92
- kd done
93
- ```
108
+ | Mode | First turn | Auto-turns | Default |
109
+ |------|-----------|------------|---------|
110
+ | `natural` | parallel broadcast | shuffled round-robin | yes |
111
+ | `round_robin` | sequential fixed-order | sequential fixed-order | |
112
+ | `manual` | only @mentioned | only @mentioned | |
113
+ | `broadcast` | parallel to all | parallel to all | |
114
+
115
+ LLM-to-LLM @mentions in responses automatically bump the mentioned member to the front of the auto-turn queue.
94
116
 
95
117
  ## How It Works
96
118
 
@@ -21,49 +21,71 @@ Gastown minus the polecats.
21
21
  uv tool install kingdom-cli
22
22
  ```
23
23
 
24
- ## Getting Started
24
+ ## Workflow Scales
25
+
26
+ `kd` scales down gracefully. You pick the parts of the workflow that fit the size of the work.
27
+
28
+ ### Full workflow (new features)
25
29
 
26
- 1. Initialize the project on your current branch:
30
+ Design with the council, break into tickets, dispatch peasants, review, and merge.
27
31
 
28
32
  ```bash
29
- kd start
33
+ kd start # initialize branch session
34
+ kd chat --new # discuss design with the council TUI
35
+ kd design approve # lock in the design
36
+ kd breakdown # generate tickets from the design
37
+ kd peasant start <id> # dispatch parallel workers
38
+ kd done # archive and clean up
30
39
  ```
31
40
 
32
- 2. Configure council agent CLIs in `.kd/config.json` (check effective config with `kd config show`).
41
+ ### Medium workflow (refactors, smaller features)
33
42
 
34
- 3. Design with the council in the TUI:
43
+ Pull tickets into a branch, work them directly or with peasants. No design phase needed.
35
44
 
36
45
  ```bash
37
- kd chat --new
46
+ kd start
47
+ kd tk pull <id> <id> # pull backlog tickets onto this branch
48
+ kd tk start <id> # work tickets one at a time
49
+ kd tk close <id>
50
+ kd done
38
51
  ```
39
52
 
40
- 4. Break your design into markdown tickets:
53
+ ### Lightweight workflow (bug fixes)
54
+
55
+ Work a single ticket, close it, make a PR. Or batch several bug-fix tickets on one branch.
41
56
 
42
57
  ```bash
43
- kd breakdown
58
+ kd start
59
+ kd tk create "fix: login redirect loop"
60
+ kd tk start <id>
61
+ # ... fix the bug ...
62
+ kd tk close <id>
63
+ kd done
44
64
  ```
45
65
 
46
- 5. Review and refine tickets:
66
+ Design docs, council sessions, and peasant workers are all optional. A branch with one ticket and no design doc is a perfectly valid `kd` workflow.
67
+
68
+ ## Getting Started
47
69
 
48
70
  ```bash
49
- kd ticket list
50
- kd ticket show <id>
71
+ kd init # one-time: create .kd/ directory
72
+ kd start # start a session on the current branch
51
73
  ```
52
74
 
53
- 6. Execute tickets:
54
- - Serial: tell Claude Code or Codex to work tickets directly, or run `kd work <id>`.
55
- - Parallel: dispatch peasants in worktrees.
75
+ Configure council agent CLIs in `.kd/config.json` (check effective config with `kd config show`).
56
76
 
57
- ```bash
58
- kd peasant start <id>
59
- kd peasant status
60
- ```
77
+ ## Chat Modes
61
78
 
62
- 7. Close out the session:
79
+ The council chat TUI (`kd chat`) supports four modes, configured via `council.chat.mode`:
63
80
 
64
- ```bash
65
- kd done
66
- ```
81
+ | Mode | First turn | Auto-turns | Default |
82
+ |------|-----------|------------|---------|
83
+ | `natural` | parallel broadcast | shuffled round-robin | yes |
84
+ | `round_robin` | sequential fixed-order | sequential fixed-order | |
85
+ | `manual` | only @mentioned | only @mentioned | |
86
+ | `broadcast` | parallel to all | parallel to all | |
87
+
88
+ LLM-to-LLM @mentions in responses automatically bump the mentioned member to the front of the auto-turn queue.
67
89
 
68
90
  ## How It Works
69
91
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kingdom-cli"
3
- version = "0.2"
3
+ version = "0.2.1"
4
4
  description = "A markdown file-based CLI for software development with multi-agent council design, markdown tickets, and background worker loops."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -42,6 +42,7 @@ where = ["src"]
42
42
 
43
43
  [tool.setuptools.package-data]
44
44
  "kingdom.skill" = ["*.md", "references/*.md"]
45
+ "kingdom.tui" = ["*.tcss"]
45
46
 
46
47
  [dependency-groups]
47
48
  dev = [
@@ -646,3 +646,84 @@ def extract_stream_thinking(line: str, backend: str) -> str | None:
646
646
  if extractor is None:
647
647
  return None
648
648
  return extractor(line)
649
+
650
+
651
+ # ---------------------------------------------------------------------------
652
+ # Stream tool-use extractors — extract tool invocation names from NDJSON
653
+ # ---------------------------------------------------------------------------
654
+
655
+
656
+ def extract_claude_stream_tool_use(line: str) -> str | None:
657
+ """Extract tool name from a Claude Code stream-json NDJSON line.
658
+
659
+ Claude Code emits ``content_block_start`` with a ``tool_use`` block
660
+ containing the tool name (e.g. "Read", "Bash", "Write").
661
+ """
662
+ try:
663
+ event = json.loads(line)
664
+ except json.JSONDecodeError:
665
+ return None
666
+ if not isinstance(event, dict):
667
+ return None
668
+ if event.get("type") == "stream_event":
669
+ event = event.get("event", {})
670
+ if event.get("type") == "content_block_start":
671
+ block = event.get("content_block", {})
672
+ if block.get("type") == "tool_use":
673
+ return block.get("name")
674
+ return None
675
+
676
+
677
+ def extract_cursor_stream_tool_use(line: str) -> str | None:
678
+ """Extract tool name from a Cursor stream-json NDJSON line.
679
+
680
+ Cursor emits ``{"type": "tool_call", "subtype": "started", ...}``
681
+ when a tool invocation begins. The ``name`` field may or may not
682
+ be present depending on the Cursor version.
683
+ """
684
+ try:
685
+ event = json.loads(line)
686
+ except json.JSONDecodeError:
687
+ return None
688
+ if not isinstance(event, dict):
689
+ return None
690
+ if event.get("type") == "tool_call" and event.get("subtype") == "started":
691
+ return event.get("name") or "tool"
692
+ return None
693
+
694
+
695
+ def extract_codex_stream_tool_use(line: str) -> str | None:
696
+ """Extract tool name from a Codex NDJSON line.
697
+
698
+ Codex emits ``item.completed`` events for tool calls with
699
+ ``item.type == "function_call"``.
700
+ """
701
+ try:
702
+ event = json.loads(line)
703
+ except json.JSONDecodeError:
704
+ return None
705
+ if not isinstance(event, dict):
706
+ return None
707
+ if event.get("type") == "item.completed":
708
+ item = event.get("item", {})
709
+ if item.get("type") == "function_call":
710
+ return item.get("name", "tool")
711
+ return None
712
+
713
+
714
+ STREAM_TOOL_USE_EXTRACTORS: dict[str, StreamExtractor] = {
715
+ "claude_code": extract_claude_stream_tool_use,
716
+ "codex": extract_codex_stream_tool_use,
717
+ "cursor": extract_cursor_stream_tool_use,
718
+ }
719
+
720
+
721
+ def extract_stream_tool_use(line: str, backend: str) -> str | None:
722
+ """Extract tool name from a single NDJSON line for the given backend.
723
+
724
+ Returns the tool name string, or None for non-tool-use events.
725
+ """
726
+ extractor = STREAM_TOOL_USE_EXTRACTORS.get(backend)
727
+ if extractor is None:
728
+ return None
729
+ return extractor(line)