@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.
- package/dist/cli.js +2053 -469
- package/package.json +1 -1
- package/template/.claude/CLAUDE.md +43 -48
- package/template/.claude/agents/implementation-agent.md +1 -1
- package/template/.claude/agents/pm-agent.md +1 -1
- package/template/.claude/commands/activate.md +1 -1
- package/template/.claude/commands/attach.md +1 -1
- package/template/.claude/commands/block.md +2 -2
- package/template/.claude/commands/capture.md +1 -1
- package/template/.claude/commands/close.md +1 -1
- package/template/.claude/commands/flydocs-setup.md +359 -72
- package/template/.claude/commands/flydocs-upgrade.md +26 -27
- package/template/.claude/commands/implement.md +1 -1
- package/template/.claude/commands/knowledge.md +61 -0
- package/template/.claude/commands/new-project.md +1 -1
- package/template/.claude/commands/onboard.md +275 -0
- package/template/.claude/commands/project-update.md +1 -1
- package/template/.claude/commands/refine.md +1 -1
- package/template/.claude/commands/review.md +1 -1
- package/template/.claude/commands/start-session.md +1 -1
- package/template/.claude/commands/status.md +1 -1
- package/template/.claude/commands/validate.md +1 -1
- package/template/.claude/commands/wrap-session.md +1 -1
- package/template/.claude/hooks/auto-approve.py +212 -0
- package/template/.claude/hooks/post-pr-check.py +108 -0
- package/template/.claude/hooks/post-transition-check.py +281 -0
- package/template/.claude/hooks/prompt-submit.py +554 -0
- package/template/.claude/hooks/session-start.py +262 -0
- package/template/.claude/hooks/stop-gate.py +162 -0
- package/template/.claude/settings.json +41 -4
- package/template/.claude/skills/README.md +23 -25
- package/template/.claude/skills/flydocs-workflow/SKILL.md +134 -42
- package/template/.claude/skills/flydocs-workflow/cursor-rule.mdc +9 -8
- package/template/.claude/skills/flydocs-workflow/reference/comment-templates.md +1 -0
- package/template/.claude/skills/flydocs-workflow/reference/golden-rules.md +28 -17
- package/template/.claude/skills/flydocs-workflow/reference/graph-schema.md +116 -0
- package/template/.claude/skills/flydocs-workflow/reference/pr-workflow.md +120 -0
- package/template/.claude/skills/flydocs-workflow/reference/priority-estimates.md +37 -15
- package/template/.claude/skills/flydocs-workflow/reference/service-descriptor-schema.md +260 -0
- package/template/.claude/skills/flydocs-workflow/reference/status-workflow.md +26 -26
- package/template/.claude/skills/flydocs-workflow/scripts/_local/__init__.py +0 -0
- package/template/.claude/skills/{flydocs-local/scripts/flydocs_api.py → flydocs-workflow/scripts/_local/file_store.py} +137 -47
- package/template/.claude/skills/flydocs-workflow/scripts/flydocs_api.py +724 -0
- package/template/{.flydocs → .claude/skills/flydocs-workflow}/scripts/generate_manifest.py +4 -4
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_build.py +132 -1
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_query.py +18 -5
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_session.py +1 -10
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_update.py +4 -4
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_utils.py +2 -1
- package/template/.claude/skills/flydocs-workflow/scripts/issues.py +738 -0
- package/template/.claude/skills/flydocs-workflow/scripts/projects.py +144 -0
- package/template/.claude/skills/flydocs-workflow/scripts/pull_services.py +128 -0
- package/template/.claude/skills/flydocs-workflow/scripts/push_service.py +132 -0
- package/template/.claude/skills/flydocs-workflow/scripts/session.py +54 -0
- package/template/.claude/skills/flydocs-workflow/scripts/test_enforcement.py +225 -0
- package/template/.claude/skills/flydocs-workflow/scripts/workspace.py +902 -0
- package/template/.claude/skills/flydocs-workflow/session.md +87 -29
- package/template/.claude/skills/flydocs-workflow/stages/activate.md +18 -7
- package/template/.claude/skills/flydocs-workflow/stages/capture.md +10 -5
- package/template/.claude/skills/flydocs-workflow/stages/close.md +4 -3
- package/template/.claude/skills/flydocs-workflow/stages/implement.md +33 -9
- package/template/.claude/skills/flydocs-workflow/stages/refine.md +22 -6
- package/template/.claude/skills/flydocs-workflow/stages/review.md +16 -4
- package/template/.claude/skills/flydocs-workflow/stages/validate.md +3 -1
- package/template/.claude/skills/flydocs-workflow/templates/pr/default.md +33 -0
- package/template/.cursor/agents/implementation-agent.md +1 -1
- package/template/.cursor/agents/pm-agent.md +2 -2
- package/template/.cursor/hooks.json +10 -3
- package/template/.env.example +6 -6
- package/template/.flydocs/config.json +5 -18
- package/template/.flydocs/templates/README.md +13 -14
- package/template/.flydocs/templates/bug.md +17 -153
- package/template/.flydocs/templates/chore.md +10 -98
- package/template/.flydocs/templates/feature.md +12 -158
- package/template/.flydocs/templates/idea.md +11 -111
- package/template/.flydocs/templates/quick-capture.md +4 -8
- package/template/.flydocs/version +1 -1
- package/template/AGENTS.md +44 -32
- package/template/CHANGELOG.md +37 -0
- package/template/flydocs/README.md +1 -3
- package/template/flydocs/context/project.md +6 -3
- package/template/flydocs/design-system/README.md +3 -3
- package/template/flydocs/knowledge/INDEX.md +38 -53
- package/template/flydocs/knowledge/README.md +60 -9
- package/template/flydocs/knowledge/templates/decision.md +47 -0
- package/template/flydocs/knowledge/templates/feature.md +35 -0
- package/template/flydocs/knowledge/templates/note.md +25 -0
- package/template/manifest.json +24 -20
- package/template/.claude/skills/flydocs-cloud/SKILL.md +0 -113
- package/template/.claude/skills/flydocs-cloud/cursor-rule.mdc +0 -50
- package/template/.claude/skills/flydocs-cloud/scripts/assign.py +0 -22
- package/template/.claude/skills/flydocs-cloud/scripts/assign_cycle.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/assign_milestone.py +0 -22
- package/template/.claude/skills/flydocs-cloud/scripts/comment.py +0 -29
- package/template/.claude/skills/flydocs-cloud/scripts/create_issue.py +0 -66
- package/template/.claude/skills/flydocs-cloud/scripts/create_milestone.py +0 -35
- package/template/.claude/skills/flydocs-cloud/scripts/create_project.py +0 -33
- package/template/.claude/skills/flydocs-cloud/scripts/create_team.py +0 -39
- package/template/.claude/skills/flydocs-cloud/scripts/estimate.py +0 -29
- package/template/.claude/skills/flydocs-cloud/scripts/flydocs_api.py +0 -210
- package/template/.claude/skills/flydocs-cloud/scripts/get_issue.py +0 -24
- package/template/.claude/skills/flydocs-cloud/scripts/link.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/list_cycles.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/list_issues.py +0 -44
- package/template/.claude/skills/flydocs-cloud/scripts/list_labels.py +0 -19
- package/template/.claude/skills/flydocs-cloud/scripts/list_milestones.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/list_projects.py +0 -31
- package/template/.claude/skills/flydocs-cloud/scripts/list_providers.py +0 -19
- package/template/.claude/skills/flydocs-cloud/scripts/list_teams.py +0 -19
- package/template/.claude/skills/flydocs-cloud/scripts/priority.py +0 -29
- package/template/.claude/skills/flydocs-cloud/scripts/project_update.py +0 -45
- package/template/.claude/skills/flydocs-cloud/scripts/set_labels.py +0 -68
- package/template/.claude/skills/flydocs-cloud/scripts/set_provider.py +0 -46
- package/template/.claude/skills/flydocs-cloud/scripts/set_team.py +0 -41
- package/template/.claude/skills/flydocs-cloud/scripts/transition.py +0 -26
- package/template/.claude/skills/flydocs-cloud/scripts/update_description.py +0 -36
- package/template/.claude/skills/flydocs-cloud/scripts/update_issue.py +0 -82
- package/template/.claude/skills/flydocs-context-graph/SKILL.md +0 -87
- package/template/.claude/skills/flydocs-context-graph/schema.md +0 -78
- package/template/.claude/skills/flydocs-context-graph/scripts/graph_context.py +0 -338
- package/template/.claude/skills/flydocs-context7/SKILL.md +0 -105
- package/template/.claude/skills/flydocs-context7/cursor-rule.mdc +0 -49
- package/template/.claude/skills/flydocs-context7/scripts/context7.py +0 -293
- package/template/.claude/skills/flydocs-estimates/SKILL.md +0 -384
- package/template/.claude/skills/flydocs-figma/SKILL.md +0 -377
- package/template/.claude/skills/flydocs-figma/references/PROMPTING.md +0 -108
- package/template/.claude/skills/flydocs-figma/references/TROUBLESHOOTING.md +0 -112
- package/template/.claude/skills/flydocs-local/SKILL.md +0 -103
- package/template/.claude/skills/flydocs-local/cursor-rule.mdc +0 -43
- package/template/.claude/skills/flydocs-local/scripts/assign.py +0 -20
- package/template/.claude/skills/flydocs-local/scripts/comment.py +0 -27
- package/template/.claude/skills/flydocs-local/scripts/create_issue.py +0 -44
- package/template/.claude/skills/flydocs-local/scripts/estimate.py +0 -37
- package/template/.claude/skills/flydocs-local/scripts/get_issue.py +0 -20
- package/template/.claude/skills/flydocs-local/scripts/link.py +0 -41
- package/template/.claude/skills/flydocs-local/scripts/list_issues.py +0 -34
- package/template/.claude/skills/flydocs-local/scripts/priority.py +0 -37
- package/template/.claude/skills/flydocs-local/scripts/project_update.py +0 -67
- package/template/.claude/skills/flydocs-local/scripts/status_summary.py +0 -16
- package/template/.claude/skills/flydocs-local/scripts/transition.py +0 -24
- package/template/.claude/skills/flydocs-local/scripts/update_description.py +0 -35
- package/template/.claude/skills/flydocs-local/scripts/update_issue.py +0 -84
- package/template/.flydocs/hooks/auto-approve.py +0 -71
- package/template/.flydocs/hooks/prompt-submit.py +0 -277
- package/template/.flydocs/scripts/skill_manager.py +0 -541
- /package/template/{.flydocs → .claude}/hooks/post-edit.py +0 -0
- /package/template/.claude/skills/{flydocs-estimates/references → flydocs-workflow/reference}/provider-costs.md +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{bug.md → issues/bug.md} +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{chore.md → issues/chore.md} +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{feature.md → issues/feature.md} +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{idea.md → issues/idea.md} +0 -0
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Assemble compressed graph context for the prime hook.
|
|
3
|
-
|
|
4
|
-
Given an active issue and/or git branch, traverses the graph and returns
|
|
5
|
-
a compact context block suitable for injection into the prompt-submit hook.
|
|
6
|
-
Stays within a ~200-400 token budget.
|
|
7
|
-
|
|
8
|
-
Usage:
|
|
9
|
-
python3 .claude/skills/flydocs-context-graph/scripts/graph_context.py \
|
|
10
|
-
[--issue FLY-56] [--branch feature/context-graph] [--root PATH]
|
|
11
|
-
|
|
12
|
-
Output: Plain text context block (not JSON) for direct injection into hook output.
|
|
13
|
-
Returns empty string if graph doesn't exist or no relevant context found.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import argparse
|
|
17
|
-
import sys
|
|
18
|
-
from datetime import date, timedelta
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
|
|
21
|
-
sys.path.insert(0, str(Path(__file__).parent))
|
|
22
|
-
from graph_utils import find_project_root, load_graph
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# Maximum lines in the context block to stay within token budget
|
|
26
|
-
MAX_CONTEXT_LINES = 12
|
|
27
|
-
|
|
28
|
-
# Session staleness policy
|
|
29
|
-
SESSION_RETENTION_DAYS = 30
|
|
30
|
-
SESSION_FRESH_DAYS = 7 # Full weight within this window
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def find_issue_node(graph, issue_ref):
|
|
34
|
-
"""Find a graph node matching an issue reference (e.g., FLY-56)."""
|
|
35
|
-
if not issue_ref:
|
|
36
|
-
return None
|
|
37
|
-
|
|
38
|
-
# Try exact match first
|
|
39
|
-
node_id = f"issue:{issue_ref}"
|
|
40
|
-
if node_id in graph.get("nodes", {}):
|
|
41
|
-
return node_id
|
|
42
|
-
|
|
43
|
-
# Try case-insensitive search
|
|
44
|
-
for nid in graph.get("nodes", {}):
|
|
45
|
-
if nid.lower() == node_id.lower():
|
|
46
|
-
return nid
|
|
47
|
-
|
|
48
|
-
return None
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def find_branch_nodes(graph, branch):
|
|
52
|
-
"""Infer relevant nodes from a git branch name.
|
|
53
|
-
|
|
54
|
-
Branch names often contain issue refs (feature/FLY-56-context-graph)
|
|
55
|
-
or skill/module names (feature/context-graph).
|
|
56
|
-
"""
|
|
57
|
-
if not branch:
|
|
58
|
-
return []
|
|
59
|
-
|
|
60
|
-
nodes = graph.get("nodes", {})
|
|
61
|
-
matches = []
|
|
62
|
-
|
|
63
|
-
# Extract issue reference from branch (e.g., FLY-56)
|
|
64
|
-
import re
|
|
65
|
-
issue_match = re.search(r"([A-Z]+-\d+)", branch, re.IGNORECASE)
|
|
66
|
-
if issue_match:
|
|
67
|
-
issue_id = find_issue_node(graph, issue_match.group(1))
|
|
68
|
-
if issue_id:
|
|
69
|
-
matches.append(issue_id)
|
|
70
|
-
|
|
71
|
-
# Match skill or module names in branch
|
|
72
|
-
branch_lower = branch.lower().replace("/", "-").replace("_", "-")
|
|
73
|
-
for node_id, node in nodes.items():
|
|
74
|
-
if node["type"] in ("skill", "module"):
|
|
75
|
-
name = node_id.split(":", 1)[-1].lower()
|
|
76
|
-
if name in branch_lower and len(name) > 3:
|
|
77
|
-
matches.append(node_id)
|
|
78
|
-
|
|
79
|
-
return matches
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def find_recent_sessions(graph, issue_nodes, today=None):
|
|
83
|
-
"""Find session nodes relevant to the current work.
|
|
84
|
-
|
|
85
|
-
Returns sessions connected to active issues, or recent sessions if no
|
|
86
|
-
issue match. Applies staleness weighting — older sessions get lower weight.
|
|
87
|
-
"""
|
|
88
|
-
if today is None:
|
|
89
|
-
today = date.today()
|
|
90
|
-
|
|
91
|
-
nodes = graph.get("nodes", {})
|
|
92
|
-
edges = graph.get("edges", [])
|
|
93
|
-
cutoff = today - timedelta(days=SESSION_RETENTION_DAYS)
|
|
94
|
-
|
|
95
|
-
# Find all session nodes within retention window
|
|
96
|
-
sessions = []
|
|
97
|
-
for node_id, node in nodes.items():
|
|
98
|
-
if node.get("type") != "session":
|
|
99
|
-
continue
|
|
100
|
-
|
|
101
|
-
session_date_str = node.get("date", "")
|
|
102
|
-
if not session_date_str:
|
|
103
|
-
continue
|
|
104
|
-
|
|
105
|
-
try:
|
|
106
|
-
session_date = date.fromisoformat(session_date_str)
|
|
107
|
-
except ValueError:
|
|
108
|
-
continue
|
|
109
|
-
|
|
110
|
-
if session_date < cutoff:
|
|
111
|
-
continue
|
|
112
|
-
|
|
113
|
-
# Calculate staleness weight
|
|
114
|
-
age_days = (today - session_date).days
|
|
115
|
-
if age_days <= SESSION_FRESH_DAYS:
|
|
116
|
-
weight = 1.0
|
|
117
|
-
else:
|
|
118
|
-
# Linear decay from 1.0 to 0.1 over the retention period
|
|
119
|
-
weight = max(0.1, 1.0 - (age_days / SESSION_RETENTION_DAYS) * 0.9)
|
|
120
|
-
|
|
121
|
-
sessions.append((node_id, node, session_date, weight))
|
|
122
|
-
|
|
123
|
-
if not sessions:
|
|
124
|
-
return []
|
|
125
|
-
|
|
126
|
-
# Check which sessions are connected to active issues
|
|
127
|
-
issue_set = set(issue_nodes)
|
|
128
|
-
connected = []
|
|
129
|
-
unconnected = []
|
|
130
|
-
|
|
131
|
-
for session_id, node, session_date, weight in sessions:
|
|
132
|
-
# Check if this session has WORKED_ON edges to any active issue
|
|
133
|
-
has_issue_link = False
|
|
134
|
-
for edge in edges:
|
|
135
|
-
if (edge["from"] == session_id
|
|
136
|
-
and edge["rel"] == "WORKED_ON"
|
|
137
|
-
and edge["to"] in issue_set):
|
|
138
|
-
has_issue_link = True
|
|
139
|
-
break
|
|
140
|
-
|
|
141
|
-
if has_issue_link:
|
|
142
|
-
connected.append((session_id, node, weight))
|
|
143
|
-
else:
|
|
144
|
-
unconnected.append((session_id, node, weight))
|
|
145
|
-
|
|
146
|
-
# Prefer connected sessions, fall back to most recent
|
|
147
|
-
if connected:
|
|
148
|
-
connected.sort(key=lambda x: x[2], reverse=True)
|
|
149
|
-
return connected[:3]
|
|
150
|
-
|
|
151
|
-
# No connected sessions — return most recent ones
|
|
152
|
-
unconnected.sort(key=lambda x: x[0], reverse=True) # Sort by ID (date-based)
|
|
153
|
-
return unconnected[:2]
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
def get_related_context(graph, start_nodes, max_depth=2):
|
|
157
|
-
"""BFS traverse from start nodes and collect related context.
|
|
158
|
-
|
|
159
|
-
Returns a deduplicated list of (node_id, node, rel, depth) tuples.
|
|
160
|
-
"""
|
|
161
|
-
nodes = graph.get("nodes", {})
|
|
162
|
-
edges = graph.get("edges", [])
|
|
163
|
-
|
|
164
|
-
# Build adjacency (both directions for full context)
|
|
165
|
-
forward = {}
|
|
166
|
-
reverse = {}
|
|
167
|
-
for edge in edges:
|
|
168
|
-
src, dst = edge["from"], edge["to"]
|
|
169
|
-
rel = edge["rel"]
|
|
170
|
-
weight = edge.get("weight", 1.0)
|
|
171
|
-
|
|
172
|
-
if src not in forward:
|
|
173
|
-
forward[src] = []
|
|
174
|
-
forward[src].append((dst, rel, weight))
|
|
175
|
-
|
|
176
|
-
if dst not in reverse:
|
|
177
|
-
reverse[dst] = []
|
|
178
|
-
reverse[dst].append((src, rel, weight))
|
|
179
|
-
|
|
180
|
-
visited = set(start_nodes)
|
|
181
|
-
results = []
|
|
182
|
-
|
|
183
|
-
# BFS from each start node
|
|
184
|
-
from collections import deque
|
|
185
|
-
queue = deque()
|
|
186
|
-
|
|
187
|
-
for start in start_nodes:
|
|
188
|
-
# Forward edges
|
|
189
|
-
for neighbor, rel, weight in forward.get(start, []):
|
|
190
|
-
if neighbor not in visited:
|
|
191
|
-
queue.append((neighbor, 1, rel, "forward"))
|
|
192
|
-
visited.add(neighbor)
|
|
193
|
-
# Reverse edges
|
|
194
|
-
for neighbor, rel, weight in reverse.get(start, []):
|
|
195
|
-
if neighbor not in visited:
|
|
196
|
-
queue.append((neighbor, 1, rel, "reverse"))
|
|
197
|
-
visited.add(neighbor)
|
|
198
|
-
|
|
199
|
-
while queue:
|
|
200
|
-
node_id, depth, rel, direction = queue.popleft()
|
|
201
|
-
node = nodes.get(node_id, {})
|
|
202
|
-
results.append((node_id, node, rel, depth))
|
|
203
|
-
|
|
204
|
-
if depth < max_depth:
|
|
205
|
-
adj = forward if direction == "forward" else reverse
|
|
206
|
-
for neighbor, next_rel, weight in adj.get(node_id, []):
|
|
207
|
-
if neighbor not in visited:
|
|
208
|
-
queue.append((neighbor, depth + 1, next_rel, direction))
|
|
209
|
-
visited.add(neighbor)
|
|
210
|
-
|
|
211
|
-
return results
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def format_context_block(graph, start_nodes, related):
|
|
215
|
-
"""Format a compressed context block within the token budget."""
|
|
216
|
-
nodes = graph.get("nodes", {})
|
|
217
|
-
lines = []
|
|
218
|
-
|
|
219
|
-
# Temporal anchor
|
|
220
|
-
lines.append(f"Today is {date.today().strftime('%B %d, %Y')}")
|
|
221
|
-
|
|
222
|
-
if not related:
|
|
223
|
-
return "\n".join(lines)
|
|
224
|
-
|
|
225
|
-
# Group by type, prioritize decisions and skills
|
|
226
|
-
decisions = []
|
|
227
|
-
skills = []
|
|
228
|
-
sessions = []
|
|
229
|
-
other = []
|
|
230
|
-
|
|
231
|
-
for node_id, node, rel, depth in related:
|
|
232
|
-
node_type = node.get("type", "unknown")
|
|
233
|
-
if node_type == "decision":
|
|
234
|
-
decisions.append((node_id, node, rel))
|
|
235
|
-
elif node_type == "skill":
|
|
236
|
-
skills.append((node_id, node, rel))
|
|
237
|
-
elif node_type == "session":
|
|
238
|
-
sessions.append((node_id, node, rel))
|
|
239
|
-
else:
|
|
240
|
-
other.append((node_id, node, rel))
|
|
241
|
-
|
|
242
|
-
# Decisions — most valuable context
|
|
243
|
-
if decisions:
|
|
244
|
-
lines.append("Related decisions:")
|
|
245
|
-
for node_id, node, rel in decisions[:4]:
|
|
246
|
-
num = node_id.split(":")[-1]
|
|
247
|
-
label = node.get("label", node_id)
|
|
248
|
-
lines.append(f" ADR-{num}: {label} ({rel})")
|
|
249
|
-
|
|
250
|
-
# Skills
|
|
251
|
-
if skills:
|
|
252
|
-
skill_names = [n.get("label", nid) for nid, n, r in skills[:3]]
|
|
253
|
-
lines.append(f"Related skills: {', '.join(skill_names)}")
|
|
254
|
-
|
|
255
|
-
# Sessions — prior work context
|
|
256
|
-
if sessions:
|
|
257
|
-
for node_id, node, rel in sessions[:2]:
|
|
258
|
-
label = node.get("label", "")
|
|
259
|
-
session_date = node.get("date", "")
|
|
260
|
-
if label:
|
|
261
|
-
lines.append(f"Prior session ({session_date}): {label}")
|
|
262
|
-
|
|
263
|
-
# Truncate to budget
|
|
264
|
-
if len(lines) > MAX_CONTEXT_LINES:
|
|
265
|
-
lines = lines[:MAX_CONTEXT_LINES]
|
|
266
|
-
|
|
267
|
-
return "\n".join(lines)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
def main():
|
|
271
|
-
parser = argparse.ArgumentParser(
|
|
272
|
-
description="Assemble graph context for prime hook"
|
|
273
|
-
)
|
|
274
|
-
parser.add_argument(
|
|
275
|
-
"--issue", type=str, default=None,
|
|
276
|
-
help="Active issue reference (e.g., FLY-56)"
|
|
277
|
-
)
|
|
278
|
-
parser.add_argument(
|
|
279
|
-
"--branch", type=str, default=None,
|
|
280
|
-
help="Current git branch name"
|
|
281
|
-
)
|
|
282
|
-
parser.add_argument(
|
|
283
|
-
"--root", type=str, default=None,
|
|
284
|
-
help="Project root (default: auto-detect)"
|
|
285
|
-
)
|
|
286
|
-
args = parser.parse_args()
|
|
287
|
-
|
|
288
|
-
root = Path(args.root) if args.root else find_project_root()
|
|
289
|
-
if not root:
|
|
290
|
-
# Graceful fallback — no output
|
|
291
|
-
sys.exit(0)
|
|
292
|
-
|
|
293
|
-
# Load graph — graceful fallback if missing
|
|
294
|
-
graph = load_graph(root)
|
|
295
|
-
if not graph.get("nodes"):
|
|
296
|
-
# Empty or missing graph — just output temporal anchor
|
|
297
|
-
print(f"Today is {date.today().strftime('%B %d, %Y')}")
|
|
298
|
-
sys.exit(0)
|
|
299
|
-
|
|
300
|
-
# Find starting nodes
|
|
301
|
-
start_nodes = []
|
|
302
|
-
|
|
303
|
-
issue_node = find_issue_node(graph, args.issue)
|
|
304
|
-
if issue_node:
|
|
305
|
-
start_nodes.append(issue_node)
|
|
306
|
-
|
|
307
|
-
branch_nodes = find_branch_nodes(graph, args.branch)
|
|
308
|
-
start_nodes.extend(n for n in branch_nodes if n not in start_nodes)
|
|
309
|
-
|
|
310
|
-
# If no specific entry points, just output temporal anchor
|
|
311
|
-
if not start_nodes:
|
|
312
|
-
print(f"Today is {date.today().strftime('%B %d, %Y')}")
|
|
313
|
-
sys.exit(0)
|
|
314
|
-
|
|
315
|
-
# Traverse and assemble context
|
|
316
|
-
related = get_related_context(graph, start_nodes, max_depth=2)
|
|
317
|
-
|
|
318
|
-
# Find recent sessions (connected to active issues or just recent)
|
|
319
|
-
issue_start_nodes = [n for n in start_nodes if n.startswith("issue:")]
|
|
320
|
-
recent_sessions = find_recent_sessions(graph, issue_start_nodes)
|
|
321
|
-
|
|
322
|
-
# Add sessions to related if not already present
|
|
323
|
-
seen = {r[0] for r in related}
|
|
324
|
-
for session_id, node, weight in recent_sessions:
|
|
325
|
-
if session_id not in seen:
|
|
326
|
-
related.append((session_id, node, "WORKED_ON", 1))
|
|
327
|
-
seen.add(session_id)
|
|
328
|
-
|
|
329
|
-
context = format_context_block(graph, start_nodes, related)
|
|
330
|
-
|
|
331
|
-
if context:
|
|
332
|
-
print(context)
|
|
333
|
-
|
|
334
|
-
sys.exit(0)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if __name__ == "__main__":
|
|
338
|
-
main()
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: flydocs-context7
|
|
3
|
-
description: |
|
|
4
|
-
Up-to-date library documentation via Context7 API. Use proactively when
|
|
5
|
-
working with external libraries, frameworks, or packages. Replaces MCP
|
|
6
|
-
with direct API scripts — no server, no runtime dependency.
|
|
7
|
-
triggers:
|
|
8
|
-
- context7
|
|
9
|
-
- library docs
|
|
10
|
-
- documentation lookup
|
|
11
|
-
- framework docs
|
|
12
|
-
- package docs
|
|
13
|
-
- API reference
|
|
14
|
-
- how to use
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
# Context7 Documentation Lookup
|
|
18
|
-
|
|
19
|
-
IMPORTANT: Prefer skill-led reasoning over pre-training reasoning for
|
|
20
|
-
library usage. Search for up-to-date docs before writing code based on
|
|
21
|
-
training data alone.
|
|
22
|
-
|
|
23
|
-
## Key Rules
|
|
24
|
-
|
|
25
|
-
1. **Proactive invocation** -- When working with ANY external library or
|
|
26
|
-
framework, search for docs first before writing code based on training data.
|
|
27
|
-
2. **Search then fetch** -- Always resolve the library ID via `search` before
|
|
28
|
-
fetching docs with `docs`.
|
|
29
|
-
3. **Session cache awareness** -- Do not re-fetch docs for the same
|
|
30
|
-
library+query within a single session.
|
|
31
|
-
4. **Graceful degradation** -- If rate-limited (429) or offline, note the
|
|
32
|
-
limitation and proceed with training knowledge.
|
|
33
|
-
5. **Stdlib-only Python** -- No external dependencies in the script.
|
|
34
|
-
6. **Token budget** -- Default 5,000 tokens per fetch to avoid context bloat.
|
|
35
|
-
|
|
36
|
-
## Script Catalog
|
|
37
|
-
|
|
38
|
-
All scripts: `python3 .claude/skills/flydocs-context7/scripts/<script>`
|
|
39
|
-
|
|
40
|
-
| Script | Usage | Output |
|
|
41
|
-
| ------------- | --------------------------- | ------------------------------------------------ |
|
|
42
|
-
| `context7.py` | `search <library> [query]` | JSON: library matches with id, name, description |
|
|
43
|
-
| `context7.py` | `docs <library_id> <query>` | Text: relevant documentation snippets |
|
|
44
|
-
|
|
45
|
-
Options: `--type txt|json`, `--tokens N` (default 5000)
|
|
46
|
-
|
|
47
|
-
## When to Use
|
|
48
|
-
|
|
49
|
-
- Before implementing code that uses an external library
|
|
50
|
-
- When the user asks about library APIs, patterns, or best practices
|
|
51
|
-
- When encountering unfamiliar library methods or configuration
|
|
52
|
-
- When upgrading dependencies and needing current API docs
|
|
53
|
-
- When debugging library-specific issues
|
|
54
|
-
|
|
55
|
-
## When NOT to Use
|
|
56
|
-
|
|
57
|
-
- For project-internal code (use knowledge base and context graph instead)
|
|
58
|
-
- For general programming concepts (training knowledge is sufficient)
|
|
59
|
-
- When already fetched docs for the same library in this session
|
|
60
|
-
|
|
61
|
-
## API Key (Optional)
|
|
62
|
-
|
|
63
|
-
- Works without a key (anonymous, ~1,000 calls/month)
|
|
64
|
-
- For higher limits, add `CONTEXT7_API_KEY=ctx7sk-xxx` to `.env`
|
|
65
|
-
- Free key available at context7.com/dashboard
|
|
66
|
-
|
|
67
|
-
## Example Usage
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# Find the React library
|
|
71
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py search "react" "hooks"
|
|
72
|
-
|
|
73
|
-
# Fetch docs for React hooks
|
|
74
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/facebook/react" "useState useEffect hooks"
|
|
75
|
-
|
|
76
|
-
# Get Next.js App Router docs
|
|
77
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py search "next.js"
|
|
78
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/vercel/next.js" "app router middleware"
|
|
79
|
-
|
|
80
|
-
# Fetch with custom token budget
|
|
81
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/expressjs/express" "routing middleware" --tokens 8000
|
|
82
|
-
|
|
83
|
-
# Get output as JSON
|
|
84
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py search "prisma" --type json
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## Typical Workflow
|
|
88
|
-
|
|
89
|
-
1. **Identify the library** you need docs for (from import statements,
|
|
90
|
-
`package.json`, or the task at hand).
|
|
91
|
-
2. **Search** to resolve the library ID:
|
|
92
|
-
```bash
|
|
93
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py search "react-hook-form"
|
|
94
|
-
```
|
|
95
|
-
3. **Fetch docs** for the specific topic:
|
|
96
|
-
```bash
|
|
97
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/react-hook-form/react-hook-form" "useForm validation"
|
|
98
|
-
```
|
|
99
|
-
4. **Apply** the retrieved documentation to your implementation.
|
|
100
|
-
5. **Do not re-fetch** for the same library+query later in the session.
|
|
101
|
-
|
|
102
|
-
## Related Skills
|
|
103
|
-
|
|
104
|
-
- `flydocs-context-graph` -- Project-internal knowledge navigation
|
|
105
|
-
- `flydocs-workflow` -- Development lifecycle and issue operations
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Context7 — look up library and framework documentation before writing code
|
|
3
|
-
alwaysApply: true
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
<!-- Condensed from SKILL.md — update both when changing patterns -->
|
|
7
|
-
|
|
8
|
-
# FlyDocs Context7
|
|
9
|
-
|
|
10
|
-
Proactively look up library documentation via Context7 scripts before writing
|
|
11
|
-
code that uses external packages. Do not rely on training data for API details.
|
|
12
|
-
|
|
13
|
-
## When to Use
|
|
14
|
-
|
|
15
|
-
- Installing or importing a library you haven't used in this session
|
|
16
|
-
- Unsure about API signatures, configuration options, or return types
|
|
17
|
-
- Framework-specific patterns (routing, data fetching, middleware, hooks)
|
|
18
|
-
- Resolving version-specific behavior or breaking changes
|
|
19
|
-
|
|
20
|
-
## Scripts
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# Step 1: Search for the library
|
|
24
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py search "<library>" "[query]"
|
|
25
|
-
|
|
26
|
-
# Step 2: Fetch docs using the library ID from search results
|
|
27
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py docs "<library_id>" "<query>"
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Examples
|
|
31
|
-
|
|
32
|
-
React hooks:
|
|
33
|
-
```bash
|
|
34
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py search "react" "hooks"
|
|
35
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/facebook/react" "hooks useState"
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Next.js App Router:
|
|
39
|
-
```bash
|
|
40
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py search "next.js"
|
|
41
|
-
python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/vercel/next.js" "app router middleware"
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Key Rules
|
|
45
|
-
|
|
46
|
-
- Always resolve the library ID first via `search` — do not guess the ID format
|
|
47
|
-
- Prefer Context7 docs over training data for API specifics
|
|
48
|
-
- If Context7 has no results or is rate-limited, fall back to web search
|
|
49
|
-
- Cache within a session — no need to re-fetch the same library docs repeatedly
|