@flydocs/cli 0.6.0-alpha.2 → 0.6.0-alpha.20

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 (148) hide show
  1. package/dist/cli.js +678 -392
  2. package/package.json +1 -1
  3. package/template/.claude/CLAUDE.md +62 -63
  4. package/template/.claude/agents/implementation-agent.md +1 -1
  5. package/template/.claude/agents/pm-agent.md +1 -1
  6. package/template/.claude/commands/activate.md +1 -1
  7. package/template/.claude/commands/attach.md +1 -1
  8. package/template/.claude/commands/block.md +2 -2
  9. package/template/.claude/commands/capture.md +1 -1
  10. package/template/.claude/commands/close.md +1 -1
  11. package/template/.claude/commands/flydocs-setup.md +387 -74
  12. package/template/.claude/commands/flydocs-upgrade.md +48 -37
  13. package/template/.claude/commands/implement.md +1 -1
  14. package/template/.claude/commands/knowledge.md +61 -0
  15. package/template/.claude/commands/new-project.md +1 -1
  16. package/template/.claude/commands/onboard.md +275 -0
  17. package/template/.claude/commands/project-update.md +1 -1
  18. package/template/.claude/commands/refine.md +1 -1
  19. package/template/.claude/commands/review.md +1 -1
  20. package/template/.claude/commands/start-session.md +1 -1
  21. package/template/.claude/commands/status.md +1 -1
  22. package/template/.claude/commands/validate.md +1 -1
  23. package/template/.claude/commands/wrap-session.md +1 -1
  24. package/template/.claude/hooks/auto-approve.py +132 -0
  25. package/template/.claude/hooks/post-pr-check.py +108 -0
  26. package/template/.claude/hooks/post-transition-check.py +94 -0
  27. package/template/.claude/hooks/prompt-submit.py +513 -0
  28. package/template/.claude/hooks/session-start.py +146 -0
  29. package/template/.claude/hooks/stop-gate.py +109 -0
  30. package/template/.claude/settings.json +41 -4
  31. package/template/.claude/skills/README.md +23 -25
  32. package/template/.claude/skills/flydocs-workflow/SKILL.md +134 -42
  33. package/template/.claude/skills/flydocs-workflow/cursor-rule.mdc +9 -8
  34. package/template/.claude/skills/flydocs-workflow/reference/comment-templates.md +1 -0
  35. package/template/.claude/skills/flydocs-workflow/reference/golden-rules.md +28 -17
  36. package/template/.claude/skills/flydocs-workflow/reference/graph-schema.md +116 -0
  37. package/template/.claude/skills/flydocs-workflow/reference/pr-workflow.md +120 -0
  38. package/template/.claude/skills/flydocs-workflow/reference/priority-estimates.md +37 -15
  39. package/template/.claude/skills/flydocs-workflow/reference/service-descriptor-schema.md +251 -0
  40. package/template/.claude/skills/flydocs-workflow/reference/status-workflow.md +26 -26
  41. package/template/.claude/skills/flydocs-workflow/scripts/_local/__init__.py +0 -0
  42. package/template/.claude/skills/{flydocs-local/scripts/flydocs_api.py → flydocs-workflow/scripts/_local/file_store.py} +137 -47
  43. package/template/.claude/skills/flydocs-workflow/scripts/flydocs_api.py +693 -0
  44. package/template/{.flydocs → .claude/skills/flydocs-workflow}/scripts/generate_manifest.py +4 -4
  45. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_build.py +132 -1
  46. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_query.py +18 -5
  47. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_session.py +1 -10
  48. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_update.py +4 -4
  49. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_utils.py +2 -1
  50. package/template/.claude/skills/flydocs-workflow/scripts/issues.py +489 -0
  51. package/template/.claude/skills/flydocs-workflow/scripts/projects.py +144 -0
  52. package/template/.claude/skills/flydocs-workflow/scripts/pull_services.py +128 -0
  53. package/template/.claude/skills/flydocs-workflow/scripts/push_service.py +132 -0
  54. package/template/.claude/skills/flydocs-workflow/scripts/session.py +54 -0
  55. package/template/.claude/skills/flydocs-workflow/scripts/workspace.py +860 -0
  56. package/template/.claude/skills/flydocs-workflow/session.md +63 -25
  57. package/template/.claude/skills/flydocs-workflow/stages/activate.md +18 -7
  58. package/template/.claude/skills/flydocs-workflow/stages/capture.md +10 -5
  59. package/template/.claude/skills/flydocs-workflow/stages/close.md +4 -3
  60. package/template/.claude/skills/flydocs-workflow/stages/implement.md +33 -9
  61. package/template/.claude/skills/flydocs-workflow/stages/refine.md +22 -6
  62. package/template/.claude/skills/flydocs-workflow/stages/review.md +16 -4
  63. package/template/.claude/skills/flydocs-workflow/stages/validate.md +3 -1
  64. package/template/.claude/skills/flydocs-workflow/templates/pr/default.md +33 -0
  65. package/template/.cursor/agents/implementation-agent.md +1 -1
  66. package/template/.cursor/agents/pm-agent.md +2 -2
  67. package/template/.cursor/hooks.json +10 -3
  68. package/template/.env.example +6 -6
  69. package/template/.flydocs/config.json +5 -18
  70. package/template/.flydocs/templates/README.md +13 -14
  71. package/template/.flydocs/templates/quick-capture.md +4 -8
  72. package/template/.flydocs/version +1 -1
  73. package/template/AGENTS.md +39 -32
  74. package/template/CHANGELOG.md +39 -0
  75. package/template/flydocs/README.md +1 -3
  76. package/template/flydocs/context/project.md +6 -3
  77. package/template/flydocs/design-system/README.md +3 -3
  78. package/template/flydocs/knowledge/INDEX.md +38 -53
  79. package/template/flydocs/knowledge/README.md +60 -9
  80. package/template/flydocs/knowledge/templates/decision.md +47 -0
  81. package/template/flydocs/knowledge/templates/feature.md +35 -0
  82. package/template/flydocs/knowledge/templates/note.md +25 -0
  83. package/template/manifest.json +24 -20
  84. package/template/.claude/skills/flydocs-cloud/SKILL.md +0 -111
  85. package/template/.claude/skills/flydocs-cloud/cursor-rule.mdc +0 -50
  86. package/template/.claude/skills/flydocs-cloud/scripts/assign.py +0 -22
  87. package/template/.claude/skills/flydocs-cloud/scripts/assign_cycle.py +0 -28
  88. package/template/.claude/skills/flydocs-cloud/scripts/assign_milestone.py +0 -22
  89. package/template/.claude/skills/flydocs-cloud/scripts/comment.py +0 -29
  90. package/template/.claude/skills/flydocs-cloud/scripts/create_issue.py +0 -63
  91. package/template/.claude/skills/flydocs-cloud/scripts/create_milestone.py +0 -35
  92. package/template/.claude/skills/flydocs-cloud/scripts/create_project.py +0 -33
  93. package/template/.claude/skills/flydocs-cloud/scripts/create_team.py +0 -39
  94. package/template/.claude/skills/flydocs-cloud/scripts/estimate.py +0 -29
  95. package/template/.claude/skills/flydocs-cloud/scripts/flydocs_api.py +0 -210
  96. package/template/.claude/skills/flydocs-cloud/scripts/get_issue.py +0 -24
  97. package/template/.claude/skills/flydocs-cloud/scripts/link.py +0 -28
  98. package/template/.claude/skills/flydocs-cloud/scripts/list_cycles.py +0 -28
  99. package/template/.claude/skills/flydocs-cloud/scripts/list_issues.py +0 -44
  100. package/template/.claude/skills/flydocs-cloud/scripts/list_labels.py +0 -19
  101. package/template/.claude/skills/flydocs-cloud/scripts/list_milestones.py +0 -28
  102. package/template/.claude/skills/flydocs-cloud/scripts/list_projects.py +0 -31
  103. package/template/.claude/skills/flydocs-cloud/scripts/list_teams.py +0 -19
  104. package/template/.claude/skills/flydocs-cloud/scripts/priority.py +0 -29
  105. package/template/.claude/skills/flydocs-cloud/scripts/project_update.py +0 -45
  106. package/template/.claude/skills/flydocs-cloud/scripts/set_labels.py +0 -68
  107. package/template/.claude/skills/flydocs-cloud/scripts/set_team.py +0 -41
  108. package/template/.claude/skills/flydocs-cloud/scripts/transition.py +0 -26
  109. package/template/.claude/skills/flydocs-cloud/scripts/update_description.py +0 -36
  110. package/template/.claude/skills/flydocs-cloud/scripts/update_issue.py +0 -82
  111. package/template/.claude/skills/flydocs-context-graph/SKILL.md +0 -87
  112. package/template/.claude/skills/flydocs-context-graph/schema.md +0 -78
  113. package/template/.claude/skills/flydocs-context-graph/scripts/graph_context.py +0 -338
  114. package/template/.claude/skills/flydocs-context7/SKILL.md +0 -105
  115. package/template/.claude/skills/flydocs-context7/cursor-rule.mdc +0 -49
  116. package/template/.claude/skills/flydocs-context7/scripts/context7.py +0 -293
  117. package/template/.claude/skills/flydocs-estimates/SKILL.md +0 -384
  118. package/template/.claude/skills/flydocs-figma/SKILL.md +0 -377
  119. package/template/.claude/skills/flydocs-figma/references/PROMPTING.md +0 -108
  120. package/template/.claude/skills/flydocs-figma/references/TROUBLESHOOTING.md +0 -112
  121. package/template/.claude/skills/flydocs-local/SKILL.md +0 -103
  122. package/template/.claude/skills/flydocs-local/cursor-rule.mdc +0 -43
  123. package/template/.claude/skills/flydocs-local/scripts/assign.py +0 -20
  124. package/template/.claude/skills/flydocs-local/scripts/comment.py +0 -27
  125. package/template/.claude/skills/flydocs-local/scripts/create_issue.py +0 -44
  126. package/template/.claude/skills/flydocs-local/scripts/estimate.py +0 -37
  127. package/template/.claude/skills/flydocs-local/scripts/get_issue.py +0 -20
  128. package/template/.claude/skills/flydocs-local/scripts/link.py +0 -41
  129. package/template/.claude/skills/flydocs-local/scripts/list_issues.py +0 -34
  130. package/template/.claude/skills/flydocs-local/scripts/priority.py +0 -37
  131. package/template/.claude/skills/flydocs-local/scripts/project_update.py +0 -67
  132. package/template/.claude/skills/flydocs-local/scripts/status_summary.py +0 -16
  133. package/template/.claude/skills/flydocs-local/scripts/transition.py +0 -24
  134. package/template/.claude/skills/flydocs-local/scripts/update_description.py +0 -35
  135. package/template/.claude/skills/flydocs-local/scripts/update_issue.py +0 -84
  136. package/template/.flydocs/hooks/auto-approve.py +0 -71
  137. package/template/.flydocs/hooks/prompt-submit.py +0 -277
  138. package/template/.flydocs/scripts/skill_manager.py +0 -541
  139. package/template/.flydocs/templates/bug.md +0 -166
  140. package/template/.flydocs/templates/chore.md +0 -110
  141. package/template/.flydocs/templates/feature.md +0 -173
  142. package/template/.flydocs/templates/idea.md +0 -122
  143. /package/template/{.flydocs → .claude}/hooks/post-edit.py +0 -0
  144. /package/template/.claude/skills/{flydocs-estimates/references → flydocs-workflow/reference}/provider-costs.md +0 -0
  145. /package/template/.claude/skills/flydocs-workflow/templates/{bug.md → issues/bug.md} +0 -0
  146. /package/template/.claude/skills/flydocs-workflow/templates/{chore.md → issues/chore.md} +0 -0
  147. /package/template/.claude/skills/flydocs-workflow/templates/{feature.md → issues/feature.md} +0 -0
  148. /package/template/.claude/skills/flydocs-workflow/templates/{idea.md → issues/idea.md} +0 -0
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env python3
2
+ """Pull workspace service descriptors from the relay.
3
+
4
+ Fetches GET /api/relay/workspace/services and caches the composite
5
+ at .flydocs/cache/workspace-services.json for local use.
6
+
7
+ Usage:
8
+ python3 .claude/skills/flydocs-workflow/scripts/pull_services.py [--root PATH]
9
+ """
10
+
11
+ import argparse
12
+ import json
13
+ import os
14
+ import sys
15
+ import urllib.error
16
+ import urllib.request
17
+ from datetime import datetime, timezone
18
+ from pathlib import Path
19
+
20
+ sys.path.insert(0, str(Path(__file__).parent))
21
+ from graph_utils import find_project_root, fail
22
+
23
+
24
+ def load_api_key(root):
25
+ """Load FLYDOCS_API_KEY from environment or .env files."""
26
+ if os.environ.get("FLYDOCS_API_KEY"):
27
+ return os.environ["FLYDOCS_API_KEY"]
28
+ for name in [".env.local", ".env"]:
29
+ env_file = root / name
30
+ if env_file.exists():
31
+ with open(env_file, "r") as f:
32
+ for line in f:
33
+ line = line.strip()
34
+ if line.startswith("#") or "=" not in line:
35
+ continue
36
+ k, _, v = line.partition("=")
37
+ if k.strip() == "FLYDOCS_API_KEY":
38
+ v = v.strip().strip("\"'")
39
+ return v if v else None
40
+ return None
41
+
42
+
43
+ def load_config(root):
44
+ """Load .flydocs/config.json."""
45
+ config_path = root / ".flydocs" / "config.json"
46
+ if config_path.exists():
47
+ with open(config_path, "r") as f:
48
+ return json.load(f)
49
+ return {}
50
+
51
+
52
+ def resolve_base_url(config):
53
+ """Resolve relay base URL."""
54
+ env_url = os.environ.get("FLYDOCS_RELAY_URL")
55
+ if env_url:
56
+ return env_url.rstrip("/")
57
+ config_url = config.get("relay", {}).get("url")
58
+ if config_url:
59
+ return config_url.rstrip("/")
60
+ return "https://app.flydocs.ai/api/relay"
61
+
62
+
63
+ def main():
64
+ parser = argparse.ArgumentParser(description="Pull workspace service descriptors")
65
+ parser.add_argument("--root", type=str, default=None, help="Project root")
66
+ args = parser.parse_args()
67
+
68
+ root = Path(args.root) if args.root else find_project_root()
69
+ if not root:
70
+ fail("Could not find project root (no .flydocs/ directory found)")
71
+
72
+ config = load_config(root)
73
+ api_key = load_api_key(root)
74
+ if not api_key:
75
+ fail("FLYDOCS_API_KEY not found. Set in environment or .env file.")
76
+
77
+ workspace_id = config.get("workspaceId")
78
+ if not workspace_id:
79
+ fail("workspaceId not found in .flydocs/config.json. Run /flydocs-setup first.")
80
+
81
+ base_url = resolve_base_url(config)
82
+
83
+ # Fetch workspace services composite
84
+ url = f"{base_url}/workspace/services"
85
+ headers = {
86
+ "Authorization": f"Bearer {api_key}",
87
+ "X-Workspace": workspace_id,
88
+ "Accept": "application/json",
89
+ }
90
+
91
+ try:
92
+ req = urllib.request.Request(url, headers=headers, method="GET")
93
+ with urllib.request.urlopen(req, timeout=15) as resp:
94
+ result = json.loads(resp.read().decode("utf-8"))
95
+ except urllib.error.HTTPError as e:
96
+ error_body = e.read().decode("utf-8") if e.fp else ""
97
+ try:
98
+ error_data = json.loads(error_body) if error_body else {}
99
+ except json.JSONDecodeError:
100
+ error_data = {"error": error_body}
101
+ fail(f"Relay API error ({e.code}): {error_data.get('error', str(e))}")
102
+ except (urllib.error.URLError, TimeoutError) as e:
103
+ fail(f"Network error: {e}")
104
+
105
+ # Cache the composite locally
106
+ cache_dir = root / ".flydocs" / "cache"
107
+ cache_dir.mkdir(parents=True, exist_ok=True)
108
+ cache_file = cache_dir / "workspace-services.json"
109
+
110
+ cached = {
111
+ "fetchedAt": datetime.now(timezone.utc).isoformat(),
112
+ "services": result,
113
+ }
114
+ cache_file.write_text(json.dumps(cached, indent=2) + "\n", encoding="utf-8")
115
+
116
+ # Report
117
+ repos = result if isinstance(result, list) else result.get("repos", [])
118
+ with_descriptor = sum(1 for r in repos if r.get("serviceDescriptor"))
119
+ print(json.dumps({
120
+ "success": True,
121
+ "totalRepos": len(repos),
122
+ "withDescriptor": with_descriptor,
123
+ "cachedAt": cache_file.name,
124
+ }, indent=2))
125
+
126
+
127
+ if __name__ == "__main__":
128
+ main()
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env python3
2
+ """Push this repo's service descriptor to the relay.
3
+
4
+ Reads flydocs/context/service.json, strips the local-only `structure` section,
5
+ and pushes to PUT /api/relay/workspace/service.
6
+
7
+ Usage:
8
+ python3 .claude/skills/flydocs-workflow/scripts/push_service.py [--root PATH]
9
+ """
10
+
11
+ import argparse
12
+ import json
13
+ import os
14
+ import sys
15
+ import urllib.error
16
+ import urllib.request
17
+ from pathlib import Path
18
+
19
+ sys.path.insert(0, str(Path(__file__).parent))
20
+ from graph_utils import find_project_root, fail
21
+
22
+
23
+ def load_api_key(root):
24
+ """Load FLYDOCS_API_KEY from environment or .env files."""
25
+ if os.environ.get("FLYDOCS_API_KEY"):
26
+ return os.environ["FLYDOCS_API_KEY"]
27
+ for name in [".env.local", ".env"]:
28
+ env_file = root / name
29
+ if env_file.exists():
30
+ with open(env_file, "r") as f:
31
+ for line in f:
32
+ line = line.strip()
33
+ if line.startswith("#") or "=" not in line:
34
+ continue
35
+ k, _, v = line.partition("=")
36
+ if k.strip() == "FLYDOCS_API_KEY":
37
+ v = v.strip().strip("\"'")
38
+ return v if v else None
39
+ return None
40
+
41
+
42
+ def load_config(root):
43
+ """Load .flydocs/config.json."""
44
+ config_path = root / ".flydocs" / "config.json"
45
+ if config_path.exists():
46
+ with open(config_path, "r") as f:
47
+ return json.load(f)
48
+ return {}
49
+
50
+
51
+ def resolve_base_url(config):
52
+ """Resolve relay base URL."""
53
+ env_url = os.environ.get("FLYDOCS_RELAY_URL")
54
+ if env_url:
55
+ return env_url.rstrip("/")
56
+ config_url = config.get("relay", {}).get("url")
57
+ if config_url:
58
+ return config_url.rstrip("/")
59
+ return "https://app.flydocs.ai/api/relay"
60
+
61
+
62
+ def main():
63
+ parser = argparse.ArgumentParser(description="Push service descriptor to relay")
64
+ parser.add_argument("--root", type=str, default=None, help="Project root")
65
+ args = parser.parse_args()
66
+
67
+ root = Path(args.root) if args.root else find_project_root()
68
+ if not root:
69
+ fail("Could not find project root (no .flydocs/ directory found)")
70
+
71
+ # Load service descriptor
72
+ service_file = root / "flydocs" / "context" / "service.json"
73
+ if not service_file.exists():
74
+ fail("No service descriptor found at flydocs/context/service.json. Run /flydocs-setup first.")
75
+
76
+ descriptor = json.loads(service_file.read_text(encoding="utf-8"))
77
+
78
+ # Strip local-only structure section before pushing
79
+ export_descriptor = {k: v for k, v in descriptor.items() if k != "structure"}
80
+
81
+ # Load config and credentials
82
+ config = load_config(root)
83
+ api_key = load_api_key(root)
84
+ if not api_key:
85
+ fail("FLYDOCS_API_KEY not found. Set in environment or .env file.")
86
+
87
+ workspace_id = config.get("workspaceId")
88
+ if not workspace_id:
89
+ fail("workspaceId not found in .flydocs/config.json. Run /flydocs-setup first.")
90
+
91
+ repo_slug = config.get("workspace", {}).get("repoSlug")
92
+ if not repo_slug:
93
+ repo_slug = descriptor.get("repoSlug")
94
+ if not repo_slug:
95
+ fail("repoSlug not found in config or service descriptor.")
96
+
97
+ base_url = resolve_base_url(config)
98
+
99
+ # Push descriptor
100
+ url = f"{base_url}/workspace/service"
101
+ headers = {
102
+ "Authorization": f"Bearer {api_key}",
103
+ "X-Workspace": workspace_id,
104
+ "X-Repo": repo_slug,
105
+ "Content-Type": "application/json",
106
+ "Accept": "application/json",
107
+ }
108
+ data = json.dumps({"descriptor": export_descriptor}).encode("utf-8")
109
+
110
+ try:
111
+ req = urllib.request.Request(url, data=data, headers=headers, method="PUT")
112
+ with urllib.request.urlopen(req, timeout=15) as resp:
113
+ result = json.loads(resp.read().decode("utf-8"))
114
+ print(json.dumps({
115
+ "success": True,
116
+ "repoSlug": repo_slug,
117
+ "fieldsExported": list(export_descriptor.keys()),
118
+ "response": result,
119
+ }, indent=2))
120
+ except urllib.error.HTTPError as e:
121
+ error_body = e.read().decode("utf-8") if e.fp else ""
122
+ try:
123
+ error_data = json.loads(error_body) if error_body else {}
124
+ except json.JSONDecodeError:
125
+ error_data = {"error": error_body}
126
+ fail(f"Relay API error ({e.code}): {error_data.get('error', str(e))}")
127
+ except (urllib.error.URLError, TimeoutError) as e:
128
+ fail(f"Network error: {e}")
129
+
130
+
131
+ if __name__ == "__main__":
132
+ main()
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env python3
2
+ """Session operations dispatcher — project updates and status summary."""
3
+
4
+ import argparse
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ sys.path.insert(0, str(Path(__file__).parent))
9
+ from flydocs_api import get_client, output_json, fail, resolve_text_input
10
+
11
+
12
+ def cmd_project_update(args):
13
+ body = resolve_text_input(text_arg=args.body, file_arg=args.body_file)
14
+ if not body:
15
+ fail("Provide body via --body, --body-file, or stdin")
16
+ client = get_client()
17
+ # Resolve project: explicit flag > activeProjects[0] > relay discovery
18
+ project_id = args.project
19
+ if not project_id and client.is_cloud:
20
+ active = client.config.get("workspace", {}).get("activeProjects", [])
21
+ if active:
22
+ project_id = active[0]
23
+ result = client.project_update(args.health, body, project_id=project_id)
24
+ output_json(result)
25
+
26
+
27
+ def cmd_status_summary(args):
28
+ client = get_client()
29
+ result = client.status_summary()
30
+ output_json(result)
31
+
32
+
33
+ def main():
34
+ parser = argparse.ArgumentParser(description="FlyDocs session operations")
35
+ sub = parser.add_subparsers(dest="command", required=True)
36
+
37
+ p = sub.add_parser("project-update", help="Post a project update")
38
+ p.add_argument("--health", required=True, choices=["onTrack", "atRisk", "offTrack"])
39
+ p.add_argument("--body", default=None)
40
+ p.add_argument("--body-file", default=None, dest="body_file")
41
+ p.add_argument("--project", default=None, help="Target project ID (defaults from activeProjects)")
42
+
43
+ sub.add_parser("status-summary", help="Show issue status counts")
44
+
45
+ args = parser.parse_args()
46
+ commands = {
47
+ "project-update": cmd_project_update,
48
+ "status-summary": cmd_status_summary,
49
+ }
50
+ commands[args.command](args)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()