Add GSP links field and link inspection

This commit is contained in:
2026-05-07 10:41:38 +08:00
parent 0c5254eb1b
commit 27e71d8c51
18 changed files with 448 additions and 17 deletions

View File

@@ -12,6 +12,7 @@ $script:GspSubcommands = @(
'trace',
'flatten',
'pack',
'links',
'impact',
'message',
'graph',
@@ -29,6 +30,7 @@ $script:GspFlags = @{
'trace' = @('--root', '--depth', '--out')
'flatten' = @('--root', '--depth', '--include-type', '--exclude-type', '--out')
'pack' = @('--root', '--for', '--stage', '--depth', '--budget', '--format', '--include-type', '--exclude-type', '--out')
'links' = @('--root', '--depth', '--format', '--out')
'impact' = @('--root', '--depth', '--format', '--out')
'message' = @('validate')
'graph' = @('--root', '--depth', '--format', '--out')
@@ -80,6 +82,8 @@ Register-ArgumentCompleter -Native -CommandName gsp -ScriptBlock {
$formats = @('json', 'md', 'canvas')
if ($command -eq 'graph') {
$formats = @('json', 'mermaid', 'md', 'canvas')
} elseif ($command -eq 'links') {
$formats = @('json', 'md')
}
return $formats |
Where-Object { $_ -like "$wordToComplete*" } |
@@ -125,7 +129,7 @@ Register-ArgumentCompleter -Native -CommandName gsp -ScriptBlock {
ForEach-Object { New-GspCompletion $_ }
}
if (@('trace', 'flatten', 'pack', 'impact', 'graph') -contains $command) {
if (@('trace', 'flatten', 'pack', 'links', 'impact', 'graph') -contains $command) {
return Get-GspIds |
Where-Object { $_ -like "$wordToComplete*" } |
ForEach-Object { New-GspCompletion $_ }
@@ -144,11 +148,13 @@ _gsp_completion() {
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
cmd="${COMP_WORDS[1]}"
local commands="init ai-init version completion validate index trace flatten pack impact message graph stage-check help"
local commands="init ai-init version completion validate index trace flatten pack links impact message graph stage-check help"
case "$prev" in
--format)
if [[ "$cmd" == "graph" ]]; then
COMPREPLY=( $(compgen -W "json mermaid md canvas" -- "$cur") )
elif [[ "$cmd" == "links" ]]; then
COMPREPLY=( $(compgen -W "json md" -- "$cur") )
else
COMPREPLY=( $(compgen -W "json md canvas" -- "$cur") )
fi
@@ -171,6 +177,7 @@ _gsp_completion() {
trace) COMPREPLY=( $(compgen -W "--root --depth --out" -- "$cur") ) ;;
flatten) COMPREPLY=( $(compgen -W "--root --depth --include-type --exclude-type --out" -- "$cur") ) ;;
pack) COMPREPLY=( $(compgen -W "--root --for --stage --depth --budget --format --include-type --exclude-type --out" -- "$cur") ) ;;
links) COMPREPLY=( $(compgen -W "--root --depth --format --out" -- "$cur") ) ;;
impact) COMPREPLY=( $(compgen -W "--root --depth --format --out" -- "$cur") ) ;;
message) COMPREPLY=( $(compgen -W "validate" -- "$cur") ) ;;
graph) COMPREPLY=( $(compgen -W "--root --depth --format --out" -- "$cur") ) ;;
@@ -180,7 +187,7 @@ _gsp_completion() {
return
fi
case "$cmd" in
trace|flatten|pack|impact|graph)
trace|flatten|pack|links|impact|graph)
local ids
ids=$(gsp index --root . 2>/dev/null | sed -n 's/.*"id": "\([^"]*\)".*/\1/p')
COMPREPLY=( $(compgen -W "$ids" -- "$cur") )
@@ -206,6 +213,7 @@ _gsp() {
'trace'
'flatten'
'pack'
'links'
'impact'
'message'
'graph'
@@ -220,12 +228,13 @@ _gsp "$@"
func fishCompletionScript() string {
return `# GSP fish completion
complete -c gsp -f -n '__fish_use_subcommand' -a 'init ai-init version completion validate index trace flatten pack impact message graph stage-check help'
complete -c gsp -f -n '__fish_use_subcommand' -a 'init ai-init version completion validate index trace flatten pack links impact message graph stage-check help'
complete -c gsp -n '__fish_seen_subcommand_from graph' -l format -a 'json mermaid md canvas'
complete -c gsp -n '__fish_seen_subcommand_from pack impact' -l format -a 'json md canvas'
complete -c gsp -n '__fish_seen_subcommand_from links' -l format -a 'json md'
complete -c gsp -n '__fish_seen_subcommand_from stage-check' -l stage -a 'design integrate implement bind release'
complete -c gsp -n '__fish_seen_subcommand_from ai-init' -l skill -a 'generic codex'
complete -c gsp -n '__fish_seen_subcommand_from pack' -l for -a 'design implement review test acceptance handoff inspect'
complete -c gsp -n '__fish_seen_subcommand_from trace flatten pack impact graph' -a '(gsp index --root . 2>/dev/null | string match -r ''"id": "([^"]+)"'' | string replace -r ''.*"id": "([^"]+)".*'' ''$1'')'
complete -c gsp -n '__fish_seen_subcommand_from trace flatten pack links impact graph' -a '(gsp index --root . 2>/dev/null | string match -r ''"id": "([^"]+)"'' | string replace -r ''.*"id": "([^"]+)".*'' ''$1'')'
`
}

View File

@@ -48,6 +48,8 @@ func run(args []string) error {
return runFlatten(args[1:])
case "pack":
return runPack(args[1:])
case "links":
return runLinks(args[1:])
case "impact":
return runImpact(args[1:])
case "message":
@@ -78,6 +80,7 @@ Usage:
gsp trace <id> [--root .] [--depth 3] [--out trace.json]
gsp flatten <id> [--root .] [--depth 3] [--include-type a,b] [--exclude-type a,b] [--out flattened.json]
gsp pack <id> [--root .] [--for implement] [--stage implement] [--depth 3] [--budget 12000] [--format json|md|canvas] [--out context-pack.json]
gsp links <id> [--root .] [--depth -1] [--format json|md] [--out links.json]
gsp impact <id> [--root .] [--depth -1] [--format json|md|canvas] [--out impact.json]
gsp message validate <file> [--root .] [--out message-report.json]
gsp graph [id] [--root .] [--depth 3] [--format json|mermaid|md|canvas] [--out graph.json]
@@ -85,6 +88,33 @@ Usage:
`)
}
func runLinks(args []string) error {
fs := flag.NewFlagSet("links", flag.ContinueOnError)
root := commonRoot(fs)
out := commonOut(fs)
depth := fs.Int("depth", -1, "maximum relation depth; -1 means unlimited")
format := fs.String("format", "json", "json or md")
if err := fs.Parse(normalizeFlagArgs(args)); err != nil {
return err
}
if fs.NArg() != 1 {
return fmt.Errorf("links requires one GSP id")
}
project, err := gsp.LoadProject(*root)
if err != nil {
return err
}
result := project.Links(fs.Arg(0), *depth)
switch *format {
case "json":
return writeJSON(*out, result)
case "md":
return writeText(*out, result.Markdown())
default:
return fmt.Errorf("unsupported links format %q", *format)
}
}
func runCompletion(args []string) error {
if len(args) == 0 {
return fmt.Errorf("completion requires powershell, bash, zsh, fish, or install powershell")