15 KiB
GitLink CLI Workflow Agent Design
Background
gitlink-cli already provides low-level and shortcut operations for GitLink repositories,
issues, pull requests, releases, CI, organizations, search, and users.
The repository also includes skills/gitlink-workflow/SKILL.md, which describes
AI workflow patterns such as Issue triage, PR review, and Release Notes generation.
The current Go command tree did not include a workflow command group before this work.
The competition PR turns the documented workflow concept into concrete,
deterministic CLI commands that can be used by human maintainers and AI Agents
without calling an external LLM.
Goals
First PR:
- Add
gitlink-cli workflow +triage. - Add
gitlink-cli workflow +health. - Keep write behavior dry-run by default.
- Produce stable JSON for Agents.
- Produce concise table output for terminal users.
- Produce markdown output for reports, PR comments, Issue comments, and competition materials.
- Support
--lang enand--lang zh-CNwith a lightweight message helper.
Additional workflow commands:
workflow +pr-summary: doneworkflow +repo-report: doneworkflow +release-notes: doneworkflow +stale: planned
Current implementation status:
- Rule engine: done
- Local command layer: done
- API fetch layer: done
- Boundary tests: expanded for empty responses, field normalization, unknown tolerance, and read-only error handling
- PR summary command: done with local JSON input, read-only fetch, rules, renderers, and tests
- Repo report command: done with local JSON input, partial read-only fetch aggregation, scoring, renderers, and tests
- Release notes command: done with local JSON input, read-only compare fetch, deterministic section classification, renderers, and tests
Current Repository Findings
Command registration:
cmd/root.goregisters global flags and callsshortcuts.RegisterAll(rootCmd).shortcuts/register.gomaps command groups to shortcut slices.- Each group exposes
Shortcuts() []*common.Shortcut. common.MountShortcutmaps aShortcutinto a Cobra command named+<name>.
Runtime and API calls:
common.NewRuntimeContextcreatesclient.Client, carries owner, repo, format, and command args.ctx.ResolveOwnerRepo()resolves--owner/--repoor Git remote context.ctx.CallAPIandctx.CallAPIWithQuerycallinternal/client.client.Doappends.json, injects auth via transport, parses GitLink error-in-body responses, and returnsoutput.Envelope.
Output:
internal/outputcurrently supportsjson,yaml, and generictable.- Workflow requires
markdown; the minimal-risk approach is a workflow-local renderer that prints stable workflow DTOs. - A later cleanup can promote markdown support into
internal/outputif multiple command groups need it. - Current workflow commands also expose workflow-local
json,table, andmarkdownrendering without changing the global formatter.
Testing:
- Existing tests use pure unit tests plus
httptest.Server. - Shortcut tests instantiate
common.RuntimeContextmanually with a mockedclient.Client. - This pattern should be reused for workflow API tests.
Command Design
workflow +triage
Examples:
gitlink-cli workflow +triage --owner Gitlink --repo gitlink-cli --state open --limit 30 --dry-run --format json
gitlink-cli workflow +triage --owner Gitlink --repo gitlink-cli --state open --limit 30 --format table
gitlink-cli workflow +triage --owner Gitlink --repo gitlink-cli --state open --limit 30 --lang zh-CN --format markdown
Flags:
--state: defaultopen--limit: default30--page: default1--dry-run: defaulttrue--from: optional local JSON input--title,--body,--number,--author,--url,--labels: optional local single-issue input--lang: defaulten, alloweden,zh-CN
Stable JSON item fields:
issue_idnumbertitleurlauthorstatecreated_atupdated_atdetected_typepriorityconfidencesuggested_labelsmissing_informationrisk_flagsrecommended_actionsuggested_commentreasoning
Rule categories:
bugfeaturequestiondocscisecurityperformancerefactorunknown
Priority:
P0: security incident, secret/token leak, auth bypass, repository unusableP1: core command unusable, install/login failure, CI/release blockerP2: normal bug, important feature, missing docs blocking usageP3: ordinary question, typo, minor improvement
Missing information for bug-like issues:
- reproduction steps
- expected behavior
- actual behavior
- version
- OS / platform
- command output
- logs
workflow +health
Examples:
gitlink-cli workflow +health --owner Gitlink --repo gitlink-cli --format json
gitlink-cli workflow +health --owner Gitlink --repo gitlink-cli --format table
gitlink-cli workflow +health --owner Gitlink --repo gitlink-cli --lang zh-CN --format markdown
Flags:
--stale-days: default30--from: optional local JSON input- local metric flags such as
--repository,--open-issues,--open-prs,--has-readme,--has-license, and--agent-readiness-score --lang: defaulten
Stable JSON fields:
repositoryopen_issuesopen_prsstale_issuesstale_prsrecent_activityrelease_statusci_statusdocumentation_statuslicense_statuscontribution_statusagent_readiness_scorehealth_scorerisk_levelrecommendationsscoring_notes
Scoring:
- Issue backlog and response: 20
- PR backlog and merge state: 20
- Recent activity: 15
- Release status: 15
- Documentation completeness: 10
- License and contribution readiness: 10
- Agent readiness: 10
Unknown metric policy:
- Keep field present.
- Set status or score detail to
unknown. - Add one entry to
scoring_notes. - Either omit the metric from denominator or apply a conservative partial score; the first PR should prefer denominator adjustment to avoid fake precision.
Risk levels:
low: 80-100medium: 60-79high: 40-59critical: 0-39
Architecture
Proposed files:
shortcuts/workflow/
workflow.go # Shortcuts() and command wiring
types.go # Stable DTOs
triage_rules.go # pure classifier, scoring, missing info detection
triage_fetch.go # GitLink issue fetching and response normalization
triage_render.go # json/table/markdown workflow rendering if needed
health_score.go # pure health scoring
health_fetch.go # repo, issue, PR, release, CI/doc/license probes
health_render.go # markdown/table rendering
messages.go # en and zh-CN strings
*_test.go
Registration:
- Add
workflowimport inshortcuts/register.go. - Add
"workflow": workflow.Shortcuts()togroups. - Add description
"AI agent workflow analysis".
No new dependency is needed for this PR.
Data Normalization
GitLink responses vary by endpoint. Workflow code should not depend on a single raw shape. Add small extraction helpers:
stringField(map, keys...)numberField(map, keys...)timeField(map, keys...)sliceField(map, keys...)extractItems(env, candidateKeys...)
Candidate issue list keys:
issuesdata- direct array after future client improvements
Candidate issue fields:
- ID:
id,issue_id - Number:
project_issues_index,number,index,id - Title:
subject,title - Body:
description,body - Author:
author.login,user.login,login - URL:
html_url,url,issue_url
Health activity fields currently tolerated:
updated_atupdatedAtlast_updated_atlastUpdatedAtlast_activity_atlastActivityAtmerged_atmergedAtclosed_atclosedAt
Safety Strategy
+triageonly reads by default.--dry-rundefaults true.- A future explicit write flag for posting comments must require
--dry-run=falsein a later PR. - Generated comments are output as data, not posted remotely in the first PR.
- Health checks never mutate remote state.
- If an API probe fails, health continues with
unknown. - The implemented prototype is local-first and has no LLM dependency.
- Remote fetch mode remains read-only and does not post comments, labels, merges, or close actions.
- API failures should fall back to
unknownmetrics or a clear fetch error instead of fabricating healthy data.
Core Pseudocode
Triage
issues := fetchIssues(owner, repo, state, limit, page)
results := []TriageResult{}
for _, issue := range issues {
text := normalize(issue.Title + "\n" + issue.Body)
scores := scoreKeywords(text, keywordRules)
detectedType := maxScoreType(scores)
priority := scorePriority(text, detectedType)
missing := detectMissingInfo(issue, detectedType)
confidence := confidenceFromScores(scores, missing)
result := TriageResult{
IssueID: issue.ID,
Number: issue.Number,
DetectedType: detectedType,
Priority: priority,
SuggestedLabels: labelsFor(detectedType, priority, riskFlags),
MissingInformation: missing,
RiskFlags: detectRiskFlags(text),
RecommendedAction: actionFor(detectedType, priority, missing, lang),
SuggestedComment: commentFor(missing, lang),
Reasoning: explainTopMatches(scores, priorityRules),
}
results = append(results, result)
}
render(results, format, lang)
Health
signals := collectHealthSignals(owner, repo)
score := NewWeightedScore(100)
score.Add("issues", 20, scoreIssueBacklog(signals.OpenIssues, signals.StaleIssues))
score.Add("prs", 20, scorePRBacklog(signals.OpenPRs, signals.StalePRs))
score.Add("activity", 15, scoreRecentActivity(signals.RecentActivity))
score.Add("release", 15, scoreReleaseStatus(signals.ReleaseStatus))
score.Add("docs", 10, scoreDocStatus(signals.DocumentationStatus))
score.Add("license", 10, scoreLicenseContribution(signals.LicenseStatus, signals.ContributionStatus))
score.Add("agent", 10, scoreAgentReadiness(signals))
result := HealthResult{
HealthScore: score.Percent(),
RiskLevel: riskLevel(score.Percent()),
Recommendations: recommendations(signals, score),
ScoringNotes: score.Notes(),
}
render(result, format, lang)
Output Protocol
JSON:
- Use stable struct tags.
- Include empty arrays as
[]where useful for Agent consumption. - Avoid prose outside JSON.
Table:
- Triage columns:
NUMBER,TYPE,PRIORITY,CONFIDENCE,MISSING,ACTION - Health rows:
METRIC,STATUS,SCORE,NOTE
Markdown:
- Triage: one summary table with type, priority, confidence, action, and missing information.
- Health: repository score, metric table, recommendations, and scoring notes.
zh-CNchanges rule messages and recommendation text, not JSON field names.
Test Plan
Unit tests:
- Issue type classification.
- Priority scoring.
- Missing information detection.
- Risk flag detection.
- Suggested comment generation.
- Health weighted score and risk level.
- Unknown metric denominator adjustment.
- Markdown headings and required sections.
Mock API tests:
workflow +triagefetches issues and normalizes raw response.workflow +healthtolerates failing CI/release/doc probes.
Command tests:
--dry-rundefaults to true.--lang zh-CNaccepted.- invalid
--langfalls back toen. --format markdownroutes to markdown renderer.
Later Extensions
workflow +pr-summary
Inputs:
--number--from--lang--format- optional
--include-files - optional
--include-commits - optional
--max-files - optional
--max-commits
Default format:
tablefor human review when--formatis omitted
Data:
- PR details
- changed files
- commits
Output:
change_typerisk_levelreview_focustest_suggestionsmerge_checklistreasoning
Implementation status:
- read-only local JSON mode: done
- read-only GitLink fetch mode: done
- rules and renderers: done
- tests: rules, fetch boundary, render, and command wiring
Safety:
- no comments
- no approve/reject
- no merge
- no remote write operation
workflow +repo-report
Inputs:
--owner--repo--from--lang--format- optional
--issue-limit - optional
--pr-limit - optional
--stale-days - optional
--include-issues - optional
--include-prs - optional
--include-health
Default format:
markdownfor maintainer and competition reports when--formatis omitted
Data:
- repository health input and score
- issue triage results aggregated by type, priority, risk, and missing information
- PR summary results aggregated by type, risk, and review focus
Output:
report_scorerisk_levelhealthissue_summarypr_summaryrecommendationsreasoning
Partial report strategy:
- health, issue, and PR sections are fetched independently
- if at least one enabled section succeeds, the command returns a partial report
- failed sections are recorded in scoring notes or reasoning
- PR remote aggregation currently uses PR list metadata only;
detailed changed files and commits remain available through
workflow +pr-summary --number
Safety:
- read-only aggregation only
- no comments, labels, closes, approve/reject, or merge operations
- no LLM dependency
workflow +release-notes
Inputs:
--from--from-ref--to-ref- optional
--version - optional
--max-commits - optional
--include-prs - optional
--lang
Data:
- PR titles
- commit messages
- changed file paths when present in compare data
Markdown categories:
- Breaking Changes
- Features
- Bug Fixes
- Documentation
- Tests
- Refactoring
- Chores
Examples:
gitlink-cli workflow +release-notes --from shortcuts/workflow/testdata/release_notes.json --format markdown
gitlink-cli workflow +release-notes --owner Gitlink --repo gitlink-cli --from-ref v0.1.0 --to-ref master --version v0.2.0 --format json
Behavior:
- Use local JSON input when
--fromis set. - In remote mode, read
GET /v1/:owner/:repo/compare?from=<from-ref>&to=<to-ref>. - Classify commits and PRs with deterministic rules.
- Render
json,table, ormarkdown; default output ismarkdown. - Do not create releases, comments, labels, reviews, or merges.
workflow +stale
Inputs:
--stale-days--state--dry-run
Behavior:
- Identify stale issues and PRs.
- Generate suggested comments or labels.
- Do not mutate remote state by default.
API Fetch Layer
The current fetch layer uses:
triage_fetch.gohealth_fetch.gopr_fetch.gorepo_report_fetch.go
Design goals already applied:
- tolerate unknown or partial API fields
- map GitLink response shapes into stable workflow DTOs
- continue operating when optional signals fail
- keep remote-write actions disabled until explicitly enabled later
Planned fetch-layer extension:
triage_fetch.goandhealth_fetch.goremain the normalization boundary for remote mode.pr_fetch.gonow reuses the same stable DTO and message patterns for read-only PR metadata, changed files, and commits.repo_report_fetch.gocomposes the existing fetch helpers and records partial failures instead of failing the whole report.release_notes_fetch.goreuses the same normalization and renderer patterns for read-only compare data.- Unknown or missing fields should stay explicit in JSON output so Agents can decide how to proceed.
Implementation Order
- Pure DTOs and rule engine.
- Pure health scoring.
- Workflow renderers.
- Command registration.
- API fetch and normalization.
- Tests.
- README updates.
- Competition docs and test report.