@jenga-ai/agent 1.0.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.
- package/LICENSE +201 -0
- package/README.md +340 -0
- package/agents/ai_engineer.md +113 -0
- package/agents/developer.md +236 -0
- package/agents/scrum-master.md +349 -0
- package/agents/scrutiny-agent.md +137 -0
- package/agents/solution-assessor.md +185 -0
- package/agents/tester.md +339 -0
- package/bin/jenga.js +70 -0
- package/hooks/copilot_session_end.sh +29 -0
- package/hooks/on_session_end.sh +238 -0
- package/hooks/prompt_router.sh +11 -0
- package/hooks/prompt_router_helper.js +52 -0
- package/hooks/session_end_helper.js +29 -0
- package/hooks/session_end_watcher.sh +24 -0
- package/lib/commands/attach.js +47 -0
- package/lib/commands/init.js +207 -0
- package/lib/commands/start.js +16 -0
- package/lib/commands/status.js +53 -0
- package/lib/config-schema.js +72 -0
- package/lib/inject-settings.js +61 -0
- package/lib/mirror.js +244 -0
- package/lib/resolve-project-dir.sh +47 -0
- package/mcp/execute-ticket/index.js +10 -0
- package/mcp/execute-ticket/package.json +5 -0
- package/mcp/help/index.js +79 -0
- package/mcp/help/package.json +14 -0
- package/mcp/router/README.md +19 -0
- package/mcp/router/embedder.js +23 -0
- package/mcp/router/index.js +204 -0
- package/mcp/router/matcher.js +87 -0
- package/mcp/router/package-lock.json +1048 -0
- package/mcp/router/package.json +11 -0
- package/mcp/router/skill-index.js +104 -0
- package/package.json +47 -0
- package/scripts/board_resolver.sh +46 -0
- package/scripts/e25_s01_extract_board_graph.py +292 -0
- package/scripts/e25_s01_generate_synthetic_board.py +90 -0
- package/scripts/measurement-10x.json +50 -0
- package/scripts/measurement-10x.txt +4 -0
- package/scripts/measurement-real.json +50 -0
- package/scripts/measurement-real.txt +4 -0
- package/scripts/postinstall.js +165 -0
- package/scripts/todo_cleanup.sh +22 -0
- package/scripts/todo_manager.sh +86 -0
- package/scripts/validate-board.sh +190 -0
- package/scripts/validate-story-format.sh +53 -0
- package/skills/brainstorm/SKILL.md +47 -0
- package/skills/btw/SKILL.md +42 -0
- package/skills/commit/SKILL.md +29 -0
- package/skills/commit/assets/user_instructions_template.md +22 -0
- package/skills/continue/SKILL.md +29 -0
- package/skills/convert/SKILL.md +124 -0
- package/skills/convert/convert_cli.py +235 -0
- package/skills/convert/tests/sample.csv +4 -0
- package/skills/convert/tests/sample.json +5 -0
- package/skills/convert/tests/sample.jsonl +3 -0
- package/skills/convert/tests/sample.yaml +18 -0
- package/skills/convert/tests/sample_obj.csv +2 -0
- package/skills/convert/tests/sample_obj.json +9 -0
- package/skills/deep-dive/SKILL.md +167 -0
- package/skills/do/SKILL.md +88 -0
- package/skills/do/assets/sender_template.json +12 -0
- package/skills/doc/SKILL.md +314 -0
- package/skills/doc/assets/path-objectives.yaml +38 -0
- package/skills/doc-sync/SKILL.md +167 -0
- package/skills/doc-sync/assets/default_excludes.txt +21 -0
- package/skills/doc-sync/assets/doc_targets.md +14 -0
- package/skills/dooo/SKILL.md +60 -0
- package/skills/error/SKILL.md +29 -0
- package/skills/evaluate/SKILL.md +45 -0
- package/skills/evaluate/assets/evaluation_invokation_template.yml +3 -0
- package/skills/evaluate/assets/evaluation_rapport_template.md +24 -0
- package/skills/examplify/SKILL.md +42 -0
- package/skills/help/SKILL.md +36 -0
- package/skills/improve/SKILL.md +55 -0
- package/skills/index/scripts/board-index +4 -0
- package/skills/index/scripts/board_index.py +615 -0
- package/skills/index/scripts/smoke_test.sh +86 -0
- package/skills/init/SKILL.md +44 -0
- package/skills/init/assets/.gitignore_template +15 -0
- package/skills/init/assets/PROJECT_SUMMARY_template.md +13 -0
- package/skills/init/assets/directory_structure.txt +13 -0
- package/skills/init/assets/test-config_template.json +4 -0
- package/skills/init/assets/workflow_template.json +30 -0
- package/skills/init/scripts/init.sh +48 -0
- package/skills/jbp/SKILL.md +25 -0
- package/skills/jenga/SKILL.md +68 -0
- package/skills/lgtm/SKILL.md +21 -0
- package/skills/mirror-public/SKILL.md +237 -0
- package/skills/mirror-public/assets/config.json +5 -0
- package/skills/mirror-public/scripts/mirror.sh +374 -0
- package/skills/pi-plan/SKILL.md +62 -0
- package/skills/pi-plan/assets/epic.json +7 -0
- package/skills/pi-plan/assets/story_template.md +18 -0
- package/skills/proceed/SKILL.md +29 -0
- package/skills/publish/SKILL.md +351 -0
- package/skills/publish/adapters/droplet.md +200 -0
- package/skills/publish/adapters/mobile-ios.md +114 -0
- package/skills/publish/adapters/npm-ci.md +223 -0
- package/skills/publish/adapters/npm.md +121 -0
- package/skills/publish/assets/ExportOptions.plist.template +19 -0
- package/skills/publish/assets/ci-contract.md +111 -0
- package/skills/publish/assets/ownership-matrix.md +17 -0
- package/skills/publish/assets/publish.example.json +85 -0
- package/skills/publish/assets/publish.example.npm-ci.json +40 -0
- package/skills/publish/assets/publish.example.npm.json +41 -0
- package/skills/publish/assets/secrets-guide.md +104 -0
- package/skills/publish/schemas/fixtures/npm-ci-minimal.json +17 -0
- package/skills/publish/schemas/fixtures/npm-ci-with-empty-secrets.json +18 -0
- package/skills/publish/schemas/fixtures/npm-ci-with-workflow-path.json +18 -0
- package/skills/publish/schemas/publish.schema.json +428 -0
- package/skills/publish/scripts/check_target_config.sh +96 -0
- package/skills/publish/scripts/droplet_pipeline.sh +208 -0
- package/skills/publish/scripts/generate_release_notes.sh +200 -0
- package/skills/publish/scripts/ios_pipeline.sh +486 -0
- package/skills/publish/scripts/npm_ci_pipeline.sh +225 -0
- package/skills/publish/scripts/npm_pipeline.sh +249 -0
- package/skills/publish/scripts/publish_common.sh +253 -0
- package/skills/publish/scripts/publish_deploy.sh +538 -0
- package/skills/publish/scripts/reconcile_tags.sh +135 -0
- package/skills/publish/scripts/run_gates.sh +616 -0
- package/skills/publish/scripts/setup_wizard.sh +394 -0
- package/skills/publish/scripts/show_history.sh +95 -0
- package/skills/publish/scripts/suggest_semver_bump.sh +105 -0
- package/skills/publish/scripts/validate_config.sh +163 -0
- package/skills/publish/scripts/validate_droplet_env.sh +45 -0
- package/skills/publish/scripts/validate_ios_env.sh +68 -0
- package/skills/publish/scripts/validate_npm_ci_env.sh +71 -0
- package/skills/publish/scripts/validate_npm_env.sh +22 -0
- package/skills/publish/scripts/write_ledger_entry.sh +126 -0
- package/skills/publish/wizards/droplet.md +275 -0
- package/skills/publish/wizards/mobile-ios.md +157 -0
- package/skills/publish/wizards/npm-ci.md +240 -0
- package/skills/publish/wizards/npm.md +224 -0
- package/skills/reconcile/SKILL.md +93 -0
- package/skills/reconcile/assets/report_format.md +44 -0
- package/skills/reconcile-origin/SKILL.md +75 -0
- package/skills/reconcile-origin/scripts/reconcile-origin.sh +372 -0
- package/skills/redo/SKILL.md +70 -0
- package/skills/route/SKILL.md +180 -0
- package/skills/self-sync/SKILL.md +73 -0
- package/skills/self-sync/scripts/run.js +136 -0
- package/skills/skillify/SKILL.md +68 -0
- package/skills/skillify/assets/init-new/SKILL.md +35 -0
- package/skills/skillify/assets/init-new/assets/.gitignore_template +15 -0
- package/skills/skillify/assets/init-new/assets/PROJECT_SUMMARY_template.md +13 -0
- package/skills/skillify/assets/init-new/assets/directory_structure.txt +10 -0
- package/skills/skillify/assets/init-new/assets/test-config_template.json +4 -0
- package/skills/skillify/assets/init-new/assets/workflow_template.json +17 -0
- package/skills/skillify/assets/init-new/scripts/init.sh +48 -0
- package/skills/skillify/assets/init-old/SKILL.md +124 -0
- package/skills/spinoff/SKILL.md +48 -0
- package/skills/status/SKILL.md +33 -0
- package/skills/status/assets/output_format.md +41 -0
- package/skills/todo/SKILL.md +46 -0
- package/skills/todo/assets/todo_handoff_template.md +22 -0
- package/skills/todo/assets/todo_template.md +3 -0
- package/skills/train/SKILL.md +116 -0
- package/skills/train/assets/dashboard-templates/classifiers.html +106 -0
- package/skills/train/assets/dashboard-templates/nlp.html +102 -0
- package/skills/train/assets/dashboard-templates/transformers.html +98 -0
- package/skills/train/assets/results-parsers/__init__.py +9 -0
- package/skills/train/assets/results-parsers/classifiers.py +84 -0
- package/skills/train/assets/results-parsers/nlp.py +88 -0
- package/skills/train/assets/results-parsers/reporter.py +154 -0
- package/skills/train/assets/results-parsers/transformers.py +120 -0
- package/skills/train/train_cli.py +786 -0
- package/templates/EXECUTION_PLAN_TEMPLATE.md +43 -0
- package/templates/EXECUTION_SUMMARY_TEMPLATE.md +50 -0
- package/templates/JENGA_CONFIG_TEMPLATE.json +23 -0
- package/templates/PROBLEM_RAPPORT_TEMPLATE.md +88 -0
- package/templates/SCRUM_BOARD_SCHEMA.md +311 -0
- package/templates/SKILL.md +16 -0
- package/templates/SKILL_TEMPLATE.md +28 -0
- package/templates/USER_INSTRUCTIONS_TEMPLATE.md +22 -0
- package/templates/copilot-instructions.md.tpl +55 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commit
|
|
3
|
+
description: Commit implemented epic, story, or task work using the EST naming convention. Also handles user-action prerequisites and new-epic boundaries. Use after completing any EST work item.
|
|
4
|
+
keywords:
|
|
5
|
+
- commit
|
|
6
|
+
- save
|
|
7
|
+
- git commit
|
|
8
|
+
- done
|
|
9
|
+
- push
|
|
10
|
+
examples:
|
|
11
|
+
- "commit this work"
|
|
12
|
+
- "save my changes"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Commit — Commit Completed Work
|
|
16
|
+
|
|
17
|
+
## Instructions
|
|
18
|
+
|
|
19
|
+
If no epic, task, or story has been implemented, exit with the message: "No implementation to commit."
|
|
20
|
+
|
|
21
|
+
1. **Verify user-action prerequisites** — Check whether an `_INSTRUCTIONS.md` file exists for this task at `project/board/tasks/<E##_S##_T##>_INSTRUCTIONS.md`. If the task has out-of-scope prerequisites but no instructions file was created, create one now using `assets/user_instructions_template.md`. If one already exists, surface it to the user as a reminder. (The developer should have created this file during task intake — this is a final safety check.)
|
|
22
|
+
|
|
23
|
+
2. **Commit** using the following format:
|
|
24
|
+
- **Epic:** `epic(<Epic Title>): <MAX_50_CHAR_SUMMARY>`
|
|
25
|
+
- **Task/Story:** `story(<Epic Title>_<Story Title>): <MAX_50_CHAR_SUMMARY>`
|
|
26
|
+
|
|
27
|
+
**Fallback: Group changes logically** — prefer one commit per coherent unit of work, but don't force splits. When in doubt, keep it together.
|
|
28
|
+
|
|
29
|
+
3. **Check for next epic** — If a new epic is to be started, inform the user that a new conversation should be initiated. If there are no subsequent epics left, show the message: "All Done! 🎉"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# <Action Name> — Setup Instructions
|
|
2
|
+
|
|
3
|
+
**Epic**: E## — <epic title>
|
|
4
|
+
**Required before**: <story or task that depends on this>
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
<Brief description of what the user needs to set up and why.>
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. <Step one>
|
|
13
|
+
2. <Step two>
|
|
14
|
+
3. <Step three>
|
|
15
|
+
|
|
16
|
+
## Verification
|
|
17
|
+
|
|
18
|
+
<How the user can confirm the setup is complete and working.>
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
<Any caveats, links to external docs, or environment-specific instructions.>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: continue
|
|
3
|
+
description: Check project status across PROJECT_SUMMARY.md, epics, and stories to determine what should be done next. Reports "All done!" if everything is complete.
|
|
4
|
+
keywords:
|
|
5
|
+
- continue
|
|
6
|
+
- next
|
|
7
|
+
- proceed
|
|
8
|
+
- what's next
|
|
9
|
+
- status
|
|
10
|
+
examples:
|
|
11
|
+
- "what should I do next?"
|
|
12
|
+
- "continue with the project"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Continue — Pick Up the Next Work Item
|
|
16
|
+
|
|
17
|
+
## Instructions
|
|
18
|
+
|
|
19
|
+
1. **Check `project/PROJECT_SUMMARY.md`** — Determine if there is outstanding work at the project level.
|
|
20
|
+
|
|
21
|
+
2. **Check `project/epics/`** — If the project summary is done, check if any epics have remaining work.
|
|
22
|
+
|
|
23
|
+
3. **Check `project/stories/`** — If epics are done, check if any stories have remaining work.
|
|
24
|
+
|
|
25
|
+
**Important:** Always check story status within an epic even if the epic itself is marked as done.
|
|
26
|
+
|
|
27
|
+
4. **If everything is complete** — Respond with: "All done! 🎉"
|
|
28
|
+
|
|
29
|
+
5. **Otherwise** — Begin work on the next incomplete item.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: convert
|
|
3
|
+
description: Convert JSON, JSONL, YAML, or YML dataset files to CSV format. Pass-through for files already in CSV. Flattens nested structures using dot-notation.
|
|
4
|
+
keywords:
|
|
5
|
+
- convert
|
|
6
|
+
- csv
|
|
7
|
+
- json to csv
|
|
8
|
+
- yaml to csv
|
|
9
|
+
- dataset format
|
|
10
|
+
examples:
|
|
11
|
+
- "convert this JSON file to CSV"
|
|
12
|
+
- "convert my dataset to CSV format"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Convert — Dataset File Converter
|
|
16
|
+
|
|
17
|
+
## What It Does
|
|
18
|
+
|
|
19
|
+
`/convert` takes a dataset file in JSON, JSONL, YAML, or YML format and outputs a clean CSV file ready for use in `/train` jobs.
|
|
20
|
+
|
|
21
|
+
- **Auto-detects** the input format from the file extension
|
|
22
|
+
- **Flattens** nested objects using dot-notation (e.g. `{"user": {"age": 30}}` → column `user.age`)
|
|
23
|
+
- **Pass-through**: if the input is already `.csv`, it is returned unchanged
|
|
24
|
+
- **Warns** if the top-level structure is an object `{}` instead of an array `[]`, and asks for confirmation before converting
|
|
25
|
+
|
|
26
|
+
Output is written to the **same directory** as the input file, with a `.csv` extension.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Invocation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
python skills/convert/convert_cli.py <path-to-file>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or, when invoked through the Copilot CLI:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
/convert <path-to-file>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Supported Formats
|
|
45
|
+
|
|
46
|
+
| Extension | Description |
|
|
47
|
+
|---------------|--------------------------------------------------|
|
|
48
|
+
| `.json` | JSON array `[{...}, ...]` or object `{...}` |
|
|
49
|
+
| `.jsonl` | JSON Lines — one JSON object per line |
|
|
50
|
+
| `.yaml`/`.yml`| YAML array of records or mapping |
|
|
51
|
+
| `.csv` | Already CSV — returned as-is (no conversion) |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
### JSON array → CSV
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python skills/convert/convert_cli.py data/train.json
|
|
61
|
+
# Output: data/train.csv
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### JSONL with nested structures → CSV
|
|
65
|
+
|
|
66
|
+
Input `data/train.jsonl`:
|
|
67
|
+
```
|
|
68
|
+
{"id": 1, "user": {"name": "Alice", "age": 30}, "label": "pos"}
|
|
69
|
+
{"id": 2, "user": {"name": "Bob", "age": 25}, "label": "neg"}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Output `data/train.csv`:
|
|
73
|
+
```
|
|
74
|
+
id,user.name,user.age,label
|
|
75
|
+
1,Alice,30,pos
|
|
76
|
+
2,Bob,25,neg
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### YAML → CSV
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python skills/convert/convert_cli.py data/train.yaml
|
|
83
|
+
# Output: data/train.csv
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### CSV pass-through
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
python skills/convert/convert_cli.py data/train.csv
|
|
90
|
+
# ✅ Input is already CSV — no conversion needed: /path/to/data/train.csv
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### JSON object (top-level `{}`)
|
|
94
|
+
|
|
95
|
+
When the file's top-level structure is an object rather than an array, the tool warns:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
⚠️ Warning: 'config.json' has a top-level object ({...}), not an array ([...]).
|
|
99
|
+
The tool will create a single-row CSV where each top-level key becomes a column.
|
|
100
|
+
Proceed? [y/N]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Dot-Notation Flattening
|
|
106
|
+
|
|
107
|
+
Nested dicts are flattened recursively:
|
|
108
|
+
|
|
109
|
+
| Input JSON | CSV column | Value |
|
|
110
|
+
|-----------------------------------------|----------------|-------|
|
|
111
|
+
| `{"user": {"name": "Alice"}}` | `user.name` | Alice |
|
|
112
|
+
| `{"user": {"address": {"city": "NYC"}}}` | `user.address.city` | NYC |
|
|
113
|
+
| `{"tags": ["ml", "nlp"]}` | `tags` | `["ml", "nlp"]` (JSON string) |
|
|
114
|
+
|
|
115
|
+
Lists nested within records are preserved as JSON strings.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Notes
|
|
120
|
+
|
|
121
|
+
- Requires `pyyaml` for YAML/YML support: `pip install pyyaml`
|
|
122
|
+
- Standard library only for JSON and JSONL (no extra dependencies)
|
|
123
|
+
- Columns are ordered by first appearance across all records
|
|
124
|
+
- Records missing a key will have an empty cell in that column
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
convert_cli.py — Dataset file converter for ML training jobs.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python convert_cli.py <path-to-file>
|
|
7
|
+
|
|
8
|
+
Supported input formats:
|
|
9
|
+
.json — JSON array of records (or object, with confirmation)
|
|
10
|
+
.jsonl — JSON Lines (one record per line)
|
|
11
|
+
.yaml — YAML array of records (or object, with confirmation)
|
|
12
|
+
.yml — same as .yaml
|
|
13
|
+
.csv — pass-through (returned as-is, no conversion)
|
|
14
|
+
|
|
15
|
+
Output:
|
|
16
|
+
Written to the same directory as the input file with a .csv extension.
|
|
17
|
+
e.g. data/train.json → data/train.csv
|
|
18
|
+
"""
|
|
19
|
+
import csv
|
|
20
|
+
import json
|
|
21
|
+
import sys
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
import yaml
|
|
26
|
+
_YAML_AVAILABLE = True
|
|
27
|
+
except ImportError:
|
|
28
|
+
_YAML_AVAILABLE = False
|
|
29
|
+
|
|
30
|
+
SUPPORTED_EXTENSIONS = {".json", ".jsonl", ".yaml", ".yml", ".csv"}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
# Flattening
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
def _flatten(record, prefix=""):
|
|
38
|
+
"""
|
|
39
|
+
Recursively flatten a nested dict using dot-notation keys.
|
|
40
|
+
Non-dict values (including lists) are kept as-is (lists become JSON strings).
|
|
41
|
+
"""
|
|
42
|
+
out = {}
|
|
43
|
+
for k, v in record.items():
|
|
44
|
+
full_key = f"{prefix}.{k}" if prefix else k
|
|
45
|
+
if isinstance(v, dict):
|
|
46
|
+
out.update(_flatten(v, full_key))
|
|
47
|
+
elif isinstance(v, list):
|
|
48
|
+
out[full_key] = json.dumps(v)
|
|
49
|
+
else:
|
|
50
|
+
out[full_key] = v
|
|
51
|
+
return out
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def flatten_records(records):
|
|
55
|
+
"""Flatten a list of dicts. Returns a list of flat dicts."""
|
|
56
|
+
return [_flatten(r) if isinstance(r, dict) else {"value": r} for r in records]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
# Loaders
|
|
61
|
+
# ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
def load_json(path):
|
|
64
|
+
with open(path, encoding="utf-8") as f:
|
|
65
|
+
data = json.load(f)
|
|
66
|
+
return data
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def load_jsonl(path):
|
|
70
|
+
records = []
|
|
71
|
+
with open(path, encoding="utf-8") as f:
|
|
72
|
+
for lineno, line in enumerate(f, 1):
|
|
73
|
+
line = line.strip()
|
|
74
|
+
if not line:
|
|
75
|
+
continue
|
|
76
|
+
try:
|
|
77
|
+
records.append(json.loads(line))
|
|
78
|
+
except json.JSONDecodeError as e:
|
|
79
|
+
print(f"⚠️ Skipping line {lineno} — JSON parse error: {e}")
|
|
80
|
+
return records
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def load_yaml(path):
|
|
84
|
+
if not _YAML_AVAILABLE:
|
|
85
|
+
print("❌ PyYAML is not installed. Install it with: pip install pyyaml")
|
|
86
|
+
sys.exit(1)
|
|
87
|
+
with open(path, encoding="utf-8") as f:
|
|
88
|
+
data = yaml.safe_load(f)
|
|
89
|
+
return data
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# ---------------------------------------------------------------------------
|
|
93
|
+
# Top-level structure sniff + normalisation
|
|
94
|
+
# ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
def _confirm_object_conversion(path, yes=False):
|
|
97
|
+
"""
|
|
98
|
+
Warn the user that the top-level structure is a dict (not a list),
|
|
99
|
+
and ask whether to proceed by treating each top-level key as a column.
|
|
100
|
+
Returns True to proceed, False to abort.
|
|
101
|
+
When yes=True, auto-confirms without prompting (for non-interactive use).
|
|
102
|
+
"""
|
|
103
|
+
print(f"\n⚠️ Warning: '{path.name}' has a top-level object ({{...}}), not an array ([...]).")
|
|
104
|
+
print(" The tool will create a single-row CSV where each top-level key becomes a column.")
|
|
105
|
+
if yes:
|
|
106
|
+
print(" Auto-confirming (--yes flag set).")
|
|
107
|
+
return True
|
|
108
|
+
try:
|
|
109
|
+
answer = input(" Proceed? [y/N] ").strip().lower()
|
|
110
|
+
except EOFError:
|
|
111
|
+
answer = "n"
|
|
112
|
+
return answer in ("y", "yes")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def normalise_to_records(data, path, yes=False):
|
|
116
|
+
"""
|
|
117
|
+
Ensure data is a list of dicts.
|
|
118
|
+
- list → used directly
|
|
119
|
+
- dict → warn + confirm, then wrap as [data]
|
|
120
|
+
- other → error
|
|
121
|
+
When yes=True, dict top-level is auto-confirmed.
|
|
122
|
+
"""
|
|
123
|
+
if isinstance(data, list):
|
|
124
|
+
return data
|
|
125
|
+
if isinstance(data, dict):
|
|
126
|
+
if not _confirm_object_conversion(path, yes=yes):
|
|
127
|
+
print("❌ Conversion aborted by user.")
|
|
128
|
+
sys.exit(0)
|
|
129
|
+
return [data]
|
|
130
|
+
print(f"❌ Unsupported top-level type '{type(data).__name__}'. Expected a list or dict.")
|
|
131
|
+
sys.exit(1)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
# Writer
|
|
136
|
+
# ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
def write_csv(records, output_path):
|
|
139
|
+
"""Write a list of flat dicts to a CSV file."""
|
|
140
|
+
if not records:
|
|
141
|
+
print(f"⚠️ No records to write — creating empty CSV at {output_path}")
|
|
142
|
+
output_path.write_text("")
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
# Build a unified ordered fieldset (preserving first-seen order)
|
|
146
|
+
fieldnames = list(dict.fromkeys(k for r in records for k in r))
|
|
147
|
+
|
|
148
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
149
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")
|
|
150
|
+
writer.writeheader()
|
|
151
|
+
writer.writerows(records)
|
|
152
|
+
|
|
153
|
+
print(f"✅ Converted → {output_path} ({len(records)} row{'s' if len(records) != 1 else ''})")
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# ---------------------------------------------------------------------------
|
|
157
|
+
# Main conversion entry point
|
|
158
|
+
# ---------------------------------------------------------------------------
|
|
159
|
+
|
|
160
|
+
def convert(input_path_str, yes=False):
|
|
161
|
+
"""
|
|
162
|
+
Convert the given file to CSV.
|
|
163
|
+
Returns the output path (str), or the input path for .csv pass-through.
|
|
164
|
+
When yes=True, object top-level confirmation is auto-accepted.
|
|
165
|
+
"""
|
|
166
|
+
path = Path(input_path_str).resolve()
|
|
167
|
+
|
|
168
|
+
if not path.exists():
|
|
169
|
+
print(f"❌ File not found: {path}")
|
|
170
|
+
sys.exit(1)
|
|
171
|
+
|
|
172
|
+
ext = path.suffix.lower()
|
|
173
|
+
|
|
174
|
+
if ext not in SUPPORTED_EXTENSIONS:
|
|
175
|
+
print(f"❌ Unsupported file extension '{ext}'.")
|
|
176
|
+
print(f" Supported: {', '.join(sorted(SUPPORTED_EXTENSIONS))}")
|
|
177
|
+
sys.exit(1)
|
|
178
|
+
|
|
179
|
+
# Pass-through for CSV
|
|
180
|
+
if ext == ".csv":
|
|
181
|
+
print(f"✅ Input is already CSV — no conversion needed: {path}")
|
|
182
|
+
return str(path)
|
|
183
|
+
|
|
184
|
+
# Load data based on format
|
|
185
|
+
if ext == ".json":
|
|
186
|
+
data = load_json(path)
|
|
187
|
+
elif ext == ".jsonl":
|
|
188
|
+
data = load_jsonl(path)
|
|
189
|
+
# JSONL is already a list of records
|
|
190
|
+
records = flatten_records(normalise_to_records(data, path, yes=yes))
|
|
191
|
+
output_path = path.with_suffix(".csv")
|
|
192
|
+
write_csv(records, output_path)
|
|
193
|
+
return str(output_path)
|
|
194
|
+
elif ext in (".yaml", ".yml"):
|
|
195
|
+
data = load_yaml(path)
|
|
196
|
+
else:
|
|
197
|
+
print(f"❌ Extension '{ext}' reached conversion without a handler — this is a bug.")
|
|
198
|
+
sys.exit(1)
|
|
199
|
+
|
|
200
|
+
records = flatten_records(normalise_to_records(data, path, yes=yes))
|
|
201
|
+
output_path = path.with_suffix(".csv")
|
|
202
|
+
write_csv(records, output_path)
|
|
203
|
+
return str(output_path)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# ---------------------------------------------------------------------------
|
|
207
|
+
# CLI entry point
|
|
208
|
+
# ---------------------------------------------------------------------------
|
|
209
|
+
|
|
210
|
+
def main():
|
|
211
|
+
args = [a for a in sys.argv[1:] if a not in ("-h", "--help")]
|
|
212
|
+
help_requested = "-h" in sys.argv or "--help" in sys.argv
|
|
213
|
+
yes = "--yes" in args or "--no-confirm" in args
|
|
214
|
+
file_args = [a for a in args if not a.startswith("--")]
|
|
215
|
+
|
|
216
|
+
if help_requested or len(file_args) != 1:
|
|
217
|
+
print("Usage: python convert_cli.py <path-to-file> [--yes]")
|
|
218
|
+
print()
|
|
219
|
+
print("Supported formats: .json, .jsonl, .yaml, .yml, .csv")
|
|
220
|
+
print()
|
|
221
|
+
print("Options:")
|
|
222
|
+
print(" --yes, --no-confirm Auto-confirm object-to-CSV conversion (non-interactive)")
|
|
223
|
+
print()
|
|
224
|
+
print("Examples:")
|
|
225
|
+
print(" python convert_cli.py data/train.json")
|
|
226
|
+
print(" python convert_cli.py data/train.jsonl --yes")
|
|
227
|
+
print(" python convert_cli.py data/train.yaml")
|
|
228
|
+
print(" python convert_cli.py data/train.csv # pass-through")
|
|
229
|
+
sys.exit(0 if help_requested else 1)
|
|
230
|
+
|
|
231
|
+
convert(file_args[0], yes=yes)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
if __name__ == "__main__":
|
|
235
|
+
main()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
- id: 1
|
|
2
|
+
text: "The movie was great"
|
|
3
|
+
meta:
|
|
4
|
+
source: twitter
|
|
5
|
+
lang: en
|
|
6
|
+
label: positive
|
|
7
|
+
- id: 2
|
|
8
|
+
text: "Terrible experience"
|
|
9
|
+
meta:
|
|
10
|
+
source: reddit
|
|
11
|
+
lang: en
|
|
12
|
+
label: negative
|
|
13
|
+
- id: 3
|
|
14
|
+
text: "Pretty average overall"
|
|
15
|
+
meta:
|
|
16
|
+
source: twitter
|
|
17
|
+
lang: en
|
|
18
|
+
label: neutral
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deep-dive
|
|
3
|
+
description: >
|
|
4
|
+
Multi-phase investigation workflow. The scrum-master orchestrates information
|
|
5
|
+
gathering, interactive brainstorming, critical scrutiny, and solution assessment
|
|
6
|
+
to produce a refined, well-considered output document. Use when a request needs
|
|
7
|
+
thorough analysis before committing to a plan. Triggers on phrases like
|
|
8
|
+
"deep dive", "investigate thoroughly", "think this through properly",
|
|
9
|
+
"analyze this in depth", or "I want a thorough analysis of".
|
|
10
|
+
metadata:
|
|
11
|
+
prefered_agent: scrum_master
|
|
12
|
+
keywords:
|
|
13
|
+
- "deep dive"
|
|
14
|
+
- "investigate"
|
|
15
|
+
- "analyze thoroughly"
|
|
16
|
+
- "think through"
|
|
17
|
+
examples:
|
|
18
|
+
- "deep dive on this idea"
|
|
19
|
+
- "let's think through this properly"
|
|
20
|
+
- "I want a thorough analysis of this feature"
|
|
21
|
+
- "investigate this proposal in depth"
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# /deep-dive — Deep Investigation Workflow
|
|
25
|
+
|
|
26
|
+
## Overview
|
|
27
|
+
|
|
28
|
+
A multi-phase workflow that takes a user's request through structured investigation,
|
|
29
|
+
collaborative brainstorming, critical scrutiny, and optional solution assessment —
|
|
30
|
+
producing a refined, saved output document.
|
|
31
|
+
|
|
32
|
+
### Modes
|
|
33
|
+
|
|
34
|
+
| Mode | Pipeline | When to use |
|
|
35
|
+
|------|----------|-------------|
|
|
36
|
+
| `explore` | Info gathering → Brainstorm → Save | Idea is clear, just needs structure |
|
|
37
|
+
| `challenge` | + Scrutiny review → Amend → Save | Default — most requests |
|
|
38
|
+
| `resolve` | + Solution assessment → Amend → Save | Known problems need concrete solutions |
|
|
39
|
+
|
|
40
|
+
**Default mode: `challenge`**
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Instructions
|
|
45
|
+
|
|
46
|
+
### Step 1 — Receive the Request
|
|
47
|
+
|
|
48
|
+
Accept the user's mission, issue, or idea as the **request**. Note it clearly before proceeding.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
### Step 2 — Select Mode
|
|
53
|
+
|
|
54
|
+
If the user has not specified a mode, ask:
|
|
55
|
+
|
|
56
|
+
> "How deep should we go?"
|
|
57
|
+
> 1. **Explore** — Brainstorm only
|
|
58
|
+
> 2. **Challenge** — Brainstorm + critical scrutiny *(default)*
|
|
59
|
+
> 3. **Resolve** — Full pipeline with solution assessment
|
|
60
|
+
|
|
61
|
+
If the user is in a hurry or it's obvious from context, default to `challenge` without asking.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### Step 3 — Information Gathering (Judgment Call)
|
|
66
|
+
|
|
67
|
+
Before brainstorming, assess whether sufficient context exists to proceed productively.
|
|
68
|
+
|
|
69
|
+
- Check `project/documentation/examples/` for related prior work or descriptions
|
|
70
|
+
- Consider invoking `/examplify` if a concept in the request needs clarification
|
|
71
|
+
- Ask the user directly if a critical piece of context is missing
|
|
72
|
+
|
|
73
|
+
**Default: proceed.** Do not over-investigate. The brainstorm step will surface gaps naturally. Move on unless something fundamental is clearly missing.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### Step 4 — Interactive Brainstorm
|
|
78
|
+
|
|
79
|
+
Invoke `/brainstorm` with the request and any context gathered in Step 3.
|
|
80
|
+
|
|
81
|
+
This is an **interactive session** — the user participates actively. Ask focused questions,
|
|
82
|
+
challenge assumptions, and explore the design space together.
|
|
83
|
+
|
|
84
|
+
When the user signals they are satisfied with the brainstorm output, **capture the full brainstorm result** as the working document and proceed.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### Step 5 — Scrutiny Review (`challenge` and `resolve` modes)
|
|
89
|
+
|
|
90
|
+
Summon the `scrutiny-agent` (`agents/scrutiny-agent.md`) with the brainstorm output as input.
|
|
91
|
+
|
|
92
|
+
The scrutiny agent will:
|
|
93
|
+
- Produce a structured critical assessment (assumptions, key questions, risks, strengths)
|
|
94
|
+
- Save it to `./scrutiny-<slug>.md`
|
|
95
|
+
- Return the assessment to the scrum-master
|
|
96
|
+
|
|
97
|
+
**Escalation threshold is low.** After reading the scrutiny output, escalate to Step 6 if any of the following are true:
|
|
98
|
+
- Any risk is rated **Med** or **High** severity
|
|
99
|
+
- Any key question remains unanswered and is not trivial
|
|
100
|
+
- Any core assumption is directly challenged without a clear resolution
|
|
101
|
+
|
|
102
|
+
If none of the above apply and the mode is `challenge`, skip Step 6 and proceed to Step 7.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### Step 6 — Solution Assessment (`resolve` mode, or escalated from `challenge`)
|
|
107
|
+
|
|
108
|
+
Summon the `solution-assessor` (`agents/solution-assessor.md`) in **Mode B (chained)** —
|
|
109
|
+
pass the full scrutiny output as input.
|
|
110
|
+
|
|
111
|
+
The solution assessor will:
|
|
112
|
+
- Derive all problems from the scrutiny output
|
|
113
|
+
- Assess candidate solutions with effort, risk, and viability
|
|
114
|
+
- Save the assessment to `./solution-assessment-<slug>.md`
|
|
115
|
+
- Return the full assessment to the scrum-master
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### Step 7 — Amend the Brainstorm Output
|
|
120
|
+
|
|
121
|
+
The scrum-master **amends** the captured brainstorm document — does not replace it.
|
|
122
|
+
|
|
123
|
+
Append a `## 🔍 Deep Dive Synthesis` section at the end of the brainstorm document containing:
|
|
124
|
+
|
|
125
|
+
```markdown
|
|
126
|
+
## 🔍 Deep Dive Synthesis
|
|
127
|
+
|
|
128
|
+
### Scrutiny Findings
|
|
129
|
+
[Brief summary of critical concerns, key questions, and risks identified]
|
|
130
|
+
→ Full assessment: `./scrutiny-<slug>.md`
|
|
131
|
+
|
|
132
|
+
### Solution Paths *(if applicable)*
|
|
133
|
+
[Brief summary of recommended solution paths and estimated effort]
|
|
134
|
+
→ Full assessment: `./solution-assessment-<slug>.md`
|
|
135
|
+
|
|
136
|
+
### Open Decisions
|
|
137
|
+
[Any unresolved questions or choices the user must make before proceeding]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Keep each section **concise** — these are signposts to the full documents, not rewrites of them.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### Step 8 — Save Output
|
|
145
|
+
|
|
146
|
+
Determine the correct output directory based on content:
|
|
147
|
+
|
|
148
|
+
| Directory | When to use |
|
|
149
|
+
|-----------|-------------|
|
|
150
|
+
| `project/documentation/plans/` | Result can directly seed one or more Epics and/or Stories |
|
|
151
|
+
| `project/documentation/examples/` | Result is primarily descriptive or explanatory in nature |
|
|
152
|
+
| `project/documentation/summaries/` | Everything else |
|
|
153
|
+
|
|
154
|
+
Save the amended brainstorm document as `<slug>.md` in the chosen directory.
|
|
155
|
+
Also move any scrutiny/solution-assessment files from the working directory into the same directory for co-location.
|
|
156
|
+
|
|
157
|
+
Inform the user of all saved file paths.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
### Step 9 — Offer Next Steps
|
|
162
|
+
|
|
163
|
+
Ask the user:
|
|
164
|
+
|
|
165
|
+
> "Would you like to commit this to the board?"
|
|
166
|
+
> 1. **Yes** — proceed with `/todo` to create board items from the output
|
|
167
|
+
> 2. **No** — close the deep-dive session
|