issue-flow 0.4.4.post1__tar.gz → 0.4.4.post3__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 (74) hide show
  1. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/PKG-INFO +10 -1
  2. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/README.md +9 -0
  3. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/pyproject.toml +1 -1
  4. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/agent.py +122 -0
  5. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/cli.py +46 -0
  6. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/rules/_body.md.j2 +2 -0
  7. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/LICENSE +0 -0
  8. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/__init__.py +0 -0
  9. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/config.py +0 -0
  10. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/dependencies.py +0 -0
  11. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/editors.py +0 -0
  12. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/epicplan.py +0 -0
  13. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/gitutils.py +0 -0
  14. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/graphify.py +0 -0
  15. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/init.py +0 -0
  16. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/modes.py +0 -0
  17. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/modes.toml +0 -0
  18. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/project.py +0 -0
  19. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/py.typed +0 -0
  20. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/queueplan.py +0 -0
  21. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/step_profiles.py +0 -0
  22. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/step_profiles.toml +0 -0
  23. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/__init__.py +0 -0
  24. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/__init__.py +0 -0
  25. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-archive.md.j2 +0 -0
  26. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-cleanup.md.j2 +0 -0
  27. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-close.md.j2 +0 -0
  28. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-cycle.md.j2 +0 -0
  29. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-epic.md.j2 +0 -0
  30. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-fix.md.j2 +0 -0
  31. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-graphify.md.j2 +0 -0
  32. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-init.md.j2 +0 -0
  33. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-pause.md.j2 +0 -0
  34. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-pick.md.j2 +0 -0
  35. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-plan.md.j2 +0 -0
  36. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-start.md.j2 +0 -0
  37. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-status.md.j2 +0 -0
  38. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow-yolo.md.j2 +0 -0
  39. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/commands/iflow.md.j2 +0 -0
  40. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/designs/python-quality-tools.md.j2 +0 -0
  41. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/docs/__init__.py +0 -0
  42. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/docs/issue-workflow.md.j2 +0 -0
  43. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/docs/this-project.md.j2 +0 -0
  44. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/rules/AGENTS.md.j2 +0 -0
  45. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/rules/CLAUDE.md.j2 +0 -0
  46. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/rules/__init__.py +0 -0
  47. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/rules/issueflow-rules.mdc.j2 +0 -0
  48. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/_invocation_forms.md.j2 +0 -0
  49. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/_model_directive.md.j2 +0 -0
  50. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/_resolve_project_root.md.j2 +0 -0
  51. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/caveman/SKILL.md.j2 +0 -0
  52. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/grill_me/SKILL.md.j2 +0 -0
  53. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_archive/SKILL.md.j2 +0 -0
  54. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_cleanup/SKILL.md.j2 +0 -0
  55. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_close/SKILL.md.j2 +0 -0
  56. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_comments/SKILL.md.j2 +0 -0
  57. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_cycle/SKILL.md.j2 +0 -0
  58. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_epic/SKILL.md.j2 +0 -0
  59. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_fix/SKILL.md.j2 +0 -0
  60. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_graphify/SKILL.md.j2 +0 -0
  61. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_history_update/SKILL.md.j2 +0 -0
  62. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_iflow/SKILL.md.j2 +0 -0
  63. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_init/SKILL.md.j2 +0 -0
  64. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_pause/SKILL.md.j2 +0 -0
  65. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_pick/SKILL.md.j2 +0 -0
  66. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_plan/SKILL.md.j2 +0 -0
  67. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_start/SKILL.md.j2 +0 -0
  68. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_status/SKILL.md.j2 +0 -0
  69. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_version_bump/SKILL.md.j2 +0 -0
  70. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/skills/iflow_yolo/SKILL.md.j2 +0 -0
  71. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templates/tools/README.md.j2 +0 -0
  72. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/templating.py +0 -0
  73. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/tracking.py +0 -0
  74. {issue_flow-0.4.4.post1 → issue_flow-0.4.4.post3}/src/issue_flow/versionplan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: issue-flow
3
- Version: 0.4.4.post1
3
+ Version: 0.4.4.post3
4
4
  Summary: Agents should behave. Let them follow the issue flow.
5
5
  Keywords: cursor,ai,agents,issue-tracking,workflow
6
6
  Author: jepegit
@@ -33,6 +33,14 @@ Agents should behave. Let them follow the issue flow.
33
33
 
34
34
  **Full documentation:** <https://issue-flow.readthedocs.io/>
35
35
 
36
+
37
+ ## Why use it
38
+
39
+ I guess it is just a matter of taste. If you are familiar with coding using agents and harnesses, `issue-flow` could very well slow you down. But...
40
+
41
+ Maybe that is a good thing?
42
+
43
+
36
44
  ## What it does
37
45
 
38
46
  Running `issue-flow init` in your project root creates:
@@ -46,6 +54,7 @@ your-project/
46
54
  03-solved-issues/ # Completed issues archive
47
55
  04-designs-and-guides/ # Durable project context and decisions
48
56
  this-project.md # Hand-editable project brief (created if missing)
57
+ 05-epics/ # Staged epic plans (epic<N>_plan.md)
49
58
  .cursor/
50
59
  skills/ # Agent Skills (/iflow, /iflow-pick, /iflow-init,
51
60
  # /iflow-plan, /iflow-start, /iflow-close, ...)
@@ -6,6 +6,14 @@ Agents should behave. Let them follow the issue flow.
6
6
 
7
7
  **Full documentation:** <https://issue-flow.readthedocs.io/>
8
8
 
9
+
10
+ ## Why use it
11
+
12
+ I guess it is just a matter of taste. If you are familiar with coding using agents and harnesses, `issue-flow` could very well slow you down. But...
13
+
14
+ Maybe that is a good thing?
15
+
16
+
9
17
  ## What it does
10
18
 
11
19
  Running `issue-flow init` in your project root creates:
@@ -19,6 +27,7 @@ your-project/
19
27
  03-solved-issues/ # Completed issues archive
20
28
  04-designs-and-guides/ # Durable project context and decisions
21
29
  this-project.md # Hand-editable project brief (created if missing)
30
+ 05-epics/ # Staged epic plans (epic<N>_plan.md)
22
31
  .cursor/
23
32
  skills/ # Agent Skills (/iflow, /iflow-pick, /iflow-init,
24
33
  # /iflow-plan, /iflow-start, /iflow-close, ...)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "issue-flow"
3
- version = "0.4.4.post1"
3
+ version = "0.4.4.post3"
4
4
  description = "Agents should behave. Let them follow the issue flow."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1048,6 +1048,128 @@ def run_workspace_init(
1048
1048
  return 0
1049
1049
 
1050
1050
 
1051
+ def run_workspace_update(
1052
+ workspace_dir: Path,
1053
+ console: Console,
1054
+ skip_dep_check: bool,
1055
+ editors: list[str] | None,
1056
+ as_json: bool,
1057
+ ) -> int:
1058
+ """Refresh issue-flow scaffolds in every scaffolded workspace member.
1059
+
1060
+ Discovers ``issueflow-workspace.toml`` above ``workspace_dir``, runs
1061
+ :func:`issue_flow.init.run_update` on each member that carries a
1062
+ ``.issueflows/`` tree, and aggregates per-member success. One dependency
1063
+ check runs up front (unless ``skip_dep_check``); individual member
1064
+ failures do not abort the rest.
1065
+ """
1066
+ import typer
1067
+
1068
+ from issue_flow.init import _dependency_gate, run_update
1069
+
1070
+ start = workspace_dir.resolve()
1071
+ workspace = project.discover_workspace(start)
1072
+
1073
+ def _fail(msg: str) -> int:
1074
+ if as_json:
1075
+ _emit_json(
1076
+ console,
1077
+ {
1078
+ "ok": False,
1079
+ "error": msg,
1080
+ "workspace_root": None,
1081
+ "members": [],
1082
+ "ok_count": 0,
1083
+ "fail_count": 0,
1084
+ },
1085
+ )
1086
+ else:
1087
+ console.print(f"[red]error[/red] {msg}")
1088
+ return 1
1089
+
1090
+ if workspace is None:
1091
+ return _fail(
1092
+ f"no {project.WORKSPACE_FILENAME} found above {start} — run "
1093
+ f"`issue-flow workspace init` from the workspace root first."
1094
+ )
1095
+
1096
+ member_roots = workspace.member_roots()
1097
+ if not member_roots:
1098
+ return _fail(
1099
+ f"no scaffolded member repos found under {workspace.root} — run "
1100
+ "`issue-flow init` inside the member repos first."
1101
+ )
1102
+
1103
+ if not skip_dep_check and not _dependency_gate(skip_dep_check=False):
1104
+ return 1
1105
+
1106
+ import issue_flow.init as init_module
1107
+
1108
+ def _run_member_update(root: Path) -> None:
1109
+ if as_json:
1110
+ saved = init_module.console
1111
+ init_module.console = Console(quiet=True)
1112
+ try:
1113
+ run_update(root, skip_dep_check=True, editors=editors)
1114
+ finally:
1115
+ init_module.console = saved
1116
+ else:
1117
+ run_update(root, skip_dep_check=True, editors=editors)
1118
+
1119
+ if not as_json:
1120
+ console.print(
1121
+ f"\n[bold]Updating issue-flow scaffolds in workspace "
1122
+ f"[cyan]{workspace.root}[/cyan][/bold]"
1123
+ )
1124
+ console.print(f"[dim]{len(member_roots)} member(s)[/dim]\n")
1125
+
1126
+ results: list[dict[str, Any]] = []
1127
+ ok_count = 0
1128
+ fail_count = 0
1129
+
1130
+ for name, root in zip(workspace.members, member_roots, strict=True):
1131
+ entry: dict[str, Any] = {"name": name, "path": str(root)}
1132
+ try:
1133
+ _run_member_update(root)
1134
+ entry["ok"] = True
1135
+ ok_count += 1
1136
+ except typer.Exit as exc:
1137
+ entry["ok"] = False
1138
+ entry["error"] = f"update failed (exit {exc.exit_code})"
1139
+ fail_count += 1
1140
+ results.append(entry)
1141
+
1142
+ payload = {
1143
+ "ok": fail_count == 0,
1144
+ "workspace_root": str(workspace.root),
1145
+ "members": results,
1146
+ "ok_count": ok_count,
1147
+ "fail_count": fail_count,
1148
+ }
1149
+
1150
+ if as_json:
1151
+ _emit_json(console, payload)
1152
+ return 0 if fail_count == 0 else 1
1153
+
1154
+ console.print()
1155
+ if fail_count == 0:
1156
+ console.print(
1157
+ f"[bold green]Updated {ok_count}/{len(member_roots)} member(s).[/bold green]"
1158
+ )
1159
+ else:
1160
+ console.print(
1161
+ f"[bold yellow]Updated {ok_count}/{len(member_roots)} member(s); "
1162
+ f"{fail_count} failed.[/bold yellow]"
1163
+ )
1164
+ for entry in results:
1165
+ if not entry.get("ok"):
1166
+ console.print(
1167
+ f" [red]fail[/red] {escape(entry['name'])}: "
1168
+ f"{escape(str(entry.get('error', 'unknown error')))}"
1169
+ )
1170
+ return 0 if fail_count == 0 else 1
1171
+
1172
+
1051
1173
  # ---------------------------------------------------------------------------
1052
1174
  # agent sweep
1053
1175
  # ---------------------------------------------------------------------------
@@ -599,6 +599,52 @@ def workspace_init(
599
599
  )
600
600
 
601
601
 
602
+ @workspace_app.command("update")
603
+ def workspace_update(
604
+ workspace_dir: Path = typer.Argument(
605
+ default=Path("."),
606
+ help=(
607
+ "Workspace root directory — the folder that contains the member "
608
+ "repos (defaults to current directory)."
609
+ ),
610
+ exists=True,
611
+ file_okay=False,
612
+ resolve_path=True,
613
+ ),
614
+ skip_dep_check: bool = typer.Option(
615
+ False,
616
+ "--skip-dep-check",
617
+ help=(
618
+ "Skip the external-CLI dependency check (git, gh) and the "
619
+ "confirmation prompt that follows if anything is missing."
620
+ ),
621
+ ),
622
+ editor: list[str] = typer.Option(
623
+ ["cursor"],
624
+ "--editor",
625
+ "-e",
626
+ help=_EDITOR_HELP,
627
+ ),
628
+ json_output: bool = typer.Option(
629
+ False, "--json", help="Emit a machine-readable JSON object."
630
+ ),
631
+ ) -> None:
632
+ """Refresh packaged scaffolds in every scaffolded workspace member.
633
+
634
+ Walks up from ``workspace_dir`` for ``issueflow-workspace.toml``, then
635
+ runs ``issue-flow update`` in each member repo that carries a
636
+ ``.issueflows/`` tree. Per-member ``mode`` and ``skill_level`` come from
637
+ each repo's own ``config.toml``.
638
+ """
639
+ from issue_flow.agent import run_workspace_update
640
+
641
+ raise typer.Exit(
642
+ code=run_workspace_update(
643
+ workspace_dir, _console, skip_dep_check, editor, json_output
644
+ )
645
+ )
646
+
647
+
602
648
  app.add_typer(agent_app)
603
649
  app.add_typer(config_app)
604
650
  app.add_typer(workspace_app)
@@ -80,6 +80,8 @@ If the project uses something else, use whatever it documents (e.g. activate its
80
80
  {{ partly_solved_folder }}/
81
81
  {{ solved_folder }}/
82
82
  {{ designs_folder }}/
83
+ {{ epics_folder }}/
84
+ epicXX_plan.md
83
85
  pyproject.toml
84
86
  readme.md
85
87
  ...