بنقرة واحدة
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: