一键导入
tree-sitter-tdd
Use when adding a new F# language feature to the tree-sitter parser with TDD workflow
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when adding a new F# language feature to the tree-sitter parser with TDD workflow
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | tree-sitter-tdd |
| description | Use when adding a new F# language feature to the tree-sitter parser with TDD workflow |
Use this skill when adding a new F# language feature to the tree-sitter parser. This skill automates the TDD workflow: write test first, get Fantomas AST, map to tree-sitter format, verify with user, and then strictly orchestrate multi-agent iteration—spawning per-test subagents for parse fixes until all test cases pass. Full green suite is mandatory.
Critical: This workflow loops—using delegated subagents—until ALL tests pass. Adding a feature may break existing tests; every breakage is isolated and fixed before success is declared.
ast_parser.fsx at project root must accept the code example as a command-line argument. If it does not, update the script before continuing. See Step 1 for the exact required change.The user provides:
test/corpus/type_defn.txt)After a new test is written and (expectedly) fails, use the following orchestration:
tree-sitter-parse-testing skill) to iterate on parser and grammar only for the failing example until it parses as required.
npx tree-sitter test or attempt to fix multiple cases. It is strictly one subagent per failing test.npx tree-sitter test).This coordination ensures robust TDD and protects against missed breakages elsewhere in the corpus. (See Step 7 for concrete mechanics.)
ALWAYS use the helper script .opencode/ast_parser.fsx in the repository to obtain the Fantomas AST for your F# code example.
If the script does not accept input as a command-line parameter, update it so that it sets the sample code from the command line argument instead of any hardcoded value.
let sample = ... with:
let sample = fsi.CommandLineArgs |> Seq.skip 1 |> String.concat " "
Then run:
dotnet fsi .opencode/ast_parser.fsx -- "<F# code example to test>"
This ensures that your code snippet is always parsed accurately for each test, avoids manual copy-paste errors, and standardizes the workflow.
Read the parser's src/grammar.json to get valid node names:
cat fsharp/src/grammar.json | jq '.rules | keys'
Convert Fantomas AST to tree-sitter lisp format:
(file
(declaration_expression
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier_or_op
(identifier))))
(const
(string)))))
Use these mappings (add as needed):
Let → declaration_expressionSynIdent → identifierConst → constantInt32 → integerString → stringIf you encounter a Fantomas AST node that doesn't map to any node in grammar.json:
question tool to ask user:header: "New node name"
question: "Found Fantomas node 'X' that doesn't map to grammar. What's the tree-sitter node name?"
options:
- label: "proposed_name"
description: "Use proposed name based on F# spec"
- label: "custom"
description: "Enter custom name"
Show the user the expected parse tree and ask for verification:
header: "Verify parse tree"
question: "Does this parse tree look correct?"
options:
- label: "Yes, add test"
description: "Proceed to add test to corpus"
- label: "No, fix mapping"
description: "Revise node mappings"
Add the test to the specified corpus file:
================================================================================
test-name
================================================================================
<user's F# code>
--------------------------------------------------------------------------------
(expected parse tree)
npx tree-sitter test
IMPORTANT: Adding a new feature may break existing tests. You MUST loop until every test passes. ALL fixes should follow multi-agent TDD:
tree-sitter-parse-testing skill) assigned to that single failing case. The subagent iterates on grammar/debugging until that test parses as expected (no ERROR nodes).npx tree-sitter test
This executes the full test suite.tree-sitter-parse-testing, providing the specific code and expected tree).digraph tdd_multiagent {
"Add/confirm new failing test"
-> "Spawn subagent (parse-testing, failing case)"
-> "Subagent: Fix until passes"
-> "Agent: Run npx tree-sitter test"
-> "Any failing tests?"
-> "Yes" -> "Spawn subagent (one/test); fixing that case"
-> "Repeat: run all tests"
-> "No" -> "DONE: all tests pass!"
}
| Action | Agent/Skill | Description |
|---|---|---|
| Add test | Main agent | Write new corpus case, confirm it fails |
| Debug/fixone | Subagent (tree-sitter-parse-testing) | Fix parsing for that individual test |
| Test suite | Main agent | npx tree-sitter test - check all cases |
| Handle fail | Main agent | Spawn subagents per failing test, loop until green |
Confirm all tests pass and the new feature parses correctly.
ast_parser.fsx. This eliminates discrepancies between test and AST.NO CASES LEFT FAILING: Never declare the feature/fix complete until the main agent runs the FULL test suite and every single test is green. ALWAYS use per-case subagents for debugging, never batch fix. Any attempt to declare partial results "done" is a violation of TDD discipline and must be explicitly rejected.
After running npx tree-sitter test, you MUST automatically and robustly parse all CLI output to:
Sample npx tree-sitter test Output
Passing case:
✓ simple string
test/corpus/constants.txt
Failing case:
✗ simple string
test/corpus/constants.txt
--- Expected
+++ Actual
...
(tree diff here)
Summary example:
60/61 tests passed (1 failing)
Infinite loop/truncation warning (edge case CLI output):
Killed
<no summary>
for each line in output:
if line.startswith('✓ '):
# Passed test, extract name (optional, mostly for reporting)
mark_test_passed(test_name)
elif line.startswith('✗ '):
# Failing test, extract name
failing_tests.append(test_name)
if 'Killed' in output or 'timed out' in output:
handle_infinite_loop_or_crash()
if summary_line_reports_failures:
for test in failing_tests:
spawn_agent_for_failure(test)
else:
declare_suite_green()
================================================================================
nullable type
================================================================================
let x: int? = 1
--------------------------------------------------------------------------------
(file
(declaration_expression
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier_or_op
(identifier))))
(type
(nullable_type
(type)))
(const
(integer)))))
.fs / .fsx files → use fsharp/ parser.fsi files → use fsharp_signature/ parser| Command | Description |
|---|---|
npx tree-sitter test | Run all tests |
cd fsharp && npx tree-sitter generate | Regenerate parser after grammar changes |
echo 'code' | npx tree-sitter parse | Parse code snippet |
echo 'code' | npx tree-sitter parse -d | Debug parse (see tree-sitter-parse-testing) |
Workflow Recap: