@flydocs/cli 0.6.0-alpha.3 → 0.6.0-alpha.31

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 (151) hide show
  1. package/dist/cli.js +2053 -469
  2. package/package.json +1 -1
  3. package/template/.claude/CLAUDE.md +43 -48
  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 +359 -72
  12. package/template/.claude/commands/flydocs-upgrade.md +26 -27
  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 +212 -0
  25. package/template/.claude/hooks/post-pr-check.py +108 -0
  26. package/template/.claude/hooks/post-transition-check.py +281 -0
  27. package/template/.claude/hooks/prompt-submit.py +554 -0
  28. package/template/.claude/hooks/session-start.py +262 -0
  29. package/template/.claude/hooks/stop-gate.py +162 -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 +260 -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 +724 -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 +738 -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/test_enforcement.py +225 -0
  56. package/template/.claude/skills/flydocs-workflow/scripts/workspace.py +902 -0
  57. package/template/.claude/skills/flydocs-workflow/session.md +87 -29
  58. package/template/.claude/skills/flydocs-workflow/stages/activate.md +18 -7
  59. package/template/.claude/skills/flydocs-workflow/stages/capture.md +10 -5
  60. package/template/.claude/skills/flydocs-workflow/stages/close.md +4 -3
  61. package/template/.claude/skills/flydocs-workflow/stages/implement.md +33 -9
  62. package/template/.claude/skills/flydocs-workflow/stages/refine.md +22 -6
  63. package/template/.claude/skills/flydocs-workflow/stages/review.md +16 -4
  64. package/template/.claude/skills/flydocs-workflow/stages/validate.md +3 -1
  65. package/template/.claude/skills/flydocs-workflow/templates/pr/default.md +33 -0
  66. package/template/.cursor/agents/implementation-agent.md +1 -1
  67. package/template/.cursor/agents/pm-agent.md +2 -2
  68. package/template/.cursor/hooks.json +10 -3
  69. package/template/.env.example +6 -6
  70. package/template/.flydocs/config.json +5 -18
  71. package/template/.flydocs/templates/README.md +13 -14
  72. package/template/.flydocs/templates/bug.md +17 -153
  73. package/template/.flydocs/templates/chore.md +10 -98
  74. package/template/.flydocs/templates/feature.md +12 -158
  75. package/template/.flydocs/templates/idea.md +11 -111
  76. package/template/.flydocs/templates/quick-capture.md +4 -8
  77. package/template/.flydocs/version +1 -1
  78. package/template/AGENTS.md +44 -32
  79. package/template/CHANGELOG.md +37 -0
  80. package/template/flydocs/README.md +1 -3
  81. package/template/flydocs/context/project.md +6 -3
  82. package/template/flydocs/design-system/README.md +3 -3
  83. package/template/flydocs/knowledge/INDEX.md +38 -53
  84. package/template/flydocs/knowledge/README.md +60 -9
  85. package/template/flydocs/knowledge/templates/decision.md +47 -0
  86. package/template/flydocs/knowledge/templates/feature.md +35 -0
  87. package/template/flydocs/knowledge/templates/note.md +25 -0
  88. package/template/manifest.json +24 -20
  89. package/template/.claude/skills/flydocs-cloud/SKILL.md +0 -113
  90. package/template/.claude/skills/flydocs-cloud/cursor-rule.mdc +0 -50
  91. package/template/.claude/skills/flydocs-cloud/scripts/assign.py +0 -22
  92. package/template/.claude/skills/flydocs-cloud/scripts/assign_cycle.py +0 -28
  93. package/template/.claude/skills/flydocs-cloud/scripts/assign_milestone.py +0 -22
  94. package/template/.claude/skills/flydocs-cloud/scripts/comment.py +0 -29
  95. package/template/.claude/skills/flydocs-cloud/scripts/create_issue.py +0 -66
  96. package/template/.claude/skills/flydocs-cloud/scripts/create_milestone.py +0 -35
  97. package/template/.claude/skills/flydocs-cloud/scripts/create_project.py +0 -33
  98. package/template/.claude/skills/flydocs-cloud/scripts/create_team.py +0 -39
  99. package/template/.claude/skills/flydocs-cloud/scripts/estimate.py +0 -29
  100. package/template/.claude/skills/flydocs-cloud/scripts/flydocs_api.py +0 -210
  101. package/template/.claude/skills/flydocs-cloud/scripts/get_issue.py +0 -24
  102. package/template/.claude/skills/flydocs-cloud/scripts/link.py +0 -28
  103. package/template/.claude/skills/flydocs-cloud/scripts/list_cycles.py +0 -28
  104. package/template/.claude/skills/flydocs-cloud/scripts/list_issues.py +0 -44
  105. package/template/.claude/skills/flydocs-cloud/scripts/list_labels.py +0 -19
  106. package/template/.claude/skills/flydocs-cloud/scripts/list_milestones.py +0 -28
  107. package/template/.claude/skills/flydocs-cloud/scripts/list_projects.py +0 -31
  108. package/template/.claude/skills/flydocs-cloud/scripts/list_providers.py +0 -19
  109. package/template/.claude/skills/flydocs-cloud/scripts/list_teams.py +0 -19
  110. package/template/.claude/skills/flydocs-cloud/scripts/priority.py +0 -29
  111. package/template/.claude/skills/flydocs-cloud/scripts/project_update.py +0 -45
  112. package/template/.claude/skills/flydocs-cloud/scripts/set_labels.py +0 -68
  113. package/template/.claude/skills/flydocs-cloud/scripts/set_provider.py +0 -46
  114. package/template/.claude/skills/flydocs-cloud/scripts/set_team.py +0 -41
  115. package/template/.claude/skills/flydocs-cloud/scripts/transition.py +0 -26
  116. package/template/.claude/skills/flydocs-cloud/scripts/update_description.py +0 -36
  117. package/template/.claude/skills/flydocs-cloud/scripts/update_issue.py +0 -82
  118. package/template/.claude/skills/flydocs-context-graph/SKILL.md +0 -87
  119. package/template/.claude/skills/flydocs-context-graph/schema.md +0 -78
  120. package/template/.claude/skills/flydocs-context-graph/scripts/graph_context.py +0 -338
  121. package/template/.claude/skills/flydocs-context7/SKILL.md +0 -105
  122. package/template/.claude/skills/flydocs-context7/cursor-rule.mdc +0 -49
  123. package/template/.claude/skills/flydocs-context7/scripts/context7.py +0 -293
  124. package/template/.claude/skills/flydocs-estimates/SKILL.md +0 -384
  125. package/template/.claude/skills/flydocs-figma/SKILL.md +0 -377
  126. package/template/.claude/skills/flydocs-figma/references/PROMPTING.md +0 -108
  127. package/template/.claude/skills/flydocs-figma/references/TROUBLESHOOTING.md +0 -112
  128. package/template/.claude/skills/flydocs-local/SKILL.md +0 -103
  129. package/template/.claude/skills/flydocs-local/cursor-rule.mdc +0 -43
  130. package/template/.claude/skills/flydocs-local/scripts/assign.py +0 -20
  131. package/template/.claude/skills/flydocs-local/scripts/comment.py +0 -27
  132. package/template/.claude/skills/flydocs-local/scripts/create_issue.py +0 -44
  133. package/template/.claude/skills/flydocs-local/scripts/estimate.py +0 -37
  134. package/template/.claude/skills/flydocs-local/scripts/get_issue.py +0 -20
  135. package/template/.claude/skills/flydocs-local/scripts/link.py +0 -41
  136. package/template/.claude/skills/flydocs-local/scripts/list_issues.py +0 -34
  137. package/template/.claude/skills/flydocs-local/scripts/priority.py +0 -37
  138. package/template/.claude/skills/flydocs-local/scripts/project_update.py +0 -67
  139. package/template/.claude/skills/flydocs-local/scripts/status_summary.py +0 -16
  140. package/template/.claude/skills/flydocs-local/scripts/transition.py +0 -24
  141. package/template/.claude/skills/flydocs-local/scripts/update_description.py +0 -35
  142. package/template/.claude/skills/flydocs-local/scripts/update_issue.py +0 -84
  143. package/template/.flydocs/hooks/auto-approve.py +0 -71
  144. package/template/.flydocs/hooks/prompt-submit.py +0 -277
  145. package/template/.flydocs/scripts/skill_manager.py +0 -541
  146. /package/template/{.flydocs → .claude}/hooks/post-edit.py +0 -0
  147. /package/template/.claude/skills/{flydocs-estimates/references → flydocs-workflow/reference}/provider-costs.md +0 -0
  148. /package/template/.claude/skills/flydocs-workflow/templates/{bug.md → issues/bug.md} +0 -0
  149. /package/template/.claude/skills/flydocs-workflow/templates/{chore.md → issues/chore.md} +0 -0
  150. /package/template/.claude/skills/flydocs-workflow/templates/{feature.md → issues/feature.md} +0 -0
  151. /package/template/.claude/skills/flydocs-workflow/templates/{idea.md → issues/idea.md} +0 -0
@@ -1,293 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Context7 API client for fetching library documentation.
3
-
4
- Queries the Context7 REST API to search for libraries and retrieve
5
- LLM-ready documentation. Replaces the Context7 MCP server with a
6
- lightweight script that follows the FlyDocs mechanism pattern.
7
-
8
- Usage:
9
- python3 .claude/skills/flydocs-context7/scripts/context7.py \\
10
- search <library_name> [query]
11
-
12
- python3 .claude/skills/flydocs-context7/scripts/context7.py \\
13
- docs <library_id> <query> [--type txt|json] [--tokens N]
14
- """
15
-
16
- import argparse
17
- import json
18
- import os
19
- import sys
20
- import urllib.error
21
- import urllib.parse
22
- import urllib.request
23
- from pathlib import Path
24
-
25
- BASE_URL = "https://context7.com/api/v2"
26
- DEFAULT_TIMEOUT = 10
27
- DEFAULT_TOKENS = 5000
28
-
29
-
30
- # --- Helpers ---
31
-
32
-
33
- def fail(message):
34
- """Print error to stderr and exit 1."""
35
- print(message, file=sys.stderr)
36
- sys.exit(1)
37
-
38
-
39
- def output_json(data):
40
- """Print JSON to stdout."""
41
- print(json.dumps(data, indent=2))
42
-
43
-
44
- def find_project_root(start=None):
45
- """Walk up from start (or script location) to find the directory containing .flydocs/."""
46
- current = Path(start) if start else Path(__file__).resolve().parent
47
- for parent in [current] + list(current.parents):
48
- if (parent / ".flydocs").is_dir():
49
- return parent
50
- return None
51
-
52
-
53
- def read_env_file(root):
54
- """Read .env file at project root and return a dict of key=value pairs."""
55
- env_path = root / ".env"
56
- if not env_path.is_file():
57
- return {}
58
-
59
- env_vars = {}
60
- try:
61
- with open(env_path, "r", encoding="utf-8") as f:
62
- for line in f:
63
- line = line.strip()
64
- # Skip empty lines and comments
65
- if not line or line.startswith("#"):
66
- continue
67
- if "=" not in line:
68
- continue
69
- key, _, value = line.partition("=")
70
- key = key.strip()
71
- value = value.strip()
72
- # Strip surrounding quotes if present
73
- if len(value) >= 2 and value[0] == value[-1] and value[0] in ('"', "'"):
74
- value = value[1:-1]
75
- env_vars[key] = value
76
- except OSError:
77
- pass
78
-
79
- return env_vars
80
-
81
-
82
- def resolve_api_key(args_key):
83
- """Resolve the API key from flag, env var, or .env file. Returns None if unavailable."""
84
- # 1. Explicit flag
85
- if args_key:
86
- return args_key
87
-
88
- # 2. Environment variable
89
- env_key = os.environ.get("CONTEXT7_API_KEY")
90
- if env_key:
91
- return env_key
92
-
93
- # 3. .env file at project root
94
- root = find_project_root()
95
- if root:
96
- env_vars = read_env_file(root)
97
- dotenv_key = env_vars.get("CONTEXT7_API_KEY")
98
- if dotenv_key:
99
- return dotenv_key
100
-
101
- # 4. Anonymous (no key)
102
- return None
103
-
104
-
105
- def api_request(path, params, api_key=None):
106
- """Make a GET request to the Context7 API and return parsed response data.
107
-
108
- Handles HTTP errors, timeouts, and network failures with clear messages.
109
- """
110
- query_string = urllib.parse.urlencode(params)
111
- url = f"{BASE_URL}/{path}?{query_string}"
112
-
113
- request = urllib.request.Request(url)
114
- request.add_header("User-Agent", "flydocs-context7/1.0")
115
-
116
- if api_key:
117
- request.add_header("Authorization", f"Bearer {api_key}")
118
-
119
- try:
120
- with urllib.request.urlopen(request, timeout=DEFAULT_TIMEOUT) as response:
121
- body = response.read().decode("utf-8")
122
- content_type = response.headers.get("Content-Type", "")
123
- if "application/json" in content_type:
124
- return json.loads(body)
125
- return body
126
- except urllib.error.HTTPError as e:
127
- if e.code == 429:
128
- fail("Rate limited by Context7 API. Wait a moment and try again.")
129
- body_text = ""
130
- try:
131
- body_text = e.read().decode("utf-8", errors="replace")
132
- except Exception:
133
- pass
134
- fail(f"Context7 API error (HTTP {e.code}): {e.reason}\n{body_text}".strip())
135
- except urllib.error.URLError as e:
136
- if "timed out" in str(e.reason).lower():
137
- fail("Context7 API request timed out (10s). The service may be slow or unavailable.")
138
- fail(f"Cannot reach Context7 API. Check your network connection.\nDetails: {e.reason}")
139
- except OSError as e:
140
- fail(f"Network error connecting to Context7 API: {e}")
141
-
142
-
143
- # --- Commands ---
144
-
145
-
146
- def cmd_search(args):
147
- """Search for libraries by name and optional query."""
148
- params = {"libraryName": args.library_name}
149
- if args.query:
150
- params["query"] = args.query
151
-
152
- api_key = resolve_api_key(args.key)
153
- data = api_request("libs/search", params, api_key=api_key)
154
-
155
- # Normalize response — API wraps results in {"results": [...]}
156
- if isinstance(data, dict) and "results" in data:
157
- results = data["results"]
158
- elif isinstance(data, list):
159
- results = data
160
- else:
161
- results = []
162
-
163
- if args.type == "json" or args.type is None:
164
- # Default for search is JSON
165
- compact = []
166
- for lib in results:
167
- compact.append({
168
- "id": lib.get("id", ""),
169
- "name": lib.get("title", lib.get("name", "")),
170
- "description": lib.get("description", ""),
171
- "trustScore": lib.get("trustScore", 0),
172
- })
173
- output_json(compact)
174
- else:
175
- # txt format for search — one line per result
176
- for lib in results:
177
- name = lib.get("title", lib.get("name", "unknown"))
178
- lib_id = lib.get("id", "")
179
- desc = lib.get("description", "")
180
- score = lib.get("trustScore", 0)
181
- print(f"{lib_id} {name} (trust: {score})")
182
- if desc:
183
- print(f" {desc}")
184
- print()
185
-
186
-
187
- def cmd_docs(args):
188
- """Fetch documentation for a specific library."""
189
- params = {
190
- "libraryId": args.library_id,
191
- "query": args.query,
192
- }
193
-
194
- output_type = args.type if args.type else "txt"
195
- params["type"] = output_type
196
-
197
- if args.tokens:
198
- params["tokens"] = str(args.tokens)
199
-
200
- api_key = resolve_api_key(args.key)
201
- data = api_request("context", params, api_key=api_key)
202
-
203
- if output_type == "json":
204
- if isinstance(data, str):
205
- # API returned text when we asked for JSON; wrap it
206
- output_json({"content": data})
207
- else:
208
- output_json(data)
209
- else:
210
- # txt — print directly
211
- if isinstance(data, str):
212
- print(data)
213
- elif isinstance(data, dict):
214
- content = data.get("content", data.get("text", ""))
215
- if content:
216
- print(content)
217
- else:
218
- output_json(data)
219
- else:
220
- output_json(data)
221
-
222
-
223
- # --- Main ---
224
-
225
-
226
- def main():
227
- parser = argparse.ArgumentParser(
228
- description="Context7 API client — search libraries and fetch documentation"
229
- )
230
- parser.add_argument(
231
- "--key", type=str, default=None,
232
- help="API key override (default: CONTEXT7_API_KEY env var or .env file)"
233
- )
234
-
235
- subparsers = parser.add_subparsers(dest="command", required=True)
236
-
237
- # search subcommand
238
- search_parser = subparsers.add_parser(
239
- "search",
240
- help="Search for libraries by name"
241
- )
242
- search_parser.add_argument(
243
- "library_name",
244
- help="Library name to search for (e.g., 'react', 'next.js')"
245
- )
246
- search_parser.add_argument(
247
- "query", nargs="?", default=None,
248
- help="Optional search query to refine results"
249
- )
250
- search_parser.add_argument(
251
- "--type", choices=["txt", "json"], default=None,
252
- help="Output format (default: json for search)"
253
- )
254
- search_parser.add_argument(
255
- "--tokens", type=int, default=DEFAULT_TOKENS,
256
- help=f"Max tokens budget hint (default: {DEFAULT_TOKENS})"
257
- )
258
-
259
- # docs subcommand
260
- docs_parser = subparsers.add_parser(
261
- "docs",
262
- help="Fetch documentation for a library"
263
- )
264
- docs_parser.add_argument(
265
- "library_id",
266
- help="Library ID from search results (e.g., '/vercel/next.js')"
267
- )
268
- docs_parser.add_argument(
269
- "query",
270
- help="Documentation query (e.g., 'server components', 'routing')"
271
- )
272
- docs_parser.add_argument(
273
- "--type", choices=["txt", "json"], default=None,
274
- help="Output format (default: txt for docs)"
275
- )
276
- docs_parser.add_argument(
277
- "--tokens", type=int, default=DEFAULT_TOKENS,
278
- help=f"Max tokens budget hint (default: {DEFAULT_TOKENS})"
279
- )
280
-
281
- args = parser.parse_args()
282
-
283
- if args.command == "search":
284
- cmd_search(args)
285
- elif args.command == "docs":
286
- cmd_docs(args)
287
- else:
288
- parser.print_help()
289
- sys.exit(1)
290
-
291
-
292
- if __name__ == "__main__":
293
- main()
@@ -1,384 +0,0 @@
1
- ---
2
- name: flydocs-estimates
3
- description: "FlyDocs premium: Estimates token usage and API costs for AI development tasks. Apply when refining issues, activating work, or when user asks about costs. v1.0: Guidance-only. Future: Scripts via API relay for premium functionality."
4
- triggers:
5
- - estimate
6
- - cost
7
- - token usage
8
- - API cost
9
- - labor estimate
10
- - sizing
11
- - effort
12
- ---
13
-
14
- # FlyDocs Estimates
15
-
16
- > **Purpose**: Estimate token usage and API costs for AI-driven development tasks before implementation begins.
17
-
18
- ---
19
-
20
- ## Opt-In Feature
21
-
22
- **This skill is disabled by default.** To enable, set in `.flydocs/config.json`:
23
-
24
- ```json
25
- {
26
- "aiLabor": {
27
- "enabled": true
28
- }
29
- }
30
- ```
31
-
32
- ### Before Using This Skill
33
-
34
- ```
35
- □ 1. CHECK config: Read .flydocs/config.json
36
- □ 2. IF aiLabor.enabled !== true:
37
- → DO NOT apply any rules from this skill
38
- → DO NOT warn about missing estimates
39
- → DO NOT add estimate sections to issues
40
- → Proceed with standard workflow
41
- □ 3. IF aiLabor.enabled === true:
42
- → Apply all rules below
43
- ```
44
-
45
- **When disabled**: This skill is completely silent. No warnings, no prompts, no estimate tracking.
46
-
47
- ---
48
-
49
- ## Overview
50
-
51
- This skill enables agents to:
52
- 1. **Analyze specs** to predict token consumption
53
- 2. **Calculate cost ranges** based on provider pricing
54
- 3. **Track actuals** for calibration over time
55
- 4. **Compare** Human vs AI vs Hybrid cost projections
56
-
57
- ---
58
-
59
- ## When to Use (Only if enabled)
60
-
61
- | Trigger | Action |
62
- |---------|--------|
63
- | `/refine [spec]` | Calculate estimate, add to issue |
64
- | `/activate [spec]` | Validate estimate exists; if missing, offer to calculate; warn on high estimates |
65
- | `/implement [spec]` | Show estimate in checklist if present |
66
- | `/close [spec]` | Record actuals, calculate variance |
67
- | Implementation complete | Estimate tokens used, update actuals in issue |
68
- | User asks "how much will this cost?" | Run estimation |
69
-
70
- ### Validation Flow (for /activate and /implement) — Only When Enabled
71
-
72
- ```
73
- 1. Read issue description
74
- 2. Search for "## AI Effort Estimate" section
75
- 3. IF missing:
76
- → OFFER: "Would you like me to calculate an AI Effort Estimate?"
77
- → IF yes: Run estimation, update description
78
- → IF no: Proceed normally
79
- 4. IF present but has placeholders ([X]k):
80
- → OFFER: "Estimate exists but incomplete. Fill it now?"
81
- 5. IF estimate exceeds thresholds:
82
- → tokens > 200k OR cost > $5: Show warning
83
- → cost > $10: Require explicit approval
84
- 6. Continue with activation/implementation
85
- ```
86
-
87
- ---
88
-
89
- ## Estimation Formula
90
-
91
- ```
92
- estimated_tokens = base_tokens × scope_mult × novelty_mult × clarity_mult × codebase_mult
93
-
94
- Where:
95
- base_tokens = task type baseline (see table below)
96
- scope_mult = 0.5 (S) / 1.0 (M) / 2.0 (L) / 4.0 (XL)
97
- novelty_mult = 0.7 (existing pattern) / 1.2 (partial new) / 2.0 (greenfield)
98
- clarity_mult = 0.8 (well-defined) / 1.5 (needs discovery) / 2.5 (exploratory)
99
- codebase_mult = 0.8 (simple) / 1.0 (moderate) / 1.5 (complex)
100
-
101
- Confidence Range:
102
- low_estimate = estimated_tokens × 0.6
103
- high_estimate = estimated_tokens × 2.5
104
- ```
105
-
106
- ### Base Tokens by Task Type
107
-
108
- | Task Type | Base Tokens | Rationale |
109
- |-----------|-------------|-----------|
110
- | **feature** | 40,000 | Full cycle: plan, implement, iterate, review |
111
- | **bug** | 20,000 | Investigation + targeted fix |
112
- | **chore** | 10,000 | Usually straightforward |
113
- | **idea** | 5,000 | Quick exploration only |
114
-
115
- ---
116
-
117
- ## Scoring Multipliers
118
-
119
- ### Scope (from Complexity field)
120
-
121
- | Complexity | Multiplier | Indicators |
122
- |------------|------------|------------|
123
- | **S** | 0.5 | 1-3 acceptance criteria, single file |
124
- | **M** | 1.0 | 4-6 acceptance criteria, 2-5 files |
125
- | **L** | 2.0 | 7-10 acceptance criteria, multiple modules |
126
- | **XL** | 4.0 | 10+ criteria, cross-cutting changes |
127
-
128
- ### Novelty (from Technical Notes)
129
-
130
- | Level | Multiplier | Indicators |
131
- |-------|------------|------------|
132
- | **existing-pattern** | 0.7 | "Follow existing X pattern", references similar code |
133
- | **partial-new** | 1.2 | Mix of new + existing, some exploration needed |
134
- | **greenfield** | 2.0 | New patterns, no precedent in codebase |
135
-
136
- ### Clarity (from Acceptance Criteria quality)
137
-
138
- | Level | Multiplier | Indicators |
139
- |-------|------------|------------|
140
- | **well-defined** | 0.8 | All criteria specific & testable |
141
- | **needs-discovery** | 1.5 | Some vague criteria, needs investigation |
142
- | **exploratory** | 2.5 | Research-heavy, unclear solution |
143
-
144
- ### Codebase Complexity (from `stack.md`)
145
-
146
- | Level | Multiplier | Indicators |
147
- |-------|------------|------------|
148
- | **simple** | 0.8 | Small codebase, clear patterns |
149
- | **moderate** | 1.0 | Standard project, documented patterns |
150
- | **complex** | 1.5 | Large codebase, multiple integrations |
151
-
152
- ---
153
-
154
- ## Cost Calculation
155
-
156
- ```
157
- cost = tokens × (input_rate × input_ratio + output_rate × output_ratio)
158
-
159
- Where:
160
- input_rate = provider cost per 1M input tokens
161
- output_rate = provider cost per 1M output tokens
162
- input_ratio = 0.70 (typical for development)
163
- output_ratio = 0.30 (typical for development)
164
- ```
165
-
166
- See `references/provider-costs.md` for current pricing.
167
-
168
- ---
169
-
170
- ## Issue Template Section
171
-
172
- Add this to Linear issue description during `/refine`:
173
-
174
- ```markdown
175
- ---
176
-
177
- ## AI Effort Estimate
178
-
179
- ### Sizing Factors
180
-
181
- | Factor | Value | Multiplier |
182
- |--------|-------|------------|
183
- | **Task Type** | [feature/bug/chore] | base: [X]k |
184
- | **Scope** | [S/M/L/XL] | ×[0.5/1.0/2.0/4.0] |
185
- | **Novelty** | [existing/partial/greenfield] | ×[0.7/1.2/2.0] |
186
- | **Clarity** | [defined/discovery/exploratory] | ×[0.8/1.5/2.5] |
187
- | **Codebase** | [simple/moderate/complex] | ×[0.8/1.0/1.5] |
188
-
189
- ### Estimate
190
-
191
- **Provider**: [Claude Sonnet 4 / GPT-4o / etc.]
192
- **Calculated Tokens**: ~[X]k
193
- **Confidence**: ±[40-60]%
194
- **Token Range**: [low]k - [high]k
195
- **Cost Range**: $[low] - $[high]
196
-
197
- ### Comparison
198
-
199
- | Approach | Est. Cost | Est. Time | Best For |
200
- |----------|-----------|-----------|----------|
201
- | **Full AI** | $[X] | [X] hrs | Well-defined, pattern-matching |
202
- | **AI-Assisted** | $[X] + [X]hrs human | [X] hrs | Complex decisions |
203
- | **Human-Led** | $[X] (review) + [X]hrs | [X] hrs | Novel architecture |
204
-
205
- ---
206
- ```
207
-
208
- ---
209
-
210
- ## Recording Actuals (on /close)
211
-
212
- Add to issue comment on completion:
213
-
214
- ```markdown
215
- ## AI Effort Actuals
216
-
217
- **Estimated Tokens**: [X]k
218
- **Actual Tokens**: [X]k (from session/API logs if available)
219
- **Variance**: [+/-X]% [under/over]
220
- **Actual Cost**: $[X]
221
-
222
- ### Variance Notes
223
- - [What drove the variance - blockers, scope change, retries, etc.]
224
- - [Lessons for future estimation]
225
-
226
- ### Calibration Data
227
- - Task Type: [feature]
228
- - Final Complexity: [M]
229
- - Novelty Actual: [partial-new]
230
- - Clarity Actual: [well-defined]
231
- ```
232
-
233
- ---
234
-
235
- ## Agent Instructions
236
-
237
- ### During /refine (PM Agent)
238
-
239
- 1. **Read the spec** completely
240
- 2. **Identify task type** from labels (feature, bug, chore, idea)
241
- 3. **Score each factor**:
242
- - Count acceptance criteria → scope
243
- - Check Technical Notes for patterns → novelty
244
- - Assess criteria specificity → clarity
245
- - Reference `stack.md` → codebase complexity
246
- 4. **Calculate estimate** using formula
247
- 5. **Look up provider costs** from `references/provider-costs.md` or `.flydocs/config.json`
248
- 6. **Add estimate section** to issue description (replace placeholders with values)
249
- 7. **If estimate exceeds threshold**, flag for human review:
250
- - \> 200k tokens → Consider breaking down the issue
251
- - \> $5 estimated → Confirm before proceeding
252
- 8. **Include estimate in refine comment**: `AI Estimate: ~Xk tokens ($X-$X)`
253
-
254
- ### During /activate (PM Agent)
255
-
256
- 1. **Search issue description** for "## AI Effort Estimate"
257
- 2. **If missing**:
258
- - WARN: "⚠️ This issue is missing an AI Effort Estimate."
259
- - ASK: "Would you like me to calculate one now before activation?"
260
- - If yes → Calculate and add to description
261
- - If no → Proceed but note: "No baseline for actuals comparison"
262
- 3. **If present but incomplete** (still has `[X]k` placeholders):
263
- - OFFER: "AI Effort Estimate exists but has placeholder values. Complete it now?"
264
- 4. **If present and exceeds thresholds**:
265
- - \> 200k tokens or \> $5 → Show warning, ask for confirmation
266
- - \> $10 → Require explicit "yes proceed" before continuing
267
- 5. **Include in activation comment**: `AI Effort: ~Xk tokens ($X-$X)`
268
-
269
- ### During /implement (Implementation Agent)
270
-
271
- 1. **Search issue description** for "## AI Effort Estimate"
272
- 2. **If missing**:
273
- - WARN: "⚠️ Missing AI Effort Estimate - tracking actuals won't have comparison baseline."
274
- - OFFER: "Calculate estimate before starting implementation?"
275
- - If yes → Calculate estimate, update description
276
- - If no → Proceed with warning
277
- 3. **If present**:
278
- - Show estimate in implementation checklist
279
- - Note: "Tracking against estimate of ~Xk tokens"
280
- 4. **During implementation**:
281
- - Keep rough mental model of token usage
282
- - Note if work is going significantly over estimate (scope discovery, retries)
283
-
284
- ### On Implementation Complete (Implementation Agent)
285
-
286
- 1. **Estimate actual tokens used**:
287
- - Rough method: conversation turns × ~2k tokens/turn
288
- - Or estimate based on files changed, complexity of work
289
- 2. **Update AI Effort Estimate section** in issue description:
290
- - Fill "Actual Tokens" field
291
- - Calculate variance percentage
292
- - Add notes on variance drivers
293
- 3. **Include in completion comment**: `AI Effort: ~Xk actual (estimated Xk, +/-X% variance)`
294
-
295
- ### During /close (PM Agent)
296
-
297
- 1. **Verify actuals were recorded** (from implementation completion)
298
- 2. **If actuals missing**: Estimate based on issue activity/comments
299
- 3. **Calculate final variance** from estimate
300
- 4. **Add final actuals to issue** if not already present
301
- 5. **Log patterns for calibration**:
302
- - Which factor assessments were off?
303
- - What should be adjusted for similar future work?
304
- 6. **Include in close comment**: `Final AI Effort: ~Xk tokens (+/-X% from estimate)`
305
-
306
- ---
307
-
308
- ## Configuration
309
-
310
- In `.flydocs/config.json`:
311
-
312
- ```json
313
- {
314
- "aiLabor": {
315
- "enabled": false,
316
- "defaultProvider": "claude-sonnet-4",
317
- "thresholds": {
318
- "warnTokens": 200000,
319
- "warnCost": 5.00,
320
- "requireApproval": 10.00
321
- },
322
- "tracking": {
323
- "recordActuals": true,
324
- "calibrationEnabled": true
325
- }
326
- }
327
- }
328
- ```
329
-
330
- **To enable**, change `"enabled": false` to `"enabled": true`.
331
-
332
- When enabled, the skill will:
333
- - Add AI Effort Estimate sections during `/refine`
334
- - Offer to calculate estimates during `/activate` and `/implement`
335
- - Track actuals on completion
336
- - Warn on high-cost estimates based on thresholds
337
-
338
- ---
339
-
340
- ## Example Calculation
341
-
342
- **Spec**: "Add user profile photo upload"
343
-
344
- | Factor | Assessment | Value |
345
- |--------|------------|-------|
346
- | Type | Feature | 40k base |
347
- | Scope | M (5 criteria, ~4 files) | ×1.0 |
348
- | Novelty | Existing pattern (similar to doc upload) | ×0.7 |
349
- | Clarity | Well-defined (clear criteria) | ×0.8 |
350
- | Codebase | Moderate | ×1.0 |
351
-
352
- **Calculation**:
353
- ```
354
- 40,000 × 1.0 × 0.7 × 0.8 × 1.0 = 22,400 tokens
355
-
356
- Range: 13,440 - 56,000 tokens (±60% confidence)
357
-
358
- Cost (Claude Sonnet 4 @ $3/$15 per 1M):
359
- Low: 13.4k × (0.7×$3 + 0.3×$15)/1M = $0.09
360
- High: 56k × (0.7×$3 + 0.3×$15)/1M = $0.37
361
- ```
362
-
363
- **Result**: ~22k tokens, $0.09 - $0.37 estimated cost
364
-
365
- ---
366
-
367
- ## Related Skills
368
-
369
- - `flydocs-workflow` - For workflow lifecycle and issue operations
370
- - `spec-templates` - Template structure reference
371
-
372
- ---
373
-
374
- ## Calibration Over Time
375
-
376
- Track estimates vs actuals to improve accuracy:
377
-
378
- 1. **Log all estimates and actuals** in issue comments
379
- 2. **Review monthly** for patterns:
380
- - Which task types are consistently over/under?
381
- - Which factors need adjustment?
382
- 3. **Adjust multipliers** based on your codebase patterns
383
- 4. **Document adjustments** in `.flydocs/knowledge/notes/`
384
-