sigit-code 1.6.7__tar.gz → 1.6.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/AGENTS.md +7 -2
  2. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/sigit-code-release/SKILL.md +41 -5
  3. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/sigit-code-release/SKILL.md +41 -5
  4. sigit_code-1.6.9/.github/workflows/release-winget.yml +328 -0
  5. {sigit_code-1.6.7 → sigit_code-1.6.9}/AGENTS.md +7 -2
  6. {sigit_code-1.6.7 → sigit_code-1.6.9}/CHANGELOG.md +46 -0
  7. {sigit_code-1.6.7 → sigit_code-1.6.9}/CLAUDE.md +7 -2
  8. {sigit_code-1.6.7 → sigit_code-1.6.9}/Cargo.lock +1 -1
  9. {sigit_code-1.6.7 → sigit_code-1.6.9}/Cargo.toml +1 -1
  10. {sigit_code-1.6.7 → sigit_code-1.6.9}/PKG-INFO +1 -1
  11. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/inline_tool_calls.rs +177 -0
  12. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/main.rs +20 -1
  13. sigit_code-1.6.7/.github/workflows/release-winget.yml +0 -178
  14. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/agent-client-protocol/SKILL.md +0 -0
  15. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/ai-assisted-coding/SKILL.md +0 -0
  16. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/branding/SKILL.md +0 -0
  17. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/run-sigit/SKILL.md +0 -0
  18. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/run-sigit/driver.mjs +0 -0
  19. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/run-sigit/tui-smoke.sh +0 -0
  20. {sigit_code-1.6.7 → sigit_code-1.6.9}/.agents/skills/tool-calling/SKILL.md +0 -0
  21. {sigit_code-1.6.7 → sigit_code-1.6.9}/.cargo/config.toml +0 -0
  22. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/agent-client-protocol/SKILL.md +0 -0
  23. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/ai-assisted-coding/SKILL.md +0 -0
  24. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/branding/SKILL.md +0 -0
  25. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/run-sigit/SKILL.md +0 -0
  26. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/run-sigit/driver.mjs +0 -0
  27. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/run-sigit/tui-smoke.sh +0 -0
  28. {sigit_code-1.6.7 → sigit_code-1.6.9}/.claude/skills/tool-calling/SKILL.md +0 -0
  29. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/ci.yml +0 -0
  30. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-aur.yml +0 -0
  31. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-crates.yml +0 -0
  32. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-github.yml +0 -0
  33. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-homebrew.yml +0 -0
  34. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-npm.yml +0 -0
  35. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-nuget.yml +0 -0
  36. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-pypi.yml +0 -0
  37. {sigit_code-1.6.7 → sigit_code-1.6.9}/.github/workflows/release-scoop.yml +0 -0
  38. {sigit_code-1.6.7 → sigit_code-1.6.9}/.gitignore +0 -0
  39. {sigit_code-1.6.7 → sigit_code-1.6.9}/.nvmrc +0 -0
  40. {sigit_code-1.6.7 → sigit_code-1.6.9}/.sigit/code-cloud-agent/config.toml +0 -0
  41. {sigit_code-1.6.7 → sigit_code-1.6.9}/.sigit/code-review/config.toml +0 -0
  42. {sigit_code-1.6.7 → sigit_code-1.6.9}/.sigit/factory/config.toml +0 -0
  43. {sigit_code-1.6.7 → sigit_code-1.6.9}/LICENSE +0 -0
  44. {sigit_code-1.6.7 → sigit_code-1.6.9}/README.md +0 -0
  45. {sigit_code-1.6.7 → sigit_code-1.6.9}/docs/headless.md +0 -0
  46. {sigit_code-1.6.7 → sigit_code-1.6.9}/docs/hooks.md +0 -0
  47. {sigit_code-1.6.7 → sigit_code-1.6.9}/docs/mcp.md +0 -0
  48. {sigit_code-1.6.7 → sigit_code-1.6.9}/examples/settings-with-hooks.toml +0 -0
  49. {sigit_code-1.6.7 → sigit_code-1.6.9}/examples/skills/README.md +0 -0
  50. {sigit_code-1.6.7 → sigit_code-1.6.9}/examples/skills/commit-message/SKILL.md +0 -0
  51. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/README.md.tmpl +0 -0
  52. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/package-compat.json.tmpl +0 -0
  53. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/package-main.json.tmpl +0 -0
  54. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/package.json.tmpl +0 -0
  55. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/scripts/render-main-package.cjs +0 -0
  56. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/scripts/render-platform-package.cjs +0 -0
  57. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/sigit/.gitignore +0 -0
  58. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/sigit/README.md +0 -0
  59. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/sigit/package.json +0 -0
  60. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/sigit/src/index.ts +0 -0
  61. {sigit_code-1.6.7 → sigit_code-1.6.9}/npm/sigit/tsconfig.json +0 -0
  62. {sigit_code-1.6.7 → sigit_code-1.6.9}/nuget/.gitignore +0 -0
  63. {sigit_code-1.6.7 → sigit_code-1.6.9}/nuget/sigit/Program.cs +0 -0
  64. {sigit_code-1.6.7 → sigit_code-1.6.9}/nuget/sigit/README.md +0 -0
  65. {sigit_code-1.6.7 → sigit_code-1.6.9}/nuget/sigit/SiGit.Code.csproj +0 -0
  66. {sigit_code-1.6.7 → sigit_code-1.6.9}/packaging/aur/PKGBUILD.in +0 -0
  67. {sigit_code-1.6.7 → sigit_code-1.6.9}/packaging/nfpm.yaml +0 -0
  68. {sigit_code-1.6.7 → sigit_code-1.6.9}/packaging/windows/check-static-crt.ps1 +0 -0
  69. {sigit_code-1.6.7 → sigit_code-1.6.9}/packaging/winget/getSigit.siGitCode.installer.yaml.in +0 -0
  70. {sigit_code-1.6.7 → sigit_code-1.6.9}/packaging/winget/getSigit.siGitCode.locale.en-US.yaml.in +0 -0
  71. {sigit_code-1.6.7 → sigit_code-1.6.9}/packaging/winget/getSigit.siGitCode.yaml.in +0 -0
  72. {sigit_code-1.6.7 → sigit_code-1.6.9}/pypi/README.md +0 -0
  73. {sigit_code-1.6.7 → sigit_code-1.6.9}/pypi/pyproject.toml +0 -0
  74. {sigit_code-1.6.7 → sigit_code-1.6.9}/pyproject.toml +0 -0
  75. {sigit_code-1.6.7 → sigit_code-1.6.9}/rust-toolchain.toml +0 -0
  76. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/account.rs +0 -0
  77. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/backend.rs +0 -0
  78. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/browser_auth.rs +0 -0
  79. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/chat.rs +0 -0
  80. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/client_fs.rs +0 -0
  81. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/client_terminal.rs +0 -0
  82. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/commands.rs +0 -0
  83. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/credentials.rs +0 -0
  84. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/frontmatter.rs +0 -0
  85. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/harness_markup.rs +0 -0
  86. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/headless.rs +0 -0
  87. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/hooks.rs +0 -0
  88. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/instructions.rs +0 -0
  89. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/mcp.rs +0 -0
  90. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/models.rs +0 -0
  91. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/permissions.rs +0 -0
  92. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/provider.rs +0 -0
  93. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/repetition.rs +0 -0
  94. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/session_store.rs +0 -0
  95. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/settings.rs +0 -0
  96. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/setup.rs +0 -0
  97. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/skills.rs +0 -0
  98. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/subagents.rs +0 -0
  99. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/tools.rs +0 -0
  100. {sigit_code-1.6.7 → sigit_code-1.6.9}/src/workspace.rs +0 -0
  101. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_audio.rs +0 -0
  102. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_client_fs.rs +0 -0
  103. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_client_terminal.rs +0 -0
  104. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_concurrent_sessions.rs +0 -0
  105. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_embedded_context.rs +0 -0
  106. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_endpoint_errors.rs +0 -0
  107. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_harness_markup.rs +0 -0
  108. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_images.rs +0 -0
  109. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_logout.rs +0 -0
  110. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_multi_root.rs +0 -0
  111. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_permissions.rs +0 -0
  112. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_session_list.rs +0 -0
  113. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_session_load.rs +0 -0
  114. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_stop_reasons.rs +0 -0
  115. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_tool_call_name.rs +0 -0
  116. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/acp_tool_stdin.rs +0 -0
  117. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/headless_mode.rs +0 -0
  118. {sigit_code-1.6.7 → sigit_code-1.6.9}/tests/version_flag.rs +0 -0
@@ -502,8 +502,13 @@ Three of these need credentials or a one-time manual step before they work:
502
502
 
503
503
  - Scoop needs a `getsigit/scoop-bucket` repo and a `SCOOP_BUCKET_TOKEN` secret, mirroring the
504
504
  Homebrew tap setup.
505
- - winget needs a `WINGET_TOKEN` (PAT with `public_repo` scope) so `wingetcreate` can fork
506
- `microsoft/winget-pkgs` and open the manifest PR. It is passed as
505
+ - winget files a Package Request issue first and then opens the manifest PR that resolves it,
506
+ authored by two separate classic PATs (replacing the old single `WINGET_TOKEN`):
507
+ `WINGET_ISSUE_TOKEN` (`public_repo`) for the issue and `WINGET_PR_TOKEN` for the PR.
508
+ `WINGET_PR_TOKEN` needs `public_repo` plus `read:org` and `read:discussion`: `public_repo`
509
+ lets `wingetcreate` fork `microsoft/winget-pkgs` and open the PR, and the later `gh pr edit`
510
+ that sets the PR body runs a GraphQL query resolving org/team and discussion fields that
511
+ fails with a scope error on a `public_repo`-only token. The PR token is passed as
507
512
  `WINGET_CREATE_GITHUB_TOKEN` rather than `--token`, which wingetcreate warns can leak the
508
513
  token into logs. `wingetcreate update` only works on a package that already exists in
509
514
  `microsoft/winget-pkgs`, so the workflow checks the `manifests/g/getSigit/siGitCode` path
@@ -38,12 +38,18 @@ Use this skill when preparing a release for this repository.
38
38
  - The GitHub release body is generated, not hand-written: `release-github.yml`'s release job checks out the tag, awk-extracts the `## <version>` section from `CHANGELOG.md` (a missing section is a hard failure), appends a full-changelog link and a `sigit.si/code` footnote, and publishes it via `body_path: release_notes.md`. The only file a release-prep change needs to touch is `CHANGELOG.md` — never edit release notes in the GitHub UI, because the next tag push would overwrite them.
39
39
  - npm and NuGet publish via OIDC trusted publishing — neither has a stored token in the repo. On npm this is configured per package (each `@getsigit/*` name has a trusted publisher pointing at `release-npm.yml`), so a new package needs the same setup before its first publish will work. OIDC requires npm >= 11.5.1 and Node >= 22.14.0.
40
40
  - The NuGet package (`SiGit.Code`, `dotnet tool install --global SiGit.Code`) bundles all six platform binaries under `native/<os>-<arch>/` behind a managed shim, rather than shipping one package per platform like npm/PyPI. Watch the nuget.org 250 MB package-size limit if it ever grows.
41
- - The winget channel (`release-winget.yml`) needs a `WINGET_TOKEN` secret that is a **classic PAT** with `public_repo` scope — not a fine-grained PAT. wingetcreate forks `microsoft/winget-pkgs` on first use and submits a PR from that fork; a fine-grained PAT scoped to `getsigit/sigit` cannot fork a repo outside its scope and every release fails with a 403/404 on the fork step. The token is passed as `WINGET_CREATE_GITHUB_TOKEN` (not `--token`) so it doesn't leak into logs. `wingetcreate update` only works on a package that already exists in `microsoft/winget-pkgs`, so the workflow checks `manifests/g/getSigit/siGitCode` first and falls back to `wingetcreate submit` with `packaging/winget/*.yaml.in` for the first release; every later release takes the `update` path. If a winget release fails with a fork/permission error, check the `WINGET_TOKEN` secret type before re-dispatching.
41
+ - The winget channel (`release-winget.yml`) files a Package Request issue first and then opens the manifest PR that resolves it, authored by **two separate classic PATs** (not fine-grained) — `WINGET_ISSUE_TOKEN` for the issue and `WINGET_PR_TOKEN` for the PR, replacing the old single `WINGET_TOKEN`. `WINGET_ISSUE_TOKEN` needs `public_repo`. `WINGET_PR_TOKEN` needs `public_repo` **plus `read:org` and `read:discussion`**: wingetcreate forks `microsoft/winget-pkgs` and opens the PR (fork needs `public_repo`; a fine-grained PAT scoped to `getsigit/sigit` can't fork an outside repo and 403/404s), and the "Set the winget PR body" step then runs `gh pr edit`, whose GraphQL query resolves org/team and discussion fields and fails with a scope error on a `public_repo`-only token (CI run 38262301933). The PR token is passed as `WINGET_CREATE_GITHUB_TOKEN` (not `--token`) so it doesn't leak into logs. `wingetcreate update` only works on a package that already exists in `microsoft/winget-pkgs`, so the workflow checks `manifests/g/getSigit/siGitCode` first and falls back to `wingetcreate submit` with `packaging/winget/*.yaml.in` for the first release; every later release takes the `update` path. If a winget release fails on the fork step, check the token type; if it fails on the `gh pr edit` step with a scope error, check `WINGET_PR_TOKEN`'s scopes before re-dispatching.
42
42
  - The baked-in official MCP server is separately listed in the public MCP Registry as `si.sigit/sigit` (`release-mcp-registry.yml`, driven by `server.json` at the repo root). It's a remote Streamable-HTTP listing, so it's verified by a DNS TXT record on the `sigit.si` domain rather than the GitHub-OIDC scheme used for package listings.
43
43
 
44
44
  ## Git release flow
45
45
 
46
- Releases are cut from `development` and shipped on `main`. The published tags (`v1.2.0`, `v1.2.1`) point at the `main`-side merge commit, never at a release branch or at `development`. Follow this order:
46
+ Releases are shipped on `main`, and the published tags (`v1.2.0`, `v1.2.1`) point at the
47
+ `main`-side merge commit, never at a release branch or at `development`. There are two flows,
48
+ and picking the wrong one ships the wrong set of commits. Decide first which this is.
49
+
50
+ ### Full release (minor/major — ships everything on `development`)
51
+
52
+ Cut from `development` when the release is meant to carry all the work that has accumulated there.
47
53
 
48
54
  1. Branch `release/v<version>` off `development`.
49
55
  2. Apply the version bump and changelog edits, then commit (e.g. `Release v<version>`).
@@ -51,10 +57,38 @@ Releases are cut from `development` and shipped on `main`. The published tags (`
51
57
  4. Merge `development` into `main` (commit message: `Merge development into main for v<version> release`).
52
58
  5. Tag `v<version>` on that `main` merge commit, then push `main` and the tag.
53
59
 
54
- Step 4 is the only way commits are meant to reach `main`. A feature or fix PR targeting `main` breaks that: it puts work on the release branch that `development` does not have, so the next release is cut without it. Such PRs belong on `development` (see the pull request target rule in `AGENTS.md`).
60
+ For a full release, step 4 is the only way commits are meant to reach `main`. A feature or fix
61
+ PR targeting `main` breaks that: it puts work on the release branch that `development` does not
62
+ have, so the next release is cut without it. Such PRs belong on `development` (see the pull
63
+ request target rule in `AGENTS.md`).
64
+
65
+ ### Scoped patch (hotfix — ships only specific fixes on top of the last tag)
66
+
67
+ Use this when the patch must ship **only** a named set of fixes on top of the last released tag,
68
+ **not** the unreleased work sitting on `development` (e.g. a patch over `v1.6.7` that must carry
69
+ just a winget/Windows hotfix while ACP features stay unreleased). The giveaway is wording like
70
+ "scoped patch off `v<prev>`" or "hotfix" — if `development` is far ahead, a `development → main`
71
+ merge would drag all of it out under a patch tag, which is wrong.
72
+
73
+ 1. Branch `release/v<version>` off the **last released tag** (`v<prev>`), not `development`.
74
+ 2. Cherry-pick (or commit) only the in-scope fixes, then the version bump + changelog, and commit
75
+ (e.g. `Release v<version>`).
76
+ 3. Merge `release/v<version>` back into `development` so the bump and changelog carry forward.
77
+ 4. Merge `release/v<version>` **directly into `main`** (commit message: `Release v<version>`) —
78
+ **never `development → main` for a scoped patch**, since that would pull `development`'s
79
+ unreleased work onto `main`.
80
+ 5. Tag `v<version>` on that `main` merge commit, then push `main` and the tag.
81
+
82
+ Before tagging a scoped patch, audit the scope: `git log --oneline v<prev>^{commit}..main` and
83
+ `git diff --stat v<prev>^{commit}..main` must show only the intended fixes and the release
84
+ metadata files (`Cargo.toml`, `Cargo.lock`, `CHANGELOG.md`), nothing from `development`.
55
85
 
56
86
  Pushing the `v*.*.*` tag is what fires every release workflow, so create and push it only after the merge into `main` has landed. Do not commit, tag, or push until the user explicitly asks — confirm the version and that they want the release to go out first.
57
87
 
88
+ Decide up front which flow you are in and confirm the exact scope with the user. If in doubt about
89
+ whether a release ships everything on `development` or only a scoped set of fixes, ask — the two
90
+ flows start from different base commits and are not interchangeable.
91
+
58
92
  ## Typical files to inspect
59
93
 
60
94
  - `Cargo.toml`
@@ -79,10 +113,12 @@ Pushing the `v*.*.*` tag is what fires every release workflow, so create and pus
79
113
  - `npm/sigit/package.json` is left at `0.0.0-dev` unless the packaging flow itself changed.
80
114
  - `pypi/pyproject.toml` still uses dynamic versioning unless there is a deliberate packaging change.
81
115
  - Release workflows still derive their version from the tag as expected.
82
- - Git flow followed: bump committed on `release/v<version>`, merged back to `development`, then `development` merged into `main`, with `v<version>` tagged on the `main` merge commit.
116
+ - Correct git flow for the release type followed, with `v<version>` tagged on the `main` merge commit either way:
117
+ - **Full release:** bump committed on `release/v<version>` (off `development`), merged back to `development`, then `development` merged into `main`.
118
+ - **Scoped patch:** `release/v<version>` branched off the last tag `v<prev>`, in-scope fixes + bump committed, merged back to `development`, then `release/v<version>` merged **directly into `main`** (never `development → main`), and the scope audited (`git log --oneline v<prev>^{commit}..main` / `git diff --stat v<prev>^{commit}..main`) to show only the intended fixes plus release metadata.
83
119
  - Release notes or changelog entries match the actual changes.
84
120
  - CI-equivalent local checks pass for the relevant platform or target.
85
121
  - Package names, install commands, and branding stay consistent across npm, PyPI, crates.io, Homebrew, NuGet, Scoop, winget, AUR, and the `.deb`/`.rpm` packages.
86
122
  - Every release asset (including the new `.deb`/`.rpm`/raw binaries consumed by Scoop, winget, and AUR) has a matching `.sha256` sidecar.
87
123
  - Any known release limitations are called out explicitly, including a dispatch failure in `release-scoop`/`release-winget`/`release-aur` (non-fatal — logged as a warning by `release-github.yml`) versus a hard failure in a directly tag-triggered workflow like `release-nuget` or `release-mcp-registry`.
88
- - The `WINGET_TOKEN` secret is a classic PAT with `public_repo` scope (not fine-grained), so wingetcreate can fork `microsoft/winget-pkgs`. If a winget release fails on the fork step, verify the token type before re-dispatching.
124
+ - The winget channel uses two classic PATs (not fine-grained): `WINGET_ISSUE_TOKEN` (`public_repo`) for the Package Request issue and `WINGET_PR_TOKEN` (`public_repo` + `read:org` + `read:discussion`) for the manifest PR, so wingetcreate can fork `microsoft/winget-pkgs` and `gh pr edit` can set the PR body. If a winget release fails on the fork step, verify the token type; if it fails on the `gh pr edit` step, verify `WINGET_PR_TOKEN`'s scopes before re-dispatching.
@@ -38,12 +38,18 @@ Use this skill when preparing a release for this repository.
38
38
  - The GitHub release body is generated, not hand-written: `release-github.yml`'s release job checks out the tag, awk-extracts the `## <version>` section from `CHANGELOG.md` (a missing section is a hard failure), appends a full-changelog link and a `sigit.si/code` footnote, and publishes it via `body_path: release_notes.md`. The only file a release-prep change needs to touch is `CHANGELOG.md` — never edit release notes in the GitHub UI, because the next tag push would overwrite them.
39
39
  - npm and NuGet publish via OIDC trusted publishing — neither has a stored token in the repo. On npm this is configured per package (each `@getsigit/*` name has a trusted publisher pointing at `release-npm.yml`), so a new package needs the same setup before its first publish will work. OIDC requires npm >= 11.5.1 and Node >= 22.14.0.
40
40
  - The NuGet package (`SiGit.Code`, `dotnet tool install --global SiGit.Code`) bundles all six platform binaries under `native/<os>-<arch>/` behind a managed shim, rather than shipping one package per platform like npm/PyPI. Watch the nuget.org 250 MB package-size limit if it ever grows.
41
- - The winget channel (`release-winget.yml`) needs a `WINGET_TOKEN` secret that is a **classic PAT** with `public_repo` scope — not a fine-grained PAT. wingetcreate forks `microsoft/winget-pkgs` on first use and submits a PR from that fork; a fine-grained PAT scoped to `getsigit/sigit` cannot fork a repo outside its scope and every release fails with a 403/404 on the fork step. The token is passed as `WINGET_CREATE_GITHUB_TOKEN` (not `--token`) so it doesn't leak into logs. `wingetcreate update` only works on a package that already exists in `microsoft/winget-pkgs`, so the workflow checks `manifests/g/getSigit/siGitCode` first and falls back to `wingetcreate submit` with `packaging/winget/*.yaml.in` for the first release; every later release takes the `update` path. If a winget release fails with a fork/permission error, check the `WINGET_TOKEN` secret type before re-dispatching.
41
+ - The winget channel (`release-winget.yml`) files a Package Request issue first and then opens the manifest PR that resolves it, authored by **two separate classic PATs** (not fine-grained) — `WINGET_ISSUE_TOKEN` for the issue and `WINGET_PR_TOKEN` for the PR, replacing the old single `WINGET_TOKEN`. `WINGET_ISSUE_TOKEN` needs `public_repo`. `WINGET_PR_TOKEN` needs `public_repo` **plus `read:org` and `read:discussion`**: wingetcreate forks `microsoft/winget-pkgs` and opens the PR (fork needs `public_repo`; a fine-grained PAT scoped to `getsigit/sigit` can't fork an outside repo and 403/404s), and the "Set the winget PR body" step then runs `gh pr edit`, whose GraphQL query resolves org/team and discussion fields and fails with a scope error on a `public_repo`-only token (CI run 38262301933). The PR token is passed as `WINGET_CREATE_GITHUB_TOKEN` (not `--token`) so it doesn't leak into logs. `wingetcreate update` only works on a package that already exists in `microsoft/winget-pkgs`, so the workflow checks `manifests/g/getSigit/siGitCode` first and falls back to `wingetcreate submit` with `packaging/winget/*.yaml.in` for the first release; every later release takes the `update` path. If a winget release fails on the fork step, check the token type; if it fails on the `gh pr edit` step with a scope error, check `WINGET_PR_TOKEN`'s scopes before re-dispatching.
42
42
  - The baked-in official MCP server is separately listed in the public MCP Registry as `si.sigit/sigit` (`release-mcp-registry.yml`, driven by `server.json` at the repo root). It's a remote Streamable-HTTP listing, so it's verified by a DNS TXT record on the `sigit.si` domain rather than the GitHub-OIDC scheme used for package listings.
43
43
 
44
44
  ## Git release flow
45
45
 
46
- Releases are cut from `development` and shipped on `main`. The published tags (`v1.2.0`, `v1.2.1`) point at the `main`-side merge commit, never at a release branch or at `development`. Follow this order:
46
+ Releases are shipped on `main`, and the published tags (`v1.2.0`, `v1.2.1`) point at the
47
+ `main`-side merge commit, never at a release branch or at `development`. There are two flows,
48
+ and picking the wrong one ships the wrong set of commits. Decide first which this is.
49
+
50
+ ### Full release (minor/major — ships everything on `development`)
51
+
52
+ Cut from `development` when the release is meant to carry all the work that has accumulated there.
47
53
 
48
54
  1. Branch `release/v<version>` off `development`.
49
55
  2. Apply the version bump and changelog edits, then commit (e.g. `Release v<version>`).
@@ -51,10 +57,38 @@ Releases are cut from `development` and shipped on `main`. The published tags (`
51
57
  4. Merge `development` into `main` (commit message: `Merge development into main for v<version> release`).
52
58
  5. Tag `v<version>` on that `main` merge commit, then push `main` and the tag.
53
59
 
54
- Step 4 is the only way commits are meant to reach `main`. A feature or fix PR targeting `main` breaks that: it puts work on the release branch that `development` does not have, so the next release is cut without it. Such PRs belong on `development` (see the pull request target rule in `AGENTS.md`).
60
+ For a full release, step 4 is the only way commits are meant to reach `main`. A feature or fix
61
+ PR targeting `main` breaks that: it puts work on the release branch that `development` does not
62
+ have, so the next release is cut without it. Such PRs belong on `development` (see the pull
63
+ request target rule in `AGENTS.md`).
64
+
65
+ ### Scoped patch (hotfix — ships only specific fixes on top of the last tag)
66
+
67
+ Use this when the patch must ship **only** a named set of fixes on top of the last released tag,
68
+ **not** the unreleased work sitting on `development` (e.g. a patch over `v1.6.7` that must carry
69
+ just a winget/Windows hotfix while ACP features stay unreleased). The giveaway is wording like
70
+ "scoped patch off `v<prev>`" or "hotfix" — if `development` is far ahead, a `development → main`
71
+ merge would drag all of it out under a patch tag, which is wrong.
72
+
73
+ 1. Branch `release/v<version>` off the **last released tag** (`v<prev>`), not `development`.
74
+ 2. Cherry-pick (or commit) only the in-scope fixes, then the version bump + changelog, and commit
75
+ (e.g. `Release v<version>`).
76
+ 3. Merge `release/v<version>` back into `development` so the bump and changelog carry forward.
77
+ 4. Merge `release/v<version>` **directly into `main`** (commit message: `Release v<version>`) —
78
+ **never `development → main` for a scoped patch**, since that would pull `development`'s
79
+ unreleased work onto `main`.
80
+ 5. Tag `v<version>` on that `main` merge commit, then push `main` and the tag.
81
+
82
+ Before tagging a scoped patch, audit the scope: `git log --oneline v<prev>^{commit}..main` and
83
+ `git diff --stat v<prev>^{commit}..main` must show only the intended fixes and the release
84
+ metadata files (`Cargo.toml`, `Cargo.lock`, `CHANGELOG.md`), nothing from `development`.
55
85
 
56
86
  Pushing the `v*.*.*` tag is what fires every release workflow, so create and push it only after the merge into `main` has landed. Do not commit, tag, or push until the user explicitly asks — confirm the version and that they want the release to go out first.
57
87
 
88
+ Decide up front which flow you are in and confirm the exact scope with the user. If in doubt about
89
+ whether a release ships everything on `development` or only a scoped set of fixes, ask — the two
90
+ flows start from different base commits and are not interchangeable.
91
+
58
92
  ## Typical files to inspect
59
93
 
60
94
  - `Cargo.toml`
@@ -79,10 +113,12 @@ Pushing the `v*.*.*` tag is what fires every release workflow, so create and pus
79
113
  - `npm/sigit/package.json` is left at `0.0.0-dev` unless the packaging flow itself changed.
80
114
  - `pypi/pyproject.toml` still uses dynamic versioning unless there is a deliberate packaging change.
81
115
  - Release workflows still derive their version from the tag as expected.
82
- - Git flow followed: bump committed on `release/v<version>`, merged back to `development`, then `development` merged into `main`, with `v<version>` tagged on the `main` merge commit.
116
+ - Correct git flow for the release type followed, with `v<version>` tagged on the `main` merge commit either way:
117
+ - **Full release:** bump committed on `release/v<version>` (off `development`), merged back to `development`, then `development` merged into `main`.
118
+ - **Scoped patch:** `release/v<version>` branched off the last tag `v<prev>`, in-scope fixes + bump committed, merged back to `development`, then `release/v<version>` merged **directly into `main`** (never `development → main`), and the scope audited (`git log --oneline v<prev>^{commit}..main` / `git diff --stat v<prev>^{commit}..main`) to show only the intended fixes plus release metadata.
83
119
  - Release notes or changelog entries match the actual changes.
84
120
  - CI-equivalent local checks pass for the relevant platform or target.
85
121
  - Package names, install commands, and branding stay consistent across npm, PyPI, crates.io, Homebrew, NuGet, Scoop, winget, AUR, and the `.deb`/`.rpm` packages.
86
122
  - Every release asset (including the new `.deb`/`.rpm`/raw binaries consumed by Scoop, winget, and AUR) has a matching `.sha256` sidecar.
87
123
  - Any known release limitations are called out explicitly, including a dispatch failure in `release-scoop`/`release-winget`/`release-aur` (non-fatal — logged as a warning by `release-github.yml`) versus a hard failure in a directly tag-triggered workflow like `release-nuget` or `release-mcp-registry`.
88
- - The `WINGET_TOKEN` secret is a classic PAT with `public_repo` scope (not fine-grained), so wingetcreate can fork `microsoft/winget-pkgs`. If a winget release fails on the fork step, verify the token type before re-dispatching.
124
+ - The winget channel uses two classic PATs (not fine-grained): `WINGET_ISSUE_TOKEN` (`public_repo`) for the Package Request issue and `WINGET_PR_TOKEN` (`public_repo` + `read:org` + `read:discussion`) for the manifest PR, so wingetcreate can fork `microsoft/winget-pkgs` and `gh pr edit` can set the PR body. If a winget release fails on the fork step, verify the token type; if it fails on the `gh pr edit` step, verify `WINGET_PR_TOKEN`'s scopes before re-dispatching.
@@ -0,0 +1,328 @@
1
+ name: winget Release
2
+
3
+ # Dispatched by release-github.yml once the release and its checksums exist.
4
+ #
5
+ # winget manifests live in microsoft/winget-pkgs, and `wingetcreate update`
6
+ # only works on a package that is already there. So this workflow branches:
7
+ #
8
+ # - package already in winget-pkgs -> `wingetcreate update`, which rewrites
9
+ # the URLs and re-hashes the installers for us.
10
+ # - package not there yet -> render the manifests in packaging/winget/ and
11
+ # `wingetcreate submit` them as a new package.
12
+ #
13
+ # The second path only runs once, but keeping it here means a first release
14
+ # does not need someone to sit at a Windows box running `wingetcreate new`
15
+ # interactively.
16
+ on:
17
+ workflow_dispatch:
18
+ inputs:
19
+ tag:
20
+ description: "Release tag (e.g. v1.5.2)"
21
+ required: true
22
+
23
+ concurrency:
24
+ # A re-pushed or re-dispatched tag fires this a second time. Queue the
25
+ # duplicate behind the original instead of cancelling it: cancelling a run
26
+ # mid-publish can leave a channel half-uploaded, whereas a queued duplicate
27
+ # just hits the "already published" check and exits clean.
28
+ group: ${{ github.workflow }}-${{ github.event.inputs.tag || github.ref_name }}
29
+ cancel-in-progress: false
30
+
31
+ permissions:
32
+ contents: read
33
+
34
+ env:
35
+ REPO: getsigit/sigit
36
+ PACKAGE_IDENTIFIER: getSigit.siGitCode
37
+
38
+ jobs:
39
+ submit-winget-manifest:
40
+ name: Submit winget manifest
41
+ # wingetcreate is a Windows-only tool.
42
+ runs-on: windows-latest
43
+
44
+ steps:
45
+ - name: Check out repository
46
+ uses: actions/checkout@v6
47
+
48
+ - name: Resolve tag, version and release date
49
+ id: release
50
+ shell: bash
51
+ env:
52
+ GH_TOKEN: ${{ github.token }}
53
+ run: |
54
+ TAG="${{ github.event.inputs.tag }}"
55
+ VERSION="${TAG#v}"
56
+ # wingetcreate wants ReleaseDate as YYYY-MM-DD.
57
+ DATE=$(gh release view "$TAG" --repo "$REPO" --json publishedAt --jq '.publishedAt[0:10]')
58
+
59
+ echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
60
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
61
+ echo "date=${DATE}" >> "$GITHUB_OUTPUT"
62
+
63
+ - name: Check whether the package is already in winget-pkgs
64
+ id: exists
65
+ shell: bash
66
+ env:
67
+ GH_TOKEN: ${{ github.token }}
68
+ run: |
69
+ # manifests are filed under the lowercased first letter of the
70
+ # publisher, e.g. manifests/g/getSigit/siGitCode.
71
+ PUBLISHER="${PACKAGE_IDENTIFIER%%.*}"
72
+ NAME="${PACKAGE_IDENTIFIER#*.}"
73
+ FIRST=$(echo "${PUBLISHER:0:1}" | tr '[:upper:]' '[:lower:]')
74
+ PATH_IN_REPO="manifests/${FIRST}/${PUBLISHER}/${NAME}"
75
+
76
+ if gh api "repos/microsoft/winget-pkgs/contents/${PATH_IN_REPO}" >/dev/null 2>&1; then
77
+ echo "Found ${PACKAGE_IDENTIFIER} at ${PATH_IN_REPO}; submitting an update."
78
+ echo "found=true" >> "$GITHUB_OUTPUT"
79
+ else
80
+ echo "No ${PACKAGE_IDENTIFIER} at ${PATH_IN_REPO}; submitting it as a new package."
81
+ echo "found=false" >> "$GITHUB_OUTPUT"
82
+ fi
83
+
84
+ - name: Render manifests for a first submission
85
+ if: steps.exists.outputs.found == 'false'
86
+ shell: bash
87
+ env:
88
+ GH_TOKEN: ${{ github.token }}
89
+ run: |
90
+ TAG="${{ steps.release.outputs.tag }}"
91
+ VERSION="${{ steps.release.outputs.version }}"
92
+
93
+ mkdir -p artifacts manifests
94
+
95
+ gh release download "$TAG" \
96
+ --repo "$REPO" \
97
+ --pattern "sigit-win-*.exe.sha256" \
98
+ --dir artifacts/
99
+
100
+ # The schema wants 64 hex characters; the community validation
101
+ # pipeline writes them uppercase, so match that.
102
+ SHA_AMD64=$(tr -d '[:space:]' < artifacts/sigit-win-amd64.exe.sha256 | tr '[:lower:]' '[:upper:]')
103
+ SHA_ARM64=$(tr -d '[:space:]' < artifacts/sigit-win-arm64.exe.sha256 | tr '[:lower:]' '[:upper:]')
104
+
105
+ RELEASE_DATE="${{ steps.release.outputs.date }}"
106
+
107
+ for template in packaging/winget/*.yaml.in; do
108
+ out="manifests/$(basename "$template" .in)"
109
+ sed \
110
+ -e "s|@VERSION@|${VERSION}|g" \
111
+ -e "s|@TAG@|${TAG}|g" \
112
+ -e "s|@REPO@|${REPO}|g" \
113
+ -e "s|@SHA_AMD64@|${SHA_AMD64}|g" \
114
+ -e "s|@SHA_ARM64@|${SHA_ARM64}|g" \
115
+ -e "s|@RELEASE_DATE@|${RELEASE_DATE}|g" \
116
+ "$template" > "$out"
117
+
118
+ echo "--- ${out} ---"
119
+ cat "$out"
120
+ done
121
+
122
+ - name: Download wingetcreate
123
+ shell: pwsh
124
+ run: Invoke-WebRequest -Uri "https://aka.ms/wingetcreate/latest" -OutFile wingetcreate.exe
125
+
126
+ # winget-pkgs convention: file the "please add/update this package"
127
+ # Package Request issue *first*, then open the manifest PR that fulfils
128
+ # it with "Resolves #N". Doing it the other way round (PR first, issue
129
+ # after) reads as "here's a request, and here's the PR that already did
130
+ # it", posted seconds apart.
131
+ #
132
+ # The issue and the PR are authored by two separate PATs, configured as
133
+ # the repo secrets WINGET_ISSUE_TOKEN (the Package Request issue) and
134
+ # WINGET_PR_TOKEN (the manifest PR). Both need public_repo scope on
135
+ # microsoft/winget-pkgs (fork + open issues/PRs). WINGET_PR_TOKEN also
136
+ # needs read:org and read:discussion: the "Set the winget PR body" step
137
+ # below calls `gh pr edit`, whose GraphQL query resolves org/team and
138
+ # discussion fields and fails with a scope error without them.
139
+ # WINGET_PR_TOKEN replaces the old single WINGET_TOKEN.
140
+ - name: File the winget Package Request issue
141
+ id: issue
142
+ shell: bash
143
+ env:
144
+ # Authored by the issue account for this repo.
145
+ GH_TOKEN: ${{ secrets.WINGET_ISSUE_TOKEN }}
146
+ run: |
147
+ set -euo pipefail
148
+
149
+ if [ -z "${GH_TOKEN:-}" ]; then
150
+ echo "WINGET_ISSUE_TOKEN is not set. It needs a PAT (public_repo) for the account that should author the Package Request issue." >&2
151
+ exit 1
152
+ fi
153
+
154
+ VERSION="${{ steps.release.outputs.version }}"
155
+ TAG="${{ steps.release.outputs.tag }}"
156
+
157
+ # The release assets, same URLs the update step feeds wingetcreate.
158
+ BASE="https://github.com/${REPO}/releases/download/${TAG}"
159
+ INSTALLER_AMD64="${BASE}/sigit-win-amd64.exe"
160
+ INSTALLER_ARM64="${BASE}/sigit-win-arm64.exe"
161
+
162
+ # winget-pkgs' Package Request is an issue *form*
163
+ # (.github/ISSUE_TEMPLATE/package_request.yml): the title must be
164
+ # "[Package Request]: ..." and the body has to carry the labelled
165
+ # fields below (Installer Url especially — without it a maintainer
166
+ # just replies "please provide the installer link"). A free-text
167
+ # body lands as Needs-Triage and can't be acted on.
168
+ ISSUE_BODY=$(cat <<EOF
169
+ Download Page Url: https://github.com/${REPO}/releases/tag/${TAG}
170
+ Publisher: getSigit
171
+ Package Name: siGit Code
172
+ Description: siGit Code, an AI coding agent that runs on your machine.
173
+ Package Version: ${VERSION}
174
+ Installer Url: ${INSTALLER_AMD64}
175
+ Installer Url: ${INSTALLER_ARM64}
176
+ EOF
177
+ )
178
+
179
+ ISSUE_URL=$(gh issue create \
180
+ --repo microsoft/winget-pkgs \
181
+ --title "[Package Request]: ${PACKAGE_IDENTIFIER} ${VERSION}" \
182
+ --body "$ISSUE_BODY")
183
+
184
+ echo "Opened issue ${ISSUE_URL}"
185
+ echo "issue_url=${ISSUE_URL}" >> "$GITHUB_OUTPUT"
186
+ echo "issue_number=${ISSUE_URL##*/}" >> "$GITHUB_OUTPUT"
187
+
188
+ - name: Sebat dulu ...
189
+ if: steps.issue.outputs.issue_number != ''
190
+ shell: bash
191
+ run: sleep $(( RANDOM % 61 + 150 ))
192
+
193
+ - name: Submit new package
194
+ id: submit_new
195
+ if: steps.exists.outputs.found == 'false'
196
+ shell: pwsh
197
+ env:
198
+ # wingetcreate reads the token from this variable. Passing it as
199
+ # --token instead makes the tool warn that the token can end up in
200
+ # logs, which on a shared runner is not a warning worth ignoring.
201
+ # This is the PR-author account for this repo (see mapping above).
202
+ WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
203
+ run: |
204
+ if (-not $env:WINGET_CREATE_GITHUB_TOKEN) {
205
+ Write-Error "WINGET_PR_TOKEN is not set. It needs a PAT with public_repo, read:org, and read:discussion scopes so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR, and gh can edit the PR body."
206
+ }
207
+
208
+ $version = "${{ steps.release.outputs.version }}"
209
+
210
+ # Tee stdout so we can scrape the PR URL afterwards. wingetcreate
211
+ # prints "Pull request can be found here: <url>" on success, and
212
+ # that line is the only handle we get on the PR it just opened.
213
+ # --no-open because the runner has no browser to open the PR in.
214
+ .\wingetcreate.exe submit manifests `
215
+ --prtitle "New package: $env:PACKAGE_IDENTIFIER version $version" `
216
+ --no-open 2>&1 | Tee-Object -Variable output
217
+
218
+ if ($LASTEXITCODE -ne 0) {
219
+ Write-Error "wingetcreate submit failed with exit code $LASTEXITCODE"
220
+ }
221
+
222
+ $match = [regex]::Match(($output -join "`n"), 'https://github\.com/microsoft/winget-pkgs/pull/(\d+)')
223
+ if ($match.Success) {
224
+ "pr_url=$($match.Value)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
225
+ "pr_number=$($match.Groups[1].Value)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
226
+ } else {
227
+ Write-Warning "Could not find the PR URL in wingetcreate output; skipping issue linking."
228
+ }
229
+
230
+ - name: Submit manifest update
231
+ id: submit_update
232
+ if: steps.exists.outputs.found == 'true'
233
+ shell: pwsh
234
+ env:
235
+ # PR-author account for this repo (see mapping above).
236
+ WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
237
+ run: |
238
+ if (-not $env:WINGET_CREATE_GITHUB_TOKEN) {
239
+ Write-Error "WINGET_PR_TOKEN is not set. It needs a PAT with public_repo, read:org, and read:discussion scopes so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR, and gh can edit the PR body."
240
+ }
241
+
242
+ $tag = "${{ steps.release.outputs.tag }}"
243
+ $version = "${{ steps.release.outputs.version }}"
244
+ $base = "https://github.com/${env:REPO}/releases/download/$tag"
245
+
246
+ # The trailing |x64 and |arm64 tell wingetcreate which installer
247
+ # entry each URL replaces. Without them it guesses from the file
248
+ # name, and "sigit-win-amd64.exe" is not a spelling it recognises.
249
+ .\wingetcreate.exe update $env:PACKAGE_IDENTIFIER `
250
+ --version $version `
251
+ --urls "$base/sigit-win-amd64.exe|x64" "$base/sigit-win-arm64.exe|arm64" `
252
+ --release-notes-url "https://github.com/${env:REPO}/releases/tag/$tag" `
253
+ --release-date "${{ steps.release.outputs.date }}" `
254
+ --prtitle "Update $env:PACKAGE_IDENTIFIER to version $version" `
255
+ --submit `
256
+ --no-open 2>&1 | Tee-Object -Variable output
257
+
258
+ if ($LASTEXITCODE -ne 0) {
259
+ Write-Error "wingetcreate failed with exit code $LASTEXITCODE"
260
+ }
261
+
262
+ $match = [regex]::Match(($output -join "`n"), 'https://github\.com/microsoft/winget-pkgs/pull/(\d+)')
263
+ if ($match.Success) {
264
+ "pr_url=$($match.Value)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
265
+ "pr_number=$($match.Groups[1].Value)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
266
+ } else {
267
+ Write-Warning "Could not find the PR URL in wingetcreate output; skipping issue linking."
268
+ }
269
+
270
+ # wingetcreate has no --prbody flag (only --prtitle), so it always opens
271
+ # the PR with the winget-pkgs template: an empty Description and an
272
+ # unticked "Linked to an issue" box next to a "Resolves #[Issue Number]"
273
+ # placeholder. The issue already exists (filed first, above), so this
274
+ # step just rewrites the body to point the PR at it with "Resolves #N".
275
+ #
276
+ # This must run as the PR author (WINGET_PR_TOKEN) — the account that
277
+ # opened the PR via wingetcreate — since only the author (or a repo
278
+ # maintainer) can edit it.
279
+ - name: Set the winget PR body and link the issue
280
+ id: link
281
+ if: >-
282
+ (steps.submit_new.outputs.pr_number != '') ||
283
+ (steps.submit_update.outputs.pr_number != '')
284
+ shell: bash
285
+ env:
286
+ GH_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
287
+ run: |
288
+ set -euo pipefail
289
+
290
+ PR_URL="${{ steps.submit_new.outputs.pr_url || steps.submit_update.outputs.pr_url }}"
291
+ ISSUE_NUMBER="${{ steps.issue.outputs.issue_number }}"
292
+ VERSION="${{ steps.release.outputs.version }}"
293
+ TAG="${{ steps.release.outputs.tag }}"
294
+
295
+ if [ -n "$ISSUE_NUMBER" ]; then
296
+ CHECKBOX="- [x] Linked to an issue (if applicable)"
297
+ RESOLVES="- Resolves #${ISSUE_NUMBER}"
298
+ else
299
+ CHECKBOX="- [ ] Linked to an issue (if applicable)"
300
+ RESOLVES=""
301
+ fi
302
+
303
+ if [ "${{ steps.exists.outputs.found }}" = "false" ]; then
304
+ DESC="Adds ${PACKAGE_IDENTIFIER} version ${VERSION} from ${TAG}."
305
+ else
306
+ DESC="Updates ${PACKAGE_IDENTIFIER} to version ${VERSION} from ${TAG}."
307
+ fi
308
+
309
+ # Mirrors the current .github/PULL_REQUEST_TEMPLATE.md; keep the
310
+ # checklist items in sync with it (e.g. the 1.12 schema line).
311
+ BODY=$(cat <<EOF
312
+ ## 📖 Description
313
+ ${DESC}
314
+ ## ✅ Checklist
315
+ - [x] Signed the [Contributor License Agreement](https://cla.opensource.microsoft.com)
316
+ ${CHECKBOX}
317
+ ${RESOLVES}
318
+ ## 📦 Manifest Checklist
319
+ - [x] Checked that there aren't other open [pull requests](https://github.com/microsoft/winget-pkgs/pulls) for the same manifest update/change
320
+ - [x] This PR only modifies one (1) manifest
321
+ - [x] Validated manifest locally with \`winget validate --manifest <directory>\`
322
+ - [x] Tested manifest locally with \`winget install --manifest <directory>\`
323
+ - [x] Manifest conforms to the [1.12 schema](https://github.com/microsoft/winget-pkgs/tree/master/doc/manifest/schema/1.12.0)
324
+ EOF
325
+ )
326
+
327
+ gh pr edit "$PR_URL" --body "$BODY"
328
+ echo "Linked ${PR_URL} to issue #${ISSUE_NUMBER:-<none>}"
@@ -502,8 +502,13 @@ Three of these need credentials or a one-time manual step before they work:
502
502
 
503
503
  - Scoop needs a `getsigit/scoop-bucket` repo and a `SCOOP_BUCKET_TOKEN` secret, mirroring the
504
504
  Homebrew tap setup.
505
- - winget needs a `WINGET_TOKEN` (PAT with `public_repo` scope) so `wingetcreate` can fork
506
- `microsoft/winget-pkgs` and open the manifest PR. It is passed as
505
+ - winget files a Package Request issue first and then opens the manifest PR that resolves it,
506
+ authored by two separate classic PATs (replacing the old single `WINGET_TOKEN`):
507
+ `WINGET_ISSUE_TOKEN` (`public_repo`) for the issue and `WINGET_PR_TOKEN` for the PR.
508
+ `WINGET_PR_TOKEN` needs `public_repo` plus `read:org` and `read:discussion`: `public_repo`
509
+ lets `wingetcreate` fork `microsoft/winget-pkgs` and open the PR, and the later `gh pr edit`
510
+ that sets the PR body runs a GraphQL query resolving org/team and discussion fields that
511
+ fails with a scope error on a `public_repo`-only token. The PR token is passed as
507
512
  `WINGET_CREATE_GITHUB_TOKEN` rather than `--token`, which wingetcreate warns can leak the
508
513
  token into logs. `wingetcreate update` only works on a package that already exists in
509
514
  `microsoft/winget-pkgs`, so the workflow checks the `manifests/g/getSigit/siGitCode` path
@@ -1,5 +1,51 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.9
4
+
5
+ ### Fixed
6
+
7
+ - **Doubled-bar DSML markers survive inline tool-call recovery.** Some models
8
+ write `||name||args||` (and single-bar `|name|args|`) instead of the
9
+ underscore-form `__name__args__` that `inline_tool_calls` was matching.
10
+ These were being dropped from the recovered reply and from history, so the
11
+ model thought its call had run. The scanner now accepts both forms, and
12
+ a buffer that contains no doubled bar skips the regex fold entirely
13
+ instead of allocating an empty `String`.
14
+
15
+ ### Changed
16
+
17
+ - **The release workflow is split into full-release and scoped-patch flows.**
18
+ `sigit-code-release` now leads with a scoped-patch path for one or two
19
+ commits on top of the last tag (no new release skill, no ACP advert,
20
+ no `## $version` requirement), then a full-release path for normal
21
+ development → `main` releases. Winget CI also gets a blank line between
22
+ the issue body and the manifest PR body so the rendered issue no longer
23
+ runs the two together.
24
+
25
+ ## 1.6.8
26
+
27
+ ### Fixed
28
+
29
+ - **A bare launch of `sigit.exe` on Windows exits 0 instead of bailing.** A
30
+ no-argument launch with a TTY stdin falls through to the non-Unix branch,
31
+ which has no TUI to start (the interactive client needs Unix-only fd
32
+ redirection). It now prints a short usage message pointing at ACP and
33
+ headless modes and exits 0, so winget's installer validator no longer reports
34
+ a `Validation-Executable-Error`.
35
+
36
+ ### Changed
37
+
38
+ - **winget submissions link back to their Package Request issue.** The release
39
+ workflow scrapes the winget-pkgs PR URL from wingetcreate, opens a Package
40
+ Request issue on first submission, and rewrites the PR body to fill the
41
+ Description, tick the issue checkbox, and add `Resolves #NNN` — replacing the
42
+ manual per-PR edit that used to follow each release.
43
+ - **The winget release workflow files its Package Request issue first and uses
44
+ two scoped tokens.** The Package Request issue is opened before the
45
+ winget-pkgs PR so the PR can reference it immediately, and issue creation and
46
+ PR submission now use separate tokens (`WINGET_ISSUE_TOKEN` and
47
+ `WINGET_PR_TOKEN`) rather than one shared token.
48
+
3
49
  ## 1.6.7
4
50
 
5
51
  ### Fixed
@@ -502,8 +502,13 @@ Three of these need credentials or a one-time manual step before they work:
502
502
 
503
503
  - Scoop needs a `getsigit/scoop-bucket` repo and a `SCOOP_BUCKET_TOKEN` secret, mirroring the
504
504
  Homebrew tap setup.
505
- - winget needs a `WINGET_TOKEN` (PAT with `public_repo` scope) so `wingetcreate` can fork
506
- `microsoft/winget-pkgs` and open the manifest PR. It is passed as
505
+ - winget files a Package Request issue first and then opens the manifest PR that resolves it,
506
+ authored by two separate classic PATs (replacing the old single `WINGET_TOKEN`):
507
+ `WINGET_ISSUE_TOKEN` (`public_repo`) for the issue and `WINGET_PR_TOKEN` for the PR.
508
+ `WINGET_PR_TOKEN` needs `public_repo` plus `read:org` and `read:discussion`: `public_repo`
509
+ lets `wingetcreate` fork `microsoft/winget-pkgs` and open the PR, and the later `gh pr edit`
510
+ that sets the PR body runs a GraphQL query resolving org/team and discussion fields that
511
+ fails with a scope error on a `public_repo`-only token. The PR token is passed as
507
512
  `WINGET_CREATE_GITHUB_TOKEN` rather than `--token`, which wingetcreate warns can leak the
508
513
  token into logs. `wingetcreate update` only works on a package that already exists in
509
514
  `microsoft/winget-pkgs`, so the workflow checks the `manifests/g/getSigit/siGitCode` path
@@ -5901,7 +5901,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
5901
5901
 
5902
5902
  [[package]]
5903
5903
  name = "sigit"
5904
- version = "1.6.7"
5904
+ version = "1.6.9"
5905
5905
  dependencies = [
5906
5906
  "agent-client-protocol",
5907
5907
  "anyhow",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sigit"
3
- version = "1.6.7"
3
+ version = "1.6.9"
4
4
  edition = "2024"
5
5
  description = "siGit Code — ACP-compatible AI coding agent. Sí, git."
6
6
  documentation = "https://github.com/getsigit/sigit"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sigit-code
3
- Version: 1.6.7
3
+ Version: 1.6.9
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers