Add GateFlow terminal console and release checks#8
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bae136f0f6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| payload = build_payload(root) | ||
|
|
||
| def wrapped(stdscr) -> None: | ||
| curses.curs_set(0) |
There was a problem hiding this comment.
Guard cursor hide call for unsupported terminals
The interactive path calls curses.curs_set(0) unconditionally, which raises _curses.error on terminals that do not support cursor visibility changes; in that case /gf-tui exits before rendering any UI. This makes the new interactive console unusable in a non-trivial set of environments (including minimal/remote TTYs), so this should be wrapped in a safe fallback (e.g., try/except curses.error) instead of hard-failing.
Useful? React with 👍 / 👎.
| root = root.resolve() | ||
| validator = _load_validator() | ||
| inventory = validator.discover_inventory(root) | ||
| release = validator.run_checks(root, expected_version="2.5.0") |
There was a problem hiding this comment.
Remove hardcoded release version from TUI health check
The release health status is computed with a fixed expected version (2.5.0), so after the next version bump the TUI will report release errors even when manifests/docs are correctly synchronized to the new version. Because this value is baked into runtime behavior, the dashboard becomes misleading until code is manually edited for every release; it should derive the expected version from plugin.json (or accept it as an argument).
Useful? React with 👍 / 👎.
| --- | ||
| name: gf-tui | ||
| description: > | ||
| GateFlow terminal console inspired by OpenClaw local TUI workflows. Shows | ||
| workspace status, component inventory, tool health, map readiness, release | ||
| readiness, and command shortcuts from one terminal surface. | ||
| user-invocable: true | ||
| triggers: | ||
| - open GateFlow TUI | ||
| - show GateFlow dashboard | ||
| - terminal console | ||
| - CLI TUI | ||
| - OpenClaw-style TUI | ||
| --- | ||
| allowed-tools: | ||
| - Bash | ||
| - Read | ||
|
|
||
| # GF-TUI -- Terminal Console | ||
|
|
There was a problem hiding this comment.
🟠 High gf-tui/SKILL.md:1
The allowed-tools block on lines 15–17 is placed after the closing --- frontmatter delimiter on line 14, so it renders as Markdown text instead of being parsed as YAML metadata. This causes the skill to not declare its required tool permissions (Bash, Read), which may lead to runtime tool denials or unexpected fallback behavior. Move the allowed-tools: key and its list items above line 14, inside the frontmatter block.
+---
+name: gf-tui
+description: >
+ GateFlow terminal console inspired by OpenClaw local TUI workflows. Shows
+ workspace status, component inventory, tool health, map readiness, release
+ readiness, and command shortcuts from one terminal surface.
+user-invocable: true
+triggers:
+ - open GateFlow TUI
+ - show GateFlow dashboard
+ - terminal console
+ - CLI TUI
+ - OpenClaw-style TUI
+allowed-tools:
+ - Bash
+ - Read
+---
+
+# GF-TUI -- Terminal Console🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file plugins/gateflow/skills/gf-tui/SKILL.md around lines 1-20:
The `allowed-tools` block on lines 15–17 is placed after the closing `---` frontmatter delimiter on line 14, so it renders as Markdown text instead of being parsed as YAML metadata. This causes the skill to not declare its required tool permissions (`Bash`, `Read`), which may lead to runtime tool denials or unexpected fallback behavior. Move the `allowed-tools:` key and its list items above line 14, inside the frontmatter block.
| # GateFlow | ||
|
|
||
| **The open-source AI hardware platform.** Design, verify, synthesize, and deploy working RTL from natural language. 20 agents. 25 skills. 8 verified IP blocks. One command. | ||
| **The open-source AI hardware platform.** Design, verify, synthesize, release, and deploy working RTL from natural language. 20 agents. 27 skills. 21 commands. 8 verified IP blocks. |
There was a problem hiding this comment.
🟡 Medium gateflow/README.md:3
The header claims 27 skills (line 3) and 27 Skills (line 69), but the table only lists 25 comma-separated skill items (4+3+4+3+4+2+1+1+1+2=25). The count overstates by 2. Consider updating the header and section title to 25 skills / 25 Skills to match the actual table contents.
| **The open-source AI hardware platform.** Design, verify, synthesize, release, and deploy working RTL from natural language. 20 agents. 27 skills. 21 commands. 8 verified IP blocks. | |
| **The open-source AI hardware platform.** Design, verify, synthesize, release, and deploy working RTL from natural language. 20 agents. 25 skills. 21 commands. 8 verified IP blocks. |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file plugins/gateflow/README.md around line 3:
The header claims **27 skills** (line 3) and **27 Skills** (line 69), but the table only lists 25 comma-separated skill items (4+3+4+3+4+2+1+1+1+2=25). The count overstates by 2. Consider updating the header and section title to **25 skills** / **25 Skills** to match the actual table contents.
| def run_interactive(root: Path) -> int: | ||
| payload = build_payload(root) | ||
|
|
||
| def wrapped(stdscr) -> None: | ||
| curses.curs_set(0) |
There was a problem hiding this comment.
🟠 High tools/gateflow_tui.py:203
_draw calls curses.init_pair(..., -1) to use the terminal's default background color, but curses.use_default_colors() is never called first. This causes init_pair() to throw curses.error on terminals where the default color mechanism isn't initialized. Consider calling curses.use_default_colors() at the start of wrapped() before invoking _draw.
def run_interactive(root: Path) -> int:
payload = build_payload(root)
def wrapped(stdscr) -> int:
+ curses.use_default_colors()
curses.curs_set(0)
stdscr.keypad(True)🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file tools/gateflow_tui.py around lines 203-207:
`_draw` calls `curses.init_pair(..., -1)` to use the terminal's default background color, but `curses.use_default_colors()` is never called first. This causes `init_pair()` to throw `curses.error` on terminals where the default color mechanism isn't initialized. Consider calling `curses.use_default_colors()` at the start of `wrapped()` before invoking `_draw`.
Evidence trail:
tools/gateflow_tui.py lines 156-159: `curses.init_pair` called with `-1` background. tools/gateflow_tui.py line 206-227: `wrapped` function and `curses.wrapper(wrapped)` call. git_grep for `use_default_colors` in tools/gateflow_tui.py returned no results. Python docs: https://docs.python.org/3/library/curses.html#curses.use_default_colors confirms `-1` requires `use_default_colors()`.
| def discover_inventory(root: Path) -> Inventory: | ||
| plugin = root / "plugins" / "gateflow" | ||
| agents = sorted(path.stem for path in (plugin / "agents").glob("*.md")) | ||
| skills = sorted(path.parent.name for path in (plugin / "skills").glob("*/SKILL.md")) | ||
| commands = sorted(path.stem for path in (plugin / "commands").glob("*.md")) | ||
| ip_blocks = sorted(path.name for path in (plugin / "ip").iterdir() if path.is_dir()) | ||
| boards = sorted(path.name for path in (plugin / "boards").iterdir() if path.is_dir()) | ||
| return Inventory(agents, skills, commands, ip_blocks, boards) |
There was a problem hiding this comment.
🟢 Low tools/validate_gateflow.py:28
discover_inventory crashes with FileNotFoundError when any plugin subdirectory (agents, skills, commands, ip, or boards) is missing. Both glob() and iterdir() throw when their target directory doesn't exist. Unlike _read_json which appends to an errors list, this function has no error handling and run_checks doesn't catch exceptions. A validation tool should report missing directories as validation errors rather than terminating.
def discover_inventory(root: Path) -> Inventory:
plugin = root / "plugins" / "gateflow"
- agents = sorted(path.stem for path in (plugin / "agents").glob("*.md"))
- skills = sorted(path.parent.name for path in (plugin / "skills").glob("*/SKILL.md"))
- commands = sorted(path.stem for path in (plugin / "commands").glob("*.md"))
- ip_blocks = sorted(path.name for path in (plugin / "ip").iterdir() if path.is_dir())
- boards = sorted(path.name for path in (plugin / "boards").iterdir() if path.is_dir())
+ agents = sorted(path.stem for path in (plugin / "agents").glob("*.md")) if (plugin / "agents").exists() else []
+ skills = sorted(path.parent.name for path in (plugin / "skills").glob("*/SKILL.md")) if (plugin / "skills").exists() else []
+ commands = sorted(path.stem for path in (plugin / "commands").glob("*.md")) if (plugin / "commands").exists() else []
+ ip_blocks = sorted(path.name for path in (plugin / "ip").iterdir() if path.is_dir()) if (plugin / "ip").exists() else []
+ boards = sorted(path.name for path in (plugin / "boards").iterdir() if path.is_dir()) if (plugin / "boards").exists() else []
return Inventory(agents, skills, commands, ip_blocks, boards)Also found in 1 other location(s)
tools/gateflow_tui.py:27
importlib.util.spec_from_file_locationreturnsNoneif the file doesn't exist or cannot be loaded. Whenvalidate_gateflow.pyis missing,specwill beNone, andimportlib.util.module_from_spec(spec)will raise a confusingTypeError(orAttributeErroronspec.loader). The code should check ifspec is Nonebefore proceeding.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file tools/validate_gateflow.py around lines 28-35:
`discover_inventory` crashes with `FileNotFoundError` when any plugin subdirectory (`agents`, `skills`, `commands`, `ip`, or `boards`) is missing. Both `glob()` and `iterdir()` throw when their target directory doesn't exist. Unlike `_read_json` which appends to an errors list, this function has no error handling and `run_checks` doesn't catch exceptions. A validation tool should report missing directories as validation errors rather than terminating.
Evidence trail:
tools/validate_gateflow.py lines 28-35 (discover_inventory with no error handling), lines 33-34 (iterdir() calls), lines 135-145 (run_checks with no try/except around discover_inventory), lines 38-46 (_read_json with FileNotFoundError handling). Python docs: Path.iterdir() raises OSError/FileNotFoundError on non-existent directories (https://docs.python.org/3/library/pathlib.html#pathlib.Path.iterdir). Python 3.13 changelog: 'In previous versions, such exceptions [from glob] are suppressed in many cases, but not all.'
Also found in 1 other location(s):
- tools/gateflow_tui.py:27 -- `importlib.util.spec_from_file_location` returns `None` if the file doesn't exist or cannot be loaded. When `validate_gateflow.py` is missing, `spec` will be `None`, and `importlib.util.module_from_spec(spec)` will raise a confusing `TypeError` (or `AttributeError` on `spec.loader`). The code should check if `spec is None` before proceeding.
Summary
/gf-tuiplustools/gateflow_tui.pyfor an OpenClaw-style local terminal console with interactive, snapshot, and JSON modes./gf-releaseplustools/validate_gateflow.pyfor release-readiness validation.2.5.0, refresh release notes, docs index, README counts, and complete root mirrors.Verification
python3 -m unittestpython3 tools/validate_gateflow.py --version 2.5.0python3 tools/gateflow_tui.py --snapshot --plainpython3 tools/gateflow_tui.py --jsongit diff --checkNote
Add
/gf-tuiterminal console and/gf-releasevalidation commands to GateFlow plugintools/gateflow_tui.py, a CLI terminal console with--json,--snapshot, and interactive curses modes that renders GateFlow inventory and available actions.tools/validate_gateflow.py, a release-readiness validator that checks manifest versions, README counts, symlink mirrors, and release notes, exiting non-zero on failures./gf-tuiand/gf-releaseas commands and skills with corresponding docs inplugins/gateflow/commands/andplugins/gateflow/skills/.tests/test_gateflow_tui.pyandtests/test_validate_gateflow.pycovering snapshot output, JSON payload structure, and inventory counts.plugin.jsonandmarketplace.jsonand adds root-level symlinks for new agents and skills.📊 Macroscope summarized bae136f. 17 files reviewed, 7 issues evaluated, 1 issue filtered, 4 comments posted
🗂️ Filtered Issues
tools/gateflow_tui.py — 1 comment posted, 4 evaluated, 1 filtered
importlib.util.spec_from_file_locationreturnsNoneif the file doesn't exist or cannot be loaded. Whenvalidate_gateflow.pyis missing,specwill beNone, andimportlib.util.module_from_spec(spec)will raise a confusingTypeError(orAttributeErroronspec.loader). The code should check ifspec is Nonebefore proceeding. [ Cross-file consolidated ]