@abarcenas/ai-workflow-template 1.23.0 → 1.26.0

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 (33) hide show
  1. package/.agents/instructions/agent-skill.instructions.md +18 -20
  2. package/.agents/instructions/agent.instructions.md +111 -570
  3. package/.agents/instructions/ai-prompt-engineering-safety.instructions.md +3 -3
  4. package/.agents/instructions/instructions.instructions.md +6 -7
  5. package/.agents/instructions/learned-knowledge.instructions.md +17 -41
  6. package/.agents/instructions/memory-bank.instructions.md +125 -17
  7. package/.agents/instructions/memory-schema.instructions.md +75 -0
  8. package/.agents/instructions/prompt.instructions.md +25 -30
  9. package/.agents/instructions/task-implementation.instructions.md +12 -5
  10. package/.agents/skills/architecture-blueprint-generator/SKILL.md +63 -18
  11. package/.agents/skills/context-map/SKILL.md +27 -4
  12. package/.agents/skills/conventional-commit/SKILL.md +2 -2
  13. package/.agents/skills/github-issues/SKILL.md +2 -2
  14. package/.agents/skills/graphify-framework-aware/SKILL.md +133 -0
  15. package/.agents/skills/graphify-framework-aware/references/framework-registry.md +95 -0
  16. package/.agents/skills/graphify-framework-aware/scripts/fw-exclude.py +425 -0
  17. package/.agents/skills/memory-search/SKILL.md +69 -0
  18. package/.agents/skills/microsoft-docs/SKILL.md +1 -1
  19. package/.agents/skills/polygot-test-agent/SKILL.md +0 -1
  20. package/.agents/skills/prompt-builder/SKILL.md +15 -14
  21. package/.husky/post-merge +10 -0
  22. package/.husky/pre-commit +2 -0
  23. package/AGENTS.md +54 -0
  24. package/README.md +177 -3
  25. package/memory-bank/.vocabulary.json +52 -0
  26. package/opencode.mcp.example.json +8 -1
  27. package/package.json +25 -5
  28. package/scripts/mcp-memory-server.js +243 -0
  29. package/scripts/memory-cli.js +110 -0
  30. package/scripts/memory-index.js +512 -0
  31. package/scripts/normalize-memory.js +349 -0
  32. package/scripts/sync.test.js +12 -0
  33. package/scripts/validate-memory-schema.js +190 -0
@@ -0,0 +1,425 @@
1
+ #!/usr/bin/env python3
2
+ """graphify-framework-aware: detect project frameworks and generate .graphifyignore patterns.
3
+
4
+ Commands:
5
+ detect <path> Print JSON of detected frameworks and their markers.
6
+ apply <path> Idempotently write/update .graphifyignore with FW patterns.
7
+ show <path> Print FW patterns only (dry-run, no files written).
8
+
9
+ Exit codes: 0 = success, 1 = error (bad path, invalid args), 2 = nothing to apply.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import json
15
+ import os
16
+ import re
17
+ import subprocess
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ # ── Framework Registry ────────────────────────────────────────────────────────
22
+ # Adding a new framework:
23
+ # 1. Add detection marker(s) to FRAMEWORK_MARKERS.
24
+ # 2. Add exclude patterns to FRAMEWORK_EXCLUDES.
25
+ # Complex detection (Hugo theme) goes in _post_process_excludes().
26
+
27
+ FRAMEWORK_MARKERS: dict[str, list[str]] = {
28
+ "angular": ["angular.json"],
29
+ "nextjs": ["next.config.js", "next.config.ts", "next.config.mjs"],
30
+ "svelte": ["svelte.config.js"],
31
+ "hugo": ["hugo.toml", "hugo.yaml", "hugo.json"],
32
+ "jekyll": ["_config.yml"],
33
+ "docusaurus": ["docusaurus.config.js", "docusaurus.config.ts"],
34
+ "flutter": ["pubspec.yaml"],
35
+ "wordpress": ["wp-config.php"],
36
+ }
37
+
38
+ FRAMEWORK_EXCLUDES: dict[str, list[str]] = {
39
+ "angular": [
40
+ "**/*.spec.ts",
41
+ "**/*.harness.ts",
42
+ "e2e/",
43
+ "src/environments/",
44
+ "karma.conf.js",
45
+ "src/test.ts",
46
+ ],
47
+ "nextjs": [
48
+ "next-env.d.ts",
49
+ "out/",
50
+ ],
51
+ "svelte": [
52
+ "build/",
53
+ "**/*.test.ts",
54
+ ],
55
+ "hugo": [],
56
+ "jekyll": [
57
+ "_site/",
58
+ ".jekyll-cache/",
59
+ ".jekyll-metadata",
60
+ ],
61
+ "docusaurus": [
62
+ ".docusaurus/",
63
+ "build/",
64
+ ],
65
+ "flutter": [
66
+ ".dart_tool/",
67
+ "build/",
68
+ ".flutter-plugins",
69
+ ".flutter-plugins-dependencies",
70
+ ],
71
+ "wordpress": [
72
+ "wp-admin/",
73
+ "wp-includes/",
74
+ "wp-content/languages/",
75
+ "wp-content/upgrade/",
76
+ ],
77
+ }
78
+
79
+ # Marker section boundaries in .graphifyignore
80
+ _MARKER_START = "# ===== graphify-framework-aware (auto-generated) ====="
81
+ _MARKER_END = "# ===== end graphify-framework-aware ====="
82
+
83
+ # Directories graphify already skips natively — don't duplicate them.
84
+ _GRAPHIFY_BUILTIN_SKIP = frozenset({
85
+ "node_modules", "__pycache__", ".git", "dist", "build", "target", "out",
86
+ "site-packages", "lib64", ".pytest_cache", ".mypy_cache", ".ruff_cache",
87
+ ".tox", ".eggs", "*.egg-info", "graphify-out",
88
+ "coverage", "lcov-report", "visual-tests", "visual-test",
89
+ "__snapshots__", "snapshots", "storybook-static", "dist-protected",
90
+ ".next", ".nuxt", ".turbo", ".angular",
91
+ ".idea", ".cache", ".parcel-cache", ".svelte-kit", ".terraform",
92
+ ".serverless", ".graphify", ".worktrees",
93
+ "venv", ".venv", "env", ".env",
94
+ })
95
+
96
+ # Lock files graphify already skips.
97
+ _GRAPHIFY_BUILTIN_SKIP_FILES = frozenset({
98
+ "package-lock.json", "yarn.lock", "pnpm-lock.yaml",
99
+ "Cargo.lock", "poetry.lock", "Gemfile.lock",
100
+ "composer.lock", "go.sum", "go.work.sum",
101
+ })
102
+
103
+
104
+ # ── Detection ─────────────────────────────────────────────────────────────────
105
+
106
+ def _glob_marker(root: Path, pattern: str) -> bool:
107
+ """Check if a glob pattern matches any file in root (non-recursive by default)."""
108
+ matches = list(root.glob(pattern))
109
+ if matches:
110
+ return any(m.is_file() for m in matches)
111
+ return False
112
+
113
+
114
+ def detect_frameworks(root: Path) -> dict:
115
+ """Scan project root for framework marker files.
116
+
117
+ Returns:
118
+ {"frameworks": ["angular", "nextjs"], "markers": {"angular": ["angular.json"], ...}}
119
+ """
120
+ root = root.resolve()
121
+ if not root.is_dir():
122
+ print(f"error: not a directory: {root}", file=sys.stderr)
123
+ sys.exit(1)
124
+
125
+ found: dict[str, list[str]] = {}
126
+ for fw_name, markers in FRAMEWORK_MARKERS.items():
127
+ matched = [m for m in markers if _glob_marker(root, m)]
128
+ if matched:
129
+ found[fw_name] = matched
130
+
131
+ # Flutter: pubspec.yaml is generic — verify it's a Flutter project
132
+ if "flutter" in found:
133
+ pubspec = root / "pubspec.yaml"
134
+ try:
135
+ content = pubspec.read_text(encoding="utf-8")
136
+ if "flutter" not in content.lower():
137
+ del found["flutter"]
138
+ except OSError:
139
+ del found["flutter"]
140
+
141
+ # Hugo: config.toml needs content check if not hugo.toml
142
+ # (config.toml is too generic — many non-Hugo projects use it)
143
+ if "hugo" in found:
144
+ hugo_specific = any("hugo" in m.lower() for m in found["hugo"])
145
+ if not hugo_specific:
146
+ # Only matched generic config.toml — verify it's actually Hugo
147
+ config_file = next((root / m for m in found["hugo"] if (root / m).exists()), None)
148
+ if config_file:
149
+ try:
150
+ content = config_file.read_text(encoding="utf-8")
151
+ if "baseURL" not in content and "title" not in content:
152
+ del found["hugo"]
153
+ except OSError:
154
+ del found["hugo"]
155
+ else:
156
+ del found["hugo"]
157
+
158
+ return {
159
+ "frameworks": sorted(found.keys()),
160
+ "markers": found,
161
+ }
162
+
163
+
164
+ # ── Exclude pattern generation ────────────────────────────────────────────────
165
+
166
+ def _hugo_theme_is_vendored(root: Path) -> bool:
167
+ """Check if Hugo themes/ directory contains git submodules or cloned themes."""
168
+ themes_dir = root / "themes"
169
+ if not themes_dir.is_dir():
170
+ return False
171
+
172
+ # Check for .gitmodules referencing themes
173
+ gitmodules = root / ".gitmodules"
174
+ if gitmodules.exists():
175
+ try:
176
+ content = gitmodules.read_text(encoding="utf-8")
177
+ if "themes/" in content:
178
+ return True
179
+ except OSError:
180
+ pass
181
+
182
+ # Check if individual themes are git repos (submodules)
183
+ for theme in themes_dir.iterdir():
184
+ if theme.is_dir() and (theme / ".git").exists():
185
+ return True
186
+
187
+ return False
188
+
189
+
190
+ def _hugo_user_has_custom_layouts(root: Path) -> bool:
191
+ """Check if the user has custom layouts at project root (outside themes/)."""
192
+ layouts = root / "layouts"
193
+ if not layouts.is_dir():
194
+ return False
195
+ # Has custom layouts if more than just _default/ and partials/ exist
196
+ entries = list(layouts.iterdir())
197
+ custom_entries = [e for e in entries
198
+ if e.name not in ("_default", "partials", "shortcodes")]
199
+ return len(custom_entries) > 0
200
+
201
+
202
+ def _post_process_excludes(frameworks: dict, root: Path) -> dict[str, list[str]]:
203
+ """Apply framework-specific heuristics to refine exclude patterns.
204
+
205
+ Args:
206
+ frameworks: Raw detection result {"frameworks": [...], "markers": {...}}.
207
+ root: Project root path.
208
+
209
+ Returns:
210
+ Per-framework final exclude lists (may add/remove patterns).
211
+ """
212
+ excludes: dict[str, list[str]] = {}
213
+ for fw in frameworks["frameworks"]:
214
+ patterns = list(FRAMEWORK_EXCLUDES.get(fw, []))
215
+ excludes[fw] = patterns
216
+
217
+ # Hugo: refine based on theme/layout detection
218
+ if "hugo" in excludes:
219
+ patterns = excludes["hugo"]
220
+ patterns.append("public/")
221
+ patterns.append("resources/")
222
+
223
+ if _hugo_theme_is_vendored(root):
224
+ patterns.append("archetypes/")
225
+ patterns.append("themes/**/archetypes/")
226
+ patterns.append("themes/**/layouts/")
227
+ else:
228
+ patterns.append("archetypes/")
229
+
230
+ # If user has custom layouts, only exclude defaults
231
+ if not _hugo_user_has_custom_layouts(root):
232
+ patterns.append("layouts/")
233
+ else:
234
+ patterns.append("layouts/_default/")
235
+ patterns.append("layouts/partials/")
236
+ patterns.append("layouts/shortcodes/")
237
+
238
+ return excludes
239
+
240
+
241
+ # ── .graphifyignore management ────────────────────────────────────────────────
242
+
243
+ def _read_graphifyignore(root: Path) -> tuple[str, list[str]]:
244
+ """Read .graphifyignore and split into preamble / our-section / postscript.
245
+
246
+ Returns: (full_raw_content, lines_matching_our_section)
247
+ """
248
+ gf = root / ".graphifyignore"
249
+ if not gf.exists():
250
+ return ("", [])
251
+ try:
252
+ content = gf.read_text(encoding="utf-8")
253
+ except OSError:
254
+ return ("", [])
255
+ return (content, _extract_marker_lines(content))
256
+
257
+
258
+ def _extract_marker_lines(content: str) -> list[str]:
259
+ """Extract lines between our start/end markers (exclusive)."""
260
+ lines = content.splitlines()
261
+ in_block = False
262
+ block_lines: list[str] = []
263
+ for line in lines:
264
+ if line.strip() == _MARKER_START:
265
+ in_block = True
266
+ continue
267
+ if line.strip() == _MARKER_END:
268
+ in_block = False
269
+ continue
270
+ if in_block:
271
+ block_lines.append(line)
272
+ return block_lines
273
+
274
+
275
+ def _normalize_ignore_line(line: str) -> str:
276
+ """Strip comments and whitespace from a single .graphifyignore line."""
277
+ stripped = line.strip()
278
+ if not stripped or stripped.startswith("#"):
279
+ return ""
280
+ return stripped
281
+
282
+
283
+ def _build_marker_block(excludes: dict[str, list[str]]) -> list[str]:
284
+ """Build the marker-delimited block of FW patterns."""
285
+ lines: list[str] = [_MARKER_START]
286
+ seen: set[str] = set()
287
+
288
+ for fw_name, patterns in excludes.items():
289
+ lines.append(f"# auto-detected framework: {fw_name}")
290
+ for pat in patterns:
291
+ normalized = _normalize_ignore_line(pat)
292
+ if not normalized or normalized in seen:
293
+ continue
294
+ # Skip patterns graphify already skips natively
295
+ if normalized.rstrip("/") in _GRAPHIFY_BUILTIN_SKIP:
296
+ continue
297
+ if normalized in _GRAPHIFY_BUILTIN_SKIP_FILES:
298
+ continue
299
+ seen.add(normalized)
300
+ lines.append(pat)
301
+
302
+ lines.append(_MARKER_END)
303
+ return lines
304
+
305
+
306
+ def _write_graphifyignore(root: Path, excludes: dict[str, list[str]]) -> str:
307
+ """Write or update .graphifyignore, replacing our marker section.
308
+
309
+ Returns the summary string describing what was written.
310
+ """
311
+ gf = root / ".graphifyignore"
312
+ existing_content, existing_block = _read_graphifyignore(root)
313
+
314
+ new_block = _build_marker_block(excludes)
315
+ new_block_text = "\n".join(new_block)
316
+
317
+ # Compare ignoring comments (our own section header comments are stable)
318
+ old_effective = [_normalize_ignore_line(l) for l in existing_block if _normalize_ignore_line(l)]
319
+ new_effective = []
320
+ for l in new_block:
321
+ n = _normalize_ignore_line(l)
322
+ if n and not n.startswith("#"):
323
+ new_effective.append(n)
324
+
325
+ if sorted(old_effective) == sorted(new_effective) and _MARKER_START in existing_content:
326
+ return "unchanged"
327
+
328
+ # Rebuild the file: remove old marker block, insert new one
329
+ if _MARKER_START in existing_content:
330
+ lines = existing_content.splitlines()
331
+ out_lines: list[str] = []
332
+ in_block = False
333
+ for line in lines:
334
+ if line.strip() == _MARKER_START:
335
+ in_block = True
336
+ continue
337
+ if line.strip() == _MARKER_END:
338
+ in_block = False
339
+ continue
340
+ if not in_block:
341
+ out_lines.append(line)
342
+ # Remove trailing blank lines before appending
343
+ while out_lines and out_lines[-1].strip() == "":
344
+ out_lines.pop()
345
+ out_lines.append("")
346
+ out_lines.append(new_block_text)
347
+ result = "\n".join(out_lines)
348
+ if not result.endswith("\n"):
349
+ result += "\n"
350
+ else:
351
+ # No existing block — append
352
+ if existing_content.strip():
353
+ result = existing_content.rstrip() + "\n\n" + new_block_text + "\n"
354
+ else:
355
+ result = new_block_text + "\n"
356
+
357
+ gf.write_text(result, encoding="utf-8")
358
+
359
+ # Build summary
360
+ fw_names = list(excludes.keys())
361
+ pattern_count = len(new_effective)
362
+ if pattern_count == 0:
363
+ return f"frameworks detected ({', '.join(fw_names)}) but no additional patterns needed"
364
+ return (
365
+ f"detected {', '.join(fw_names)} — wrote {pattern_count} "
366
+ f"exclusion pattern{'s' if pattern_count != 1 else ''} to .graphifyignore"
367
+ )
368
+
369
+
370
+ # ── CLI ───────────────────────────────────────────────────────────────────────
371
+
372
+ def _cmd_detect(root: Path) -> None:
373
+ result = detect_frameworks(root)
374
+ print(json.dumps(result, indent=2))
375
+
376
+
377
+ def _cmd_show(root: Path) -> None:
378
+ result = detect_frameworks(root)
379
+ if not result["frameworks"]:
380
+ print("No supported frameworks detected.", file=sys.stderr)
381
+ sys.exit(2)
382
+ excludes = _post_process_excludes(result, root)
383
+ for fw, patterns in excludes.items():
384
+ print(f"# {fw}")
385
+ for pat in patterns:
386
+ n = _normalize_ignore_line(pat)
387
+ if n and n not in _GRAPHIFY_BUILTIN_SKIP and n not in _GRAPHIFY_BUILTIN_SKIP_FILES:
388
+ print(pat)
389
+ print()
390
+
391
+
392
+ def _cmd_apply(root: Path) -> None:
393
+ result = detect_frameworks(root)
394
+ if not result["frameworks"]:
395
+ print("No supported frameworks detected.", file=sys.stderr)
396
+ sys.exit(2)
397
+ excludes = _post_process_excludes(result, root)
398
+ summary = _write_graphifyignore(root, excludes)
399
+ print(f"graphify-framework-aware: {summary}")
400
+
401
+
402
+ _CMD_TABLE: dict[str, callable] = {
403
+ "detect": _cmd_detect,
404
+ "show": _cmd_show,
405
+ "apply": _cmd_apply,
406
+ }
407
+
408
+
409
+ def main() -> None:
410
+ if len(sys.argv) < 3:
411
+ print(f"usage: {sys.argv[0]} <detect|show|apply> <project-path>", file=sys.stderr)
412
+ sys.exit(1)
413
+
414
+ cmd = sys.argv[1]
415
+ path = Path(sys.argv[2])
416
+
417
+ if cmd not in _CMD_TABLE:
418
+ print(f"error: unknown command '{cmd}' (expected: detect, show, apply)", file=sys.stderr)
419
+ sys.exit(1)
420
+
421
+ _CMD_TABLE[cmd](path)
422
+
423
+
424
+ if __name__ == "__main__":
425
+ main()
@@ -0,0 +1,69 @@
1
+ ---
2
+ description: "Search project memory bank using semantic vector search"
3
+ name: "memory-search"
4
+ ---
5
+
6
+ # Memory Search Skill
7
+
8
+ Use this skill to retrieve project context from the memory bank without loading all files into context.
9
+
10
+ ## When to Use
11
+
12
+ - At the start of a session: search for current project focus and recent changes
13
+ - Before making a decision: search for related past decisions
14
+ - When stuck: search for architectural patterns or known issues
15
+ - After writing to memory-bank: run `memory_rebuild` to update the index
16
+
17
+ ## Available MCP Tools
18
+
19
+ This skill uses the `memory-bank` MCP server, configured in `opencode.json`:
20
+
21
+ | Tool | Purpose |
22
+ |---|---|
23
+ | `memory_search` | Semantic search across all memory-bank and docs files |
24
+ | `memory_update` | Incremental sync — only changed files (~2 seconds). Use daily. |
25
+ | `memory_rebuild` | Full rebuild (rare — fresh clone, corrupted index) |
26
+ | `memory_get` | Read a specific memory file by name |
27
+ | `memory_stats` | Get index statistics (vector count, file count, DB size) |
28
+
29
+ ## Workflow
30
+
31
+ ### Session Start
32
+
33
+ 1. Run `memory_stats` to check if the index is populated
34
+ 2. If empty, run `memory_rebuild`; otherwise, run `memory_update`
35
+ 3. Search for current context: `memory_search({ query: "current focus recent changes next steps" })`
36
+
37
+ ### During Tasks
38
+
39
+ - Before implementing: `memory_search({ query: "<topic>", topK: 5 })` for related decisions
40
+ - When writing to memory-bank: update files, then run `memory_update`
41
+ - For full file content: `memory_get({ file: "activeContext" })`
42
+
43
+ ### After Git Pull
44
+
45
+ The `post-merge` hook runs `memory:update` automatically if memory-bank files changed.
46
+
47
+ ### Search Tips
48
+
49
+ - **Be specific**: "TDD orchestrator bootstrap prerequisites" gets better results than "project"
50
+ - **Use contextual terms**: Include entity names (vitest, playwright, graphify) from the vocabulary
51
+ - **Filter by file**: `memory_search({ query: "...", sourceFile: "systemPatterns" })` to narrow scope
52
+ - **Top-K tuning**: Use `topK: 3` for focused queries, `topK: 10` for broad exploration
53
+
54
+ ## Vocabulary Reference
55
+
56
+ See `memory-bank/.vocabulary.json` for the full controlled vocabulary. Key tags:
57
+
58
+ - **Agent roles**: orchestrator, coder, reviewer, tracker, architect, researcher
59
+ - **Workflow**: tdd, feature-pipeline, bootstrap, configuration, refactor, migration
60
+ - **Memory ops**: decision, discovery, status-update, task-plan, retrospective
61
+ - **Technologies**: typescript, vitest, playwright, graphify, mcp, sqlite-vec
62
+
63
+ ## Manual CLI (for debugging)
64
+
65
+ ```bash
66
+ node scripts/memory-cli.js search "tdd orchestrator"
67
+ node scripts/memory-cli.js rebuild
68
+ node scripts/memory-cli.js stats
69
+ ```
@@ -64,7 +64,7 @@ GitHub docs live on **docs.github.com** and **cli.github.com**.
64
64
 
65
65
  | Library ID | Use for |
66
66
  | ---------------------- | --------------------------------------------- |
67
- | `/websites/github_en` | Actions, API, repos, security, admin, Copilot |
67
+ | `/websites/github_en` | Actions, API, repos, security, admin |
68
68
  | `/websites/cli_github` | GitHub CLI (`gh`) commands and flags |
69
69
 
70
70
  ### Agent Framework — Use Learn MCP + Context7
@@ -154,7 +154,6 @@ Add tests for the authentication module with focus on edge cases
154
154
 
155
155
  - Project must have a build/test system configured
156
156
  - Testing framework should be installed (or installable)
157
- - VS Code with GitHub Copilot extension
158
157
 
159
158
  ## Troubleshooting
160
159
 
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: prompt-builder
3
- description: "Guide users through creating high-quality GitHub Copilot prompts with proper structure, tools, and best practices."
3
+ description: "Guide users through creating high-quality opencode prompts with proper structure, tools, and best practices."
4
4
  ---
5
5
 
6
6
  # Professional Prompt Builder
7
7
 
8
- You are an expert prompt engineer specializing in GitHub Copilot prompt development with deep knowledge of:
8
+ You are an expert prompt engineer specializing in opencode prompt development with deep knowledge of:
9
9
 
10
10
  - Prompt engineering best practices and patterns
11
- - VS Code Copilot customization capabilities
11
+ - opencode customization capabilities
12
12
  - Effective persona design and task specification
13
13
  - Tool integration and front matter configuration
14
14
  - Output format optimization for AI consumption
@@ -27,7 +27,7 @@ I will ask you targeted questions to gather all necessary information. After col
27
27
 
28
28
  ### 2. **Persona Definition**
29
29
 
30
- - What role/expertise should Copilot embody? Be specific about:
30
+ - What role/expertise should the AI assistant embody? Be specific about:
31
31
  - Technical expertise level (junior, senior, expert, specialist)
32
32
  - Domain knowledge (languages, frameworks, tools)
33
33
  - Years of experience or specific qualifications
@@ -42,15 +42,15 @@ I will ask you targeted questions to gather all necessary information. After col
42
42
 
43
43
  ### 4. **Context & Variable Requirements**
44
44
 
45
- - Will it use `${selection}` (user's selected code)?
46
- - Will it use `${file}` (current file) or other file references?
47
- - Does it need input variables like `${input:variableName}` or `${input:variableName:placeholder}`?
48
- - Will it reference workspace variables (`${workspaceFolder}`, etc.)?
45
+ - Will it use selected text from the editor?
46
+ - Will it use the current file path or other file references?
47
+ - Does it need custom input parameters or variable references?
48
+ - Will it reference the workspace root path or other project-level variables?
49
49
  - Does it need to access other files or prompt files as dependencies?
50
50
 
51
51
  ### 5. **Detailed Instructions & Standards**
52
52
 
53
- - What step-by-step process should Copilot follow?
53
+ - What step-by-step process should the AI follow?
54
54
  - Are there specific coding standards, frameworks, or libraries to use?
55
55
  - What patterns or best practices should be enforced?
56
56
  - Are there things to avoid or constraints to respect?
@@ -68,11 +68,10 @@ I will ask you targeted questions to gather all necessary information. After col
68
68
 
69
69
  Which tools does this prompt need? Common options include:
70
70
 
71
- - **File Operations**: `codebase`, `editFiles`, `search`, `problems`
72
- - **Execution**: `runCommands`, `runTasks`, `runTests`, `terminalLastCommand`
73
- - **External**: `fetch`, `githubRepo`, `openSimpleBrowser`
74
- - **Specialized**: `playwright`, `usages`, `vscodeAPI`, `extensions`
75
- - **Analysis**: `changes`, `findTestFiles`, `testFailure`, `searchResults`
71
+ - **File Operations**: `Read`, `Write`, `Edit`, `Grep`, `Glob`
72
+ - **Execution**: `Bash`
73
+ - **External**: `WebFetch`, `WebSearch`
74
+ - **Specialized**: `playwright` (Playwright MCP)
76
75
 
77
76
  ### 8. **Technical Configuration**
78
77
 
@@ -111,9 +110,11 @@ After gathering all requirements, I will generate a complete `.prompt.md` file f
111
110
  ```markdown
112
111
  ---
113
112
  description: "[Clear, concise description from requirements]"
113
+ name: "[prompt-name]"
114
114
  agent: "[agent|ask|edit based on task type]"
115
115
  tools: ["[appropriate tools based on functionality]"]
116
116
  model: "[only if specific model required]"
117
+ argument-hint: "[hint text shown in chat input]"
117
118
  ---
118
119
 
119
120
  # [Prompt Title]
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ # After git pull/merge, check if memory-bank files changed
5
+ # and update the vector index incrementally
6
+
7
+ if git diff HEAD@{1} --name-only 2>/dev/null | grep -q "^memory-bank\|^docs/"; then
8
+ echo "[memory-bank] Memory bank files changed. Updating vector index..."
9
+ node scripts/memory-cli.js update 2>/dev/null || echo "[memory-bank] Index update skipped (service not installed)"
10
+ fi
@@ -0,0 +1,2 @@
1
+ node scripts/bump-version.js
2
+ node scripts/validate-memory-schema.js
package/AGENTS.md CHANGED
@@ -141,9 +141,63 @@ The agent file is at `.opencode/agents/orchestrator/feature-pipeline.agent.md`.
141
141
 
142
142
  **When to use:** You want a predictable, four-step feature pipeline without dynamic agent selection. The orchestrator agent is more flexible; this is more opinionated.
143
143
 
144
+ ### TDD Orchestrator — Test-Driven Development Pipeline
145
+
146
+ Use this when you want strict Test-Driven Development: **tests first, code second**. The pipeline enforces the RED → GREEN → REFACTOR/VERIFY cycle:
147
+
148
+ ```
149
+ implementer (PLAN) → unit-tester∥ (RED) → coder∥ (GREEN) → unit-tester (VERIFY ≥90%) → reviewer → tracker
150
+ ```
151
+
152
+ | Step | Phase | Agent | Role |
153
+ |------|-------|-------|------|
154
+ | 1 | PLAN | implementer | Creates plan with parallel test/code batch tables |
155
+ | 2 | RED | unit-tester∥ | Writes failing tests before any implementation exists |
156
+ | 3 | GREEN | coder∥ | Writes minimal code to pass tests — no extra features |
157
+ | 4 | VERIFY | unit-tester | Runs all tests, checks coverage ≥ 90% |
158
+ | 5 | REVIEW | reviewer | Audits tests + code for quality, security, patterns |
159
+ | 6 | DOCUMENT | tracker | Records results to `docs/tracker-log.md` |
160
+
161
+ The agent file is at `.opencode/agents/orchestrator/tdd-orchestrator.agent.md`.
162
+
163
+ **When to use:** Any feature, bug fix, or refactor where tests should be written first. The orchestrator automatically selects this pipeline when testable code changes are requested.
164
+
165
+ **Coverage gate:** If coverage < 90%, the pipeline loops back to RED phase (up to 3 iterations).
166
+
167
+ ### Memory Bank
168
+
169
+ The memory bank at `memory-bank/` preserves project context across AI sessions. Core files:
170
+
171
+ | File | Purpose |
172
+ |------|---------|
173
+ | `projectbrief.md` | Core requirements, goals, scope |
174
+ | `productContext.md` | Problem solved, UX goals |
175
+ | `systemPatterns.md` | Architecture, design patterns |
176
+ | `techContext.md` | Technologies, setup, constraints |
177
+ | `activeContext.md` | Current focus, recent changes, next steps |
178
+ | `progress.md` | What works, what's left, known issues |
179
+ | `tasks/` | Per-task tracking with `_index.md` |
180
+
181
+ **Always read `activeContext.md` and `progress.md` at the start of every task.** Update them after completing work. See `.agents/instructions/memory-bank.instructions.md` for full details.
182
+
144
183
  ## Additional Resources
145
184
 
146
185
  ### Playwright MCP Configuration
147
186
 
148
187
  For details on how Playwright MCP integrates with the headed mode debugging configuration, see:
149
188
  - **Docs**: `docs/playwright-mcp-configuration.md`
189
+
190
+ ## graphify
191
+
192
+ This project has a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships.
193
+
194
+ When the user types `/graphify`, invoke these skills in order before doing anything else:
195
+ 1. `skill: "graphify-framework-aware"` — detects project frameworks and configures `.graphifyignore` to exclude boilerplate
196
+ 2. `skill: "graphify"` — runs the knowledge graph pipeline
197
+
198
+ Rules:
199
+ - For codebase questions, first run `graphify query "<question>"` when graphify-out/graph.json exists. Use `graphify path "<A>" "<B>"` for relationships and `graphify explain "<concept>"` for focused concepts. These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output.
200
+ - Dirty graphify-out/ files are expected after hooks or incremental updates; dirty graph files are not a reason to skip graphify. Only skip graphify if the task is about stale or incorrect graph output, or the user explicitly says not to use it.
201
+ - If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing.
202
+ - Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context.
203
+ - After modifying code, run `graphify update .` to keep the graph current (AST-only, no API cost).