release-skill 0.4.0 → 0.4.1
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.
- package/.claude-plugin/marketplace.json +6 -2
- package/.claude-plugin/plugin.json +2 -2
- package/.codebuddy-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +4 -4
- package/.kimi-plugin/plugin.json +3 -3
- package/CHANGELOG.md +13 -0
- package/INSTALL.md +2 -2
- package/INSTALL.zh-CN.md +2 -2
- package/LICENSE +183 -18
- package/NOTICE +4 -2
- package/README.md +32 -23
- package/README.zh-CN.md +25 -20
- package/adapters/claude/.claude-plugin/marketplace.json +6 -2
- package/adapters/claude/.claude-plugin/plugin.json +2 -2
- package/adapters/claude/bin/release-skill.bundle.mjs +20 -1
- package/adapters/claude/skills/release-setup/SKILL.md +6 -0
- package/adapters/codex/.codex-plugin/plugin.json +4 -4
- package/adapters/codex/bin/release-skill.bundle.mjs +20 -1
- package/adapters/codex/skills/release-setup/SKILL.md +6 -0
- package/adapters/kimi/.kimi-plugin/plugin.json +3 -3
- package/adapters/kimi/bin/release-skill.bundle.mjs +20 -1
- package/adapters/kimi/skills/release-setup/SKILL.md +6 -0
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +2 -2
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +20 -1
- package/adapters/workbuddy/skills/release-setup/SKILL.md +6 -0
- package/bin/release-skill.bundle.mjs +20 -1
- package/package.json +2 -2
- package/skills/release-setup/SKILL.md +6 -0
- package/skills-src/release-setup/SKILL.md +6 -0
- package/src/adapters/npm.mjs +31 -0
|
@@ -9,8 +9,12 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "release-skill",
|
|
11
11
|
"source": "./",
|
|
12
|
-
"version": "0.4.
|
|
13
|
-
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification"
|
|
12
|
+
"version": "0.4.1",
|
|
13
|
+
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "广州市风荷科技有限公司"
|
|
16
|
+
},
|
|
17
|
+
"license": "Apache-2.0"
|
|
14
18
|
}
|
|
15
19
|
]
|
|
16
20
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"skills": "./adapters/claude/skills/"
|
|
10
10
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"skills": [
|
|
10
10
|
"./adapters/workbuddy/skills/"
|
|
11
11
|
]
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"skills": "./adapters/codex/skills/",
|
|
10
10
|
"interface": {
|
|
11
11
|
"displayName": "Release Skill",
|
|
12
12
|
"shortDescription": "Safe preparation and frozen GitHub/npm publishing",
|
|
13
13
|
"longDescription": "Prepares byte-faithful public snapshots without rewriting project source files and publishes approved frozen GitHub/npm artifacts. Full happy end verification confirms consumer installation from frozen Git ref.",
|
|
14
|
-
"developerName": "
|
|
14
|
+
"developerName": "广州市风荷科技有限公司",
|
|
15
15
|
"category": "DevOps",
|
|
16
16
|
"capabilities": [
|
|
17
17
|
"Write",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"defaultPrompt": [
|
|
21
21
|
"Assess this project for release readiness.",
|
|
22
|
-
"Prepare a release plan for version 0.4.
|
|
22
|
+
"Prepare a release plan for version 0.4.1.",
|
|
23
23
|
"Help me understand the release workflow."
|
|
24
24
|
]
|
|
25
25
|
}
|
package/.kimi-plugin/plugin.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"homepage": "https://github.com/ifoohoo/release-skill#readme",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"release",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"displayName": "Release Skill",
|
|
22
22
|
"shortDescription": "Safe preparation and frozen GitHub/npm publishing",
|
|
23
23
|
"longDescription": "Prepares byte-faithful public snapshots without rewriting project source files and publishes approved frozen GitHub/npm artifacts. Full happy end verification confirms consumer installation from frozen Git ref.",
|
|
24
|
-
"developerName": "
|
|
24
|
+
"developerName": "广州市风荷科技有限公司",
|
|
25
25
|
"websiteURL": "https://github.com/ifoohoo/release-skill"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
<!-- release-skill:changelog:start version=0.4.1 locale=en baseline=sha256:e2ccb5ddfef6c5e00b047bbf4fa009f5f5c10b003aa2254756f6f9b73a9b3346 -->
|
|
4
|
+
## [0.4.1] - 2026-08-03
|
|
5
|
+
|
|
6
|
+
v0.4.1 is the unreleased source candidate that migrates release-skill to Apache License 2.0 and aligns public author metadata while preserving repository ownership and historical attribution.
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **Open-source license**: package, plugin manifests, README, LICENSE, and NOTICE now consistently use Apache-2.0.
|
|
11
|
+
- **Identity separation**: project author and developer metadata names 广州市风荷科技有限公司, while the `ifoohoo` repository and Marketplace owner coordinates remain unchanged.
|
|
12
|
+
- **Historical attribution**: existing contributor and company copyright notices remain; metadata and license changes do not assert a copyright transfer.
|
|
13
|
+
<!-- release-skill:changelog:end version=0.4.1 locale=en -->
|
|
14
|
+
|
|
15
|
+
|
|
3
16
|
<!-- release-skill:changelog:start version=0.4.0 locale=en baseline=sha256:099d9db24049aeaae78a21d3bd5152582bb20d4efad1ceff085f9609e8e6d52e -->
|
|
4
17
|
## [0.4.0] - 2026-08-02
|
|
5
18
|
|
package/INSTALL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](INSTALL.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.4.
|
|
5
|
+
<!-- release-skill:release-version: 0.4.1 -->
|
|
6
6
|
## Prerequisites
|
|
7
7
|
|
|
8
8
|
- Node.js 22.0.0 or later
|
|
@@ -114,7 +114,7 @@ tag pinned to the exact version (never the bare repository URL, which installs
|
|
|
114
114
|
the latest release or default branch), confirm the trust prompt, then reload:
|
|
115
115
|
|
|
116
116
|
```
|
|
117
|
-
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.4.
|
|
117
|
+
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.4.1
|
|
118
118
|
/plugins reload
|
|
119
119
|
```
|
|
120
120
|
|
package/INSTALL.zh-CN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](INSTALL.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.4.
|
|
5
|
+
<!-- release-skill:release-version: 0.4.1 -->
|
|
6
6
|
## 前置条件
|
|
7
7
|
|
|
8
8
|
- Node.js 22.0.0 或更高版本
|
|
@@ -104,7 +104,7 @@ Kimi Code 有交互式插件市场,但**没有可脚本化的非交互安装
|
|
|
104
104
|
(切勿使用裸仓库地址,它会安装最新 release 或默认分支),确认信任提示后重新加载:
|
|
105
105
|
|
|
106
106
|
```
|
|
107
|
-
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.4.
|
|
107
|
+
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.4.1
|
|
108
108
|
/plugins reload
|
|
109
109
|
```
|
|
110
110
|
|
package/LICENSE
CHANGED
|
@@ -1,22 +1,187 @@
|
|
|
1
|
-
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction, and
|
|
10
|
+
distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by the
|
|
13
|
+
copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all other
|
|
16
|
+
entities that control, are controlled by, or are under common control with
|
|
17
|
+
that entity. For the purposes of this definition, "control" means (i) the
|
|
18
|
+
power, direct or indirect, to cause the direction or management of such
|
|
19
|
+
entity, whether by contract or otherwise, or (ii) ownership of fifty percent
|
|
20
|
+
(50%) or more of the outstanding shares, or (iii) beneficial ownership of
|
|
21
|
+
such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
|
24
|
+
permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation source, and
|
|
28
|
+
configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical transformation
|
|
31
|
+
or translation of a Source form, including but not limited to compiled object
|
|
32
|
+
code, generated documentation, and conversions to other media types.
|
|
33
|
+
|
|
34
|
+
"Work" shall mean the work of authorship, whether in Source or Object form,
|
|
35
|
+
made available under the License, as indicated by a copyright notice that is
|
|
36
|
+
included in or attached to the work (an example is provided in the Appendix
|
|
37
|
+
below).
|
|
38
|
+
|
|
39
|
+
"Derivative Works" shall mean any work, whether in Source or Object form,
|
|
40
|
+
that is based on (or derived from) the Work and for which the editorial
|
|
41
|
+
revisions, annotations, elaborations, or other modifications represent, as a
|
|
42
|
+
whole, an original work of authorship. For the purposes of this License,
|
|
43
|
+
Derivative Works shall not include works that remain separable from, or merely
|
|
44
|
+
link (or bind by name) to the interfaces of, the Work and Derivative Works
|
|
45
|
+
thereof.
|
|
46
|
+
|
|
47
|
+
"Contribution" shall mean any work of authorship, including the original
|
|
48
|
+
version of the Work and any modifications or additions to that Work or
|
|
49
|
+
Derivative Works thereof, that is intentionally submitted to Licensor for
|
|
50
|
+
inclusion in the Work by the copyright owner or by an individual or Legal
|
|
51
|
+
Entity authorized to submit on behalf of the copyright owner. For the purposes
|
|
52
|
+
of this definition, "submitted" means any form of electronic, verbal, or
|
|
53
|
+
written communication sent to the Licensor or its representatives, including
|
|
54
|
+
but not limited to communication on electronic mailing lists, source code
|
|
55
|
+
control systems, and issue tracking systems that are managed by, or on behalf
|
|
56
|
+
of, the Licensor for the purpose of discussing and improving the Work, but
|
|
57
|
+
excluding communication that is conspicuously marked or otherwise designated
|
|
58
|
+
in writing by the copyright owner as "Not a Contribution."
|
|
59
|
+
|
|
60
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity on
|
|
61
|
+
behalf of whom a Contribution has been received by Licensor and subsequently
|
|
62
|
+
incorporated within the Work.
|
|
63
|
+
|
|
64
|
+
2. Grant of Copyright License. Subject to the terms and conditions of this
|
|
65
|
+
License, each Contributor hereby grants to You a perpetual, worldwide,
|
|
66
|
+
non-exclusive, no-charge, royalty-free, irrevocable copyright license to
|
|
67
|
+
reproduce, prepare Derivative Works of, publicly display, publicly perform,
|
|
68
|
+
sublicense, and distribute the Work and such Derivative Works in Source or
|
|
69
|
+
Object form.
|
|
70
|
+
|
|
71
|
+
3. Grant of Patent License. Subject to the terms and conditions of this
|
|
72
|
+
License, each Contributor hereby grants to You a perpetual, worldwide,
|
|
73
|
+
non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this
|
|
74
|
+
section) patent license to make, have made, use, offer to sell, sell, import,
|
|
75
|
+
and otherwise transfer the Work, where such license applies only to those
|
|
76
|
+
patent claims licensable by such Contributor that are necessarily infringed by
|
|
77
|
+
their Contribution(s) alone or by combination of their Contribution(s) with
|
|
78
|
+
the Work to which such Contribution(s) was submitted. If You institute patent
|
|
79
|
+
litigation against any entity (including a cross-claim or counterclaim in a
|
|
80
|
+
lawsuit) alleging that the Work or a Contribution incorporated within the Work
|
|
81
|
+
constitutes direct or contributory patent infringement, then any patent
|
|
82
|
+
licenses granted to You under this License for that Work shall terminate as of
|
|
83
|
+
the date such litigation is filed.
|
|
84
|
+
|
|
85
|
+
4. Redistribution. You may reproduce and distribute copies of the Work or
|
|
86
|
+
Derivative Works thereof in any medium, with or without modifications, and in
|
|
87
|
+
Source or Object form, provided that You meet the following conditions:
|
|
88
|
+
|
|
89
|
+
(a) You must give any other recipients of the Work or Derivative Works a copy
|
|
90
|
+
of this License; and
|
|
91
|
+
|
|
92
|
+
(b) You must cause any modified files to carry prominent notices stating that
|
|
93
|
+
You changed the files; and
|
|
94
|
+
|
|
95
|
+
(c) You must retain, in the Source form of any Derivative Works that You
|
|
96
|
+
distribute, all copyright, patent, trademark, and attribution notices from the
|
|
97
|
+
Source form of the Work, excluding those notices that do not pertain to any
|
|
98
|
+
part of the Derivative Works; and
|
|
99
|
+
|
|
100
|
+
(d) If the Work includes a "NOTICE" text file as part of its distribution,
|
|
101
|
+
then any Derivative Works that You distribute must include a readable copy of
|
|
102
|
+
the attribution notices contained within such NOTICE file, excluding those
|
|
103
|
+
notices that do not pertain to any part of the Derivative Works, in at least
|
|
104
|
+
one of the following places: within a NOTICE text file distributed as part of
|
|
105
|
+
the Derivative Works; within the Source form or documentation, if provided
|
|
106
|
+
along with the Derivative Works; or, within a display generated by the
|
|
107
|
+
Derivative Works, if and wherever such third-party notices normally appear.
|
|
108
|
+
The contents of the NOTICE file are for informational purposes only and do not
|
|
109
|
+
modify the License. You may add Your own attribution notices within Derivative
|
|
110
|
+
Works that You distribute, alongside or as an addendum to the NOTICE text from
|
|
111
|
+
the Work, provided that such additional attribution notices cannot be
|
|
112
|
+
construed as modifying the License.
|
|
113
|
+
|
|
114
|
+
You may add Your own copyright statement to Your modifications and may provide
|
|
115
|
+
additional or different license terms and conditions for use, reproduction, or
|
|
116
|
+
distribution of Your modifications, or for any such Derivative Works as a
|
|
117
|
+
whole, provided Your use, reproduction, and distribution of the Work otherwise
|
|
118
|
+
complies with the conditions stated in this License.
|
|
119
|
+
|
|
120
|
+
5. Submission of Contributions. Unless You explicitly state otherwise, any
|
|
121
|
+
Contribution intentionally submitted for inclusion in the Work by You to the
|
|
122
|
+
Licensor shall be under the terms and conditions of this License, without any
|
|
123
|
+
additional terms or conditions. Notwithstanding the above, nothing herein
|
|
124
|
+
shall supersede or modify the terms of any separate license agreement you may
|
|
125
|
+
have executed with Licensor regarding such Contributions.
|
|
126
|
+
|
|
127
|
+
6. Trademarks. This License does not grant permission to use the trade names,
|
|
128
|
+
trademarks, service marks, or product names of the Licensor, except as required
|
|
129
|
+
for reasonable and customary use in describing the origin of the Work and
|
|
130
|
+
reproducing the content of the NOTICE file.
|
|
131
|
+
|
|
132
|
+
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
|
|
133
|
+
writing, Licensor provides the Work (and each Contributor provides its
|
|
134
|
+
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
135
|
+
KIND, either express or implied, including, without limitation, any warranties
|
|
136
|
+
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
137
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
138
|
+
appropriateness of using or redistributing the Work and assume any risks
|
|
139
|
+
associated with Your exercise of permissions under this License.
|
|
140
|
+
|
|
141
|
+
8. Limitation of Liability. In no event and under no legal theory, whether in
|
|
142
|
+
tort (including negligence), contract, or otherwise, unless required by
|
|
143
|
+
applicable law (such as deliberate and grossly negligent acts) or agreed to in
|
|
144
|
+
writing, shall any Contributor be liable to You for damages, including any
|
|
145
|
+
direct, indirect, special, incidental, or consequential damages of any
|
|
146
|
+
character arising as a result of this License or out of the use or inability to
|
|
147
|
+
use the Work (including but not limited to damages for loss of goodwill, work
|
|
148
|
+
stoppage, computer failure or malfunction, or any and all other commercial
|
|
149
|
+
damages or losses), even if such Contributor has been advised of the
|
|
150
|
+
possibility of such damages.
|
|
151
|
+
|
|
152
|
+
9. Accepting Warranty or Additional Liability. While redistributing the Work
|
|
153
|
+
or Derivative Works thereof, You may choose to offer, and charge a fee for,
|
|
154
|
+
acceptance of support, warranty, indemnity, or other liability obligations
|
|
155
|
+
and/or rights consistent with this License. However, in accepting such
|
|
156
|
+
obligations, You may act only on Your own behalf and on Your sole
|
|
157
|
+
responsibility, not on behalf of any other Contributor, and only if You agree
|
|
158
|
+
to indemnify, defend, and hold each Contributor harmless for any liability
|
|
159
|
+
incurred by, or claims asserted against, such Contributor by reason of your
|
|
160
|
+
accepting any such warranty or additional liability.
|
|
161
|
+
|
|
162
|
+
END OF TERMS AND CONDITIONS
|
|
163
|
+
|
|
164
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
165
|
+
|
|
166
|
+
To apply the Apache License to your work, attach the following boilerplate
|
|
167
|
+
notice, with the fields enclosed by brackets "[]" replaced with your own
|
|
168
|
+
identifying information. (Don't include the brackets!) The text should be
|
|
169
|
+
enclosed in the appropriate comment syntax for the file format. We also
|
|
170
|
+
recommend that a file or class name and description of purpose be included on
|
|
171
|
+
the same "printed page" as the copyright notice for easier identification
|
|
172
|
+
within third-party archives.
|
|
2
173
|
|
|
3
174
|
Copyright (c) 2026 release-skill contributors
|
|
4
175
|
Copyright (c) 2026 广州市风荷科技有限公司
|
|
5
176
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
-
SOFTWARE.
|
|
177
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
178
|
+
you may not use this file except in compliance with the License.
|
|
179
|
+
You may obtain a copy of the License at
|
|
180
|
+
|
|
181
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
182
|
+
|
|
183
|
+
Unless required by applicable law or agreed to in writing, software
|
|
184
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
185
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
186
|
+
See the License for the specific language governing permissions and
|
|
187
|
+
limitations under the License.
|
package/NOTICE
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# Notice
|
|
2
2
|
|
|
3
|
-
release-skill is an open-source project released under the
|
|
3
|
+
release-skill is an open-source project released under the Apache License,
|
|
4
|
+
Version 2.0.
|
|
4
5
|
|
|
5
6
|
## Maintenance
|
|
6
7
|
|
|
7
8
|
release-skill is maintained by 广州市风荷科技有限公司 (Guangzhou Fenghe
|
|
8
9
|
Technology Co., Ltd.), together with the release-skill contributors. Copyright
|
|
9
10
|
in the project is held by the release-skill contributors and 广州市风荷科技
|
|
10
|
-
有限公司 as stated in the LICENSE file. The
|
|
11
|
+
有限公司 as stated in the LICENSE file. The 0.4.1 license change does not by
|
|
12
|
+
itself assign or transfer those historical rights. The transfer of the public GitHub
|
|
11
13
|
repository to the `ifoohoo` organization is an administrative change of the
|
|
12
14
|
hosting location and maintenance identity; it does not by itself constitute a
|
|
13
15
|
copyright assignment or transfer.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](README.zh-CN.md) · Installation: [English](INSTALL.md) / [简体中文](INSTALL.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.4.
|
|
5
|
+
<!-- release-skill:release-version: 0.4.1 -->
|
|
6
6
|
Release preparation for Claude Code, CodeBuddy, WorkBuddy, Codex, and Kimi Code, with human-edited files kept intact.
|
|
7
7
|
|
|
8
8
|
release-skill helps a maintainer answer three questions: what will be released,
|
|
@@ -14,26 +14,20 @@ Setup surfaces only the deterministic `compactSummary` review view; the full
|
|
|
14
14
|
report stays in a temporary session directory.
|
|
15
15
|
|
|
16
16
|
<!-- release-skill:managed:start id=latest-release -->
|
|
17
|
-
**0.4.
|
|
17
|
+
**0.4.1** (2026-08-03)
|
|
18
18
|
|
|
19
|
-
v0.4.
|
|
20
|
-
|
|
21
|
-
**Added**
|
|
22
|
-
|
|
23
|
-
- **Manual consumer follow-ups**: when Kimi or CodeBuddy cannot be installed automatically, the release records an installation task after publishing without requiring system attestation.
|
|
19
|
+
v0.4.1 is the unreleased source candidate that migrates release-skill to Apache License 2.0 and aligns public author metadata while preserving repository ownership and historical attribution.
|
|
24
20
|
|
|
25
21
|
**Changed**
|
|
26
22
|
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
|
|
30
|
-
**Removed**
|
|
31
|
-
|
|
32
|
-
- **Redundant confirmation flags**: legacy plan-digest repetition, production-confirmation, hook-authorization, and manual-attestation interactions were removed from the normal release path.
|
|
23
|
+
- **Open-source license**: package, plugin manifests, README, LICENSE, and NOTICE now consistently use Apache-2.0.
|
|
24
|
+
- **Identity separation**: project author and developer metadata names 广州市风荷科技有限公司, while the `ifoohoo` repository and Marketplace owner coordinates remain unchanged.
|
|
25
|
+
- **Historical attribution**: existing contributor and company copyright notices remain; metadata and license changes do not assert a copyright transfer.
|
|
33
26
|
<!-- release-skill:managed:end id=latest-release -->
|
|
34
27
|
|
|
35
28
|
<!-- release-skill:capability:external-write-boundary -->
|
|
36
|
-
> **Current boundary:** v0.4.
|
|
29
|
+
> **Current boundary:** v0.4.1 is the current source candidate; v0.4.0 remains
|
|
30
|
+
> the latest published release (v0.2.2 previously held
|
|
37
31
|
> published status before the platform verification convergence fix was added).
|
|
38
32
|
> v0.1.1 completed a real production release to GitHub and npm — the first
|
|
39
33
|
> production-verified milestone — followed by
|
|
@@ -51,8 +45,8 @@ v0.4.0 simplifies the production release path to one frozen-plan approval and mo
|
|
|
51
45
|
> publish global preflight.
|
|
52
46
|
|
|
53
47
|
<!-- release-skill:capability:safe-first-command -->
|
|
54
|
-
> **Production path verified since the v0.1.1 milestone; v0.4.
|
|
55
|
-
> release.** The npm-installed CLI is the supported user entry. Source checkout
|
|
48
|
+
> **Production path verified since the v0.1.1 milestone; v0.4.1 is the current
|
|
49
|
+
> source candidate and v0.4.0 is the latest published release.** The npm-installed CLI is the supported user entry. Source checkout
|
|
56
50
|
> is the development/contributor fallback.
|
|
57
51
|
>
|
|
58
52
|
> **Start here:**
|
|
@@ -62,7 +56,13 @@ v0.4.0 simplifies the production release path to one frozen-plan approval and mo
|
|
|
62
56
|
<!-- release-skill:maturity:v0.1-boundary -->
|
|
63
57
|
<!-- release-skill:maturity:boundary -->
|
|
64
58
|
> **Safe defaults:** the recommended path is `help → assess → prepare --offline →
|
|
65
|
-
> human review`.
|
|
59
|
+
> human review`. `help` and `assess` are read-only. The release-skill-owned part of
|
|
60
|
+
> `prepare --offline` writes only under `.release-skill/` and does not call remote
|
|
61
|
+
> publish adapters, but configured hooks and gates are unsandboxed processes: they
|
|
62
|
+
> may write outside the project, access credentials, make network calls, or publish.
|
|
63
|
+
> Treat `prepare` as local-only only when those processes are absent or separately
|
|
64
|
+
> audited and explicitly acknowledged. Production publishing uses
|
|
65
|
+
> `ship --target-version <ver> → ship --approve --actor <name>`.
|
|
66
66
|
> The `ship` command runs hooks and gates automatically; the only human gate is plan approval.
|
|
67
67
|
> Kimi/CodeBuddy installations are non-blocking manual follow-up tasks (not verified by system).
|
|
68
68
|
|
|
@@ -130,8 +130,11 @@ release-skill ship --root "$PROJECT" --approve --actor "$ACTOR" --json
|
|
|
130
130
|
During development, `release-skill hooks validate` runs declared hooks and
|
|
131
131
|
writes the same content-bound cache receipts that `prepare` consumes.
|
|
132
132
|
|
|
133
|
-
Run these steps in order. Steps 1-
|
|
134
|
-
|
|
133
|
+
Run these steps in order. Steps 1-3 are read-only. In step 4, release-skill's own
|
|
134
|
+
prepare pipeline is local-only and never invokes remote publish adapters; configured
|
|
135
|
+
hooks and gates remain arbitrary unsandboxed processes and can perform local or remote
|
|
136
|
+
side effects. Step 4 is therefore local-only only when those processes are absent or
|
|
137
|
+
separately audited and explicitly acknowledged. Steps 5-9 require explicit human gates.
|
|
135
138
|
|
|
136
139
|
```bash
|
|
137
140
|
CLI=(release-skill) # or: CLI=(node "$RELEASE_SKILL_HOME/packages/release-skill/bin/release-skill.mjs")
|
|
@@ -210,6 +213,9 @@ ACTOR=your-name
|
|
|
210
213
|
--actor "$ACTOR" --json)
|
|
211
214
|
APPROVAL_PATH=$(printf '%s\n' "$APPROVAL_JSON" | jq -r '.approvalPath')
|
|
212
215
|
```
|
|
216
|
+
`--actor` is an unauthenticated local audit string. It is not identity
|
|
217
|
+
verification, a signature, or proof that a particular human approved the plan;
|
|
218
|
+
use an external authenticated approval system when that assurance is required.
|
|
213
219
|
8. **publish** — remote writes start here:
|
|
214
220
|
```bash
|
|
215
221
|
PUBLISH_JSON=$("${CLI[@]}" publish --root "$PROJECT" \
|
|
@@ -276,9 +282,12 @@ but blocks a lost or reverted README by path. It never merges, switches
|
|
|
276
282
|
branches, pushes, or creates a PR.
|
|
277
283
|
|
|
278
284
|
**Write safety:** `setup` is read-only by default (create-once after digest
|
|
279
|
-
confirmation). `prepare` writes only under
|
|
280
|
-
|
|
281
|
-
|
|
285
|
+
confirmation). Release-skill's own `prepare` pipeline writes only under
|
|
286
|
+
`.release-skill/` and does not invoke remote publish adapters. Project hooks and
|
|
287
|
+
gates are acknowledged processes without an OS sandbox; they may write outside the
|
|
288
|
+
project, access credentials, make network calls, or publish. `publish` is the
|
|
289
|
+
release-skill-owned production write entry and requires both approval and the current
|
|
290
|
+
plan digest.
|
|
282
291
|
|
|
283
292
|
## Documentation
|
|
284
293
|
|
|
@@ -519,4 +528,4 @@ declaration is narrowed to concrete targets.
|
|
|
519
528
|
|
|
520
529
|
## License
|
|
521
530
|
|
|
522
|
-
|
|
531
|
+
Apache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
package/README.zh-CN.md
CHANGED
|
@@ -2,32 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) · 安装指南:[中文](INSTALL.zh-CN.md) / [English](INSTALL.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.4.
|
|
5
|
+
<!-- release-skill:release-version: 0.4.1 -->
|
|
6
6
|
面向 Claude Code、CodeBuddy、WorkBuddy、Codex 和 Kimi Code 的发布准备工具,完整保留人工维护的文件内容。
|
|
7
7
|
|
|
8
8
|
release-skill 帮助维护者回答三个问题:准备发布什么、还有哪些检查未通过、最终发布的内容是什么。它不重新生成、也不回写项目源文件。`prepare` 把每个配置的公开文件复制到隔离快照并验证字节——先冻结并供人工审阅,再从同一份冻结产物发布。`setup` 只显示确定性的 `compactSummary` 审阅视图,完整报告保留在临时会话目录中。
|
|
9
9
|
|
|
10
10
|
<!-- release-skill:managed:start id=latest-release -->
|
|
11
|
-
**0.4.
|
|
11
|
+
**0.4.1** (2026-08-03)
|
|
12
12
|
|
|
13
|
-
v0.4.
|
|
14
|
-
|
|
15
|
-
**新增**
|
|
16
|
-
|
|
17
|
-
- **人工消费者后续任务**:Kimi 或 CodeBuddy 无法自动安装时,发布完成后记录人工安装待办,系统不再要求安装证明。
|
|
13
|
+
v0.4.1 是尚未发布的源码候选:将 release-skill 调整为 Apache License 2.0,并统一公开作者元数据,同时保留仓库 owner 与历史归属。
|
|
18
14
|
|
|
19
15
|
**变更**
|
|
20
16
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
**移除**
|
|
25
|
-
|
|
26
|
-
- **冗余确认参数**:普通发布路径移除了重复输入 plan digest、production confirmation、hook authorization 和人工证明等交互。
|
|
17
|
+
- **开源许可证**:package、插件清单、README、LICENSE 与 NOTICE 统一使用 Apache-2.0。
|
|
18
|
+
- **身份分层**:项目作者和开发者字段使用广州市风荷科技有限公司,`ifoohoo` 仓库与 Marketplace owner 坐标保持不变。
|
|
19
|
+
- **历史归属**:继续保留贡献者和公司的既有版权声明;元数据与许可证变化不声明版权转让。
|
|
27
20
|
<!-- release-skill:managed:end id=latest-release -->
|
|
28
21
|
|
|
29
22
|
<!-- release-skill:capability:external-write-boundary -->
|
|
30
|
-
> **当前边界:** v0.4.0
|
|
23
|
+
> **当前边界:** v0.4.1 是当前源码候选,v0.4.0 仍是最新已发布版本(v0.2.2 曾处于已发布状态,后因平台验证收敛修复而更新)。
|
|
31
24
|
> v0.1.1 已完成 GitHub 与 npm 的
|
|
32
25
|
> 真实生产发布,是首次生产验证的历史里程碑,并从冻结 Git ref 完成精确 npm
|
|
33
26
|
> 安装及 Claude/Codex 消费者安装验证;"当前发布版本"与"首次生产验证里程碑"
|
|
@@ -40,7 +33,7 @@ v0.4.0 将生产发布收敛为一次冻结计划批准,并把无法自动安
|
|
|
40
33
|
> 远端唯一性检查在 `publish` 全局预检执行。
|
|
41
34
|
|
|
42
35
|
<!-- release-skill:capability:safe-first-command -->
|
|
43
|
-
> **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.4.0
|
|
36
|
+
> **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.4.1 是当前源码候选,v0.4.0 是最新已发布版本。**
|
|
44
37
|
> npm 安装的 CLI 是受支持的用户入口;源码 checkout 保留为开发/贡献者路径。
|
|
45
38
|
>
|
|
46
39
|
> **第一条命令:**
|
|
@@ -49,8 +42,12 @@ v0.4.0 将生产发布收敛为一次冻结计划批准,并把无法自动安
|
|
|
49
42
|
|
|
50
43
|
<!-- release-skill:maturity:v0.1-boundary -->
|
|
51
44
|
<!-- release-skill:maturity:boundary -->
|
|
52
|
-
> **安全默认路径:** 推荐 `help → assess → prepare --offline →
|
|
53
|
-
>
|
|
45
|
+
> **安全默认路径:** 推荐 `help → assess → prepare --offline → 人工审阅`。
|
|
46
|
+
> `help` 与 `assess` 只读;`prepare --offline` 中由 release-skill 自身控制的部分只写
|
|
47
|
+
> `.release-skill/`,且不调用远端发布适配器。但配置的 hook 和 gate 是无操作系统沙箱的进程,
|
|
48
|
+
> 可以写出项目目录、访问凭据、发起网络请求或执行远端发布。只有未配置这些进程,或已单独审计并
|
|
49
|
+
> 显式确认其副作用时,才可以把 `prepare` 视为“仅本地”。生产发布使用
|
|
50
|
+
> `ship --target-version <ver> → ship --approve --actor <name>`。
|
|
54
51
|
> `ship` 自动执行 hooks 和门禁,唯一的人工门禁是计划批准。
|
|
55
52
|
> Kimi/CodeBuddy 安装是非阻塞的人工后续任务(系统不核验)。
|
|
56
53
|
|
|
@@ -117,7 +114,10 @@ release-skill ship --root "$PROJECT" --approve --actor "$ACTOR" --json
|
|
|
117
114
|
开发阶段可运行 `release-skill hooks validate`;它会执行声明的 hooks,并写入
|
|
118
115
|
`prepare` 可复用的内容绑定收据。
|
|
119
116
|
|
|
120
|
-
按以下顺序执行。步骤 1-4
|
|
117
|
+
按以下顺序执行。步骤 1-3 只读。步骤 4 中,release-skill 自身的 prepare 流水线仅在本地写入,
|
|
118
|
+
且不会调用远端发布适配器;配置的 hook 和 gate 仍是可产生本地或远端副作用的任意无沙箱进程。
|
|
119
|
+
只有这些进程不存在,或已单独审计并显式确认副作用时,步骤 4 才能视为“仅本地”。步骤 5-9
|
|
120
|
+
需要显式人工门禁。
|
|
121
121
|
|
|
122
122
|
```bash
|
|
123
123
|
CLI=(release-skill) # 或:CLI=(node "$RELEASE_SKILL_HOME/packages/release-skill/bin/release-skill.mjs")
|
|
@@ -193,6 +193,8 @@ ACTOR=your-name
|
|
|
193
193
|
--actor "$ACTOR" --json)
|
|
194
194
|
APPROVAL_PATH=$(printf '%s\n' "$APPROVAL_JSON" | jq -r '.approvalPath')
|
|
195
195
|
```
|
|
196
|
+
`--actor` 只是未经身份认证的本地审计字符串,不是身份核验、数字签名,也不能证明某位特定人员
|
|
197
|
+
已批准计划;需要此类保证时,应接入外部已认证的审批系统。
|
|
196
198
|
8. **publish** — 远端写入开始:
|
|
197
199
|
```bash
|
|
198
200
|
PUBLISH_JSON=$("${CLI[@]}" publish --root "$PROJECT" \
|
|
@@ -237,7 +239,10 @@ DISCOVERED -> ASSESSED -> PREPARED -> APPROVED -> PUBLISHING -> PUBLISHED -> VER
|
|
|
237
239
|
|
|
238
240
|
**保存契约:** release-skill 不重新生成或回写项目源文件。`prepare` 把每个配置的公开文件复制到隔离快照并验证字节。后续 prepare 重新读取当前文件,不会从模板重建。只有 `publicFiles` 列出的文件会被复制。`prepare` 不会刷新或重写人工文档——维护者先更新 README、INSTALL 和 CHANGELOG,再 prepare、审阅和批准。
|
|
239
241
|
|
|
240
|
-
**写入安全:** `setup`
|
|
242
|
+
**写入安全:** `setup` 默认只读(摘要确认后仅首次创建配置)。release-skill 自身的 `prepare`
|
|
243
|
+
流水线只写 `.release-skill/`,且不调用远端发布适配器。项目 hook 和 gate 在对应命令调用时获得
|
|
244
|
+
授权,但没有操作系统沙箱;它们可以写出项目目录、访问凭据、发起网络请求或执行远端发布。
|
|
245
|
+
`publish` 是 release-skill 自身的生产写入入口,需要有效批准;内部计划摘要由系统自动绑定和校验。
|
|
241
246
|
|
|
242
247
|
**Workspace 源码权威:** 生产配置使用 `project.sourceRepository` 指定 workspace
|
|
243
248
|
源仓库,并用 `project.defaultBranch` 指定其真实远端默认分支。prepare 冻结所有
|
|
@@ -463,4 +468,4 @@ hook 在 `prepare` 调用时运行,命令调用本身即授权执行。gate
|
|
|
463
468
|
|
|
464
469
|
## 许可证
|
|
465
470
|
|
|
466
|
-
|
|
471
|
+
Apache License 2.0,见 [LICENSE](LICENSE) 与 [NOTICE](NOTICE)。
|
|
@@ -9,8 +9,12 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "release-skill",
|
|
11
11
|
"source": "./",
|
|
12
|
-
"version": "0.4.
|
|
13
|
-
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification"
|
|
12
|
+
"version": "0.4.1",
|
|
13
|
+
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "广州市风荷科技有限公司"
|
|
16
|
+
},
|
|
17
|
+
"license": "Apache-2.0"
|
|
14
18
|
}
|
|
15
19
|
]
|
|
16
20
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"skills": "./skills/"
|
|
10
10
|
}
|
|
@@ -9,7 +9,7 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.1"});
|
|
13
13
|
|
|
14
14
|
var __create = Object.create;
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
@@ -71134,6 +71134,7 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71134
71134
|
}
|
|
71135
71135
|
let offset = 0;
|
|
71136
71136
|
let manifest = null;
|
|
71137
|
+
let readme = null;
|
|
71137
71138
|
while (offset + 512 <= data.length) {
|
|
71138
71139
|
let allZero = true;
|
|
71139
71140
|
for (let i = 0; i < 512; i++) {
|
|
@@ -71183,6 +71184,20 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71183
71184
|
throw new Error(`tarball manifest version "${manifest.version}" does not match expected "${expected.version}"`);
|
|
71184
71185
|
}
|
|
71185
71186
|
}
|
|
71187
|
+
if (entryName.toLowerCase() === "package/readme.md") {
|
|
71188
|
+
if (readme) throw new Error("tarball contains conflicting package README entries");
|
|
71189
|
+
if (!(typeFlag === 0 || typeFlag === 48)) {
|
|
71190
|
+
throw new Error("tarball package README must be a regular file");
|
|
71191
|
+
}
|
|
71192
|
+
const bodyStart = offset + 512;
|
|
71193
|
+
const bodyEnd = bodyStart + size;
|
|
71194
|
+
if (bodyEnd > data.length) throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
71195
|
+
if (size > 10 * 1024 * 1024) throw new Error("tarball package README is unreasonably large");
|
|
71196
|
+
readme = {
|
|
71197
|
+
content: data.subarray(bodyStart, bodyEnd).toString("utf8"),
|
|
71198
|
+
filename: entryName.slice("package/".length)
|
|
71199
|
+
};
|
|
71200
|
+
}
|
|
71186
71201
|
const nextOffset = offset + 512 + Math.ceil(size / 512) * 512;
|
|
71187
71202
|
if (!Number.isSafeInteger(nextOffset) || nextOffset > data.length) {
|
|
71188
71203
|
throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
@@ -71190,6 +71205,10 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71190
71205
|
offset = nextOffset;
|
|
71191
71206
|
}
|
|
71192
71207
|
if (!manifest) throw new Error("tarball does not contain package/package.json");
|
|
71208
|
+
if (readme) {
|
|
71209
|
+
manifest.readme = readme.content;
|
|
71210
|
+
manifest.readmeFilename = readme.filename;
|
|
71211
|
+
}
|
|
71193
71212
|
return manifest;
|
|
71194
71213
|
}
|
|
71195
71214
|
async function verifyFrozenNpmTarballIdentity(action, root) {
|
|
@@ -91,6 +91,12 @@ node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>
|
|
|
91
91
|
node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
## publisher 字段与个人片段泄漏策略
|
|
95
|
+
|
|
96
|
+
setup 生成的 `.release-skill/project.yaml` 中 `publisher` 是**已批准的公开发布身份**:它是人工确认的对外发布署名,属于公开面的一部分,而非需要隐藏的私有信息。
|
|
97
|
+
|
|
98
|
+
若目标仓库用“个人片段”类泄漏策略扫描仓树,而该策略按片段匹配恰好覆盖到 `publisher` 字段,正确做法不是删除或改写策略,而是由贡献者在**本地、gitignore 的个人片段 overlay** 中为该规则声明位置豁免(如 `approvedPlacements`:限定 `publisher` 所在的确切文件路径与行键前缀)。豁免只放行已批准的放置位置,其余出现照常命中;overlay 不入库,个人片段本身不进 committed 策略。
|
|
99
|
+
|
|
94
100
|
## 故障路由
|
|
95
101
|
|
|
96
102
|
- `NEEDS_INPUT`:审阅紧凑摘要;有冲突先修正权威事实并重跑。
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"skills": "./skills/",
|
|
10
10
|
"interface": {
|
|
11
11
|
"displayName": "Release Skill",
|
|
12
12
|
"shortDescription": "Safe preparation and frozen GitHub/npm publishing",
|
|
13
13
|
"longDescription": "Prepares byte-faithful public snapshots without rewriting project source files and publishes approved frozen GitHub/npm artifacts. Full happy end verification confirms consumer installation from frozen Git ref.",
|
|
14
|
-
"developerName": "
|
|
14
|
+
"developerName": "广州市风荷科技有限公司",
|
|
15
15
|
"category": "DevOps",
|
|
16
16
|
"capabilities": [
|
|
17
17
|
"Write",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"defaultPrompt": [
|
|
21
21
|
"Assess this project for release readiness.",
|
|
22
|
-
"Prepare a release plan for version 0.4.
|
|
22
|
+
"Prepare a release plan for version 0.4.1.",
|
|
23
23
|
"Help me understand the release workflow."
|
|
24
24
|
]
|
|
25
25
|
}
|
|
@@ -9,7 +9,7 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.1"});
|
|
13
13
|
|
|
14
14
|
var __create = Object.create;
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
@@ -71134,6 +71134,7 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71134
71134
|
}
|
|
71135
71135
|
let offset = 0;
|
|
71136
71136
|
let manifest = null;
|
|
71137
|
+
let readme = null;
|
|
71137
71138
|
while (offset + 512 <= data.length) {
|
|
71138
71139
|
let allZero = true;
|
|
71139
71140
|
for (let i = 0; i < 512; i++) {
|
|
@@ -71183,6 +71184,20 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71183
71184
|
throw new Error(`tarball manifest version "${manifest.version}" does not match expected "${expected.version}"`);
|
|
71184
71185
|
}
|
|
71185
71186
|
}
|
|
71187
|
+
if (entryName.toLowerCase() === "package/readme.md") {
|
|
71188
|
+
if (readme) throw new Error("tarball contains conflicting package README entries");
|
|
71189
|
+
if (!(typeFlag === 0 || typeFlag === 48)) {
|
|
71190
|
+
throw new Error("tarball package README must be a regular file");
|
|
71191
|
+
}
|
|
71192
|
+
const bodyStart = offset + 512;
|
|
71193
|
+
const bodyEnd = bodyStart + size;
|
|
71194
|
+
if (bodyEnd > data.length) throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
71195
|
+
if (size > 10 * 1024 * 1024) throw new Error("tarball package README is unreasonably large");
|
|
71196
|
+
readme = {
|
|
71197
|
+
content: data.subarray(bodyStart, bodyEnd).toString("utf8"),
|
|
71198
|
+
filename: entryName.slice("package/".length)
|
|
71199
|
+
};
|
|
71200
|
+
}
|
|
71186
71201
|
const nextOffset = offset + 512 + Math.ceil(size / 512) * 512;
|
|
71187
71202
|
if (!Number.isSafeInteger(nextOffset) || nextOffset > data.length) {
|
|
71188
71203
|
throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
@@ -71190,6 +71205,10 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71190
71205
|
offset = nextOffset;
|
|
71191
71206
|
}
|
|
71192
71207
|
if (!manifest) throw new Error("tarball does not contain package/package.json");
|
|
71208
|
+
if (readme) {
|
|
71209
|
+
manifest.readme = readme.content;
|
|
71210
|
+
manifest.readmeFilename = readme.filename;
|
|
71211
|
+
}
|
|
71193
71212
|
return manifest;
|
|
71194
71213
|
}
|
|
71195
71214
|
async function verifyFrozenNpmTarballIdentity(action, root) {
|
|
@@ -98,6 +98,12 @@ node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>
|
|
|
98
98
|
node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
## publisher 字段与个人片段泄漏策略
|
|
102
|
+
|
|
103
|
+
setup 生成的 `.release-skill/project.yaml` 中 `publisher` 是**已批准的公开发布身份**:它是人工确认的对外发布署名,属于公开面的一部分,而非需要隐藏的私有信息。
|
|
104
|
+
|
|
105
|
+
若目标仓库用“个人片段”类泄漏策略扫描仓树,而该策略按片段匹配恰好覆盖到 `publisher` 字段,正确做法不是删除或改写策略,而是由贡献者在**本地、gitignore 的个人片段 overlay** 中为该规则声明位置豁免(如 `approvedPlacements`:限定 `publisher` 所在的确切文件路径与行键前缀)。豁免只放行已批准的放置位置,其余出现照常命中;overlay 不入库,个人片段本身不进 committed 策略。
|
|
106
|
+
|
|
101
107
|
## 故障路由
|
|
102
108
|
|
|
103
109
|
- `NEEDS_INPUT`:审阅紧凑摘要;有冲突先修正权威事实并重跑。
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"homepage": "https://github.com/ifoohoo/release-skill#readme",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"release",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"displayName": "Release Skill",
|
|
22
22
|
"shortDescription": "Safe preparation and frozen GitHub/npm publishing",
|
|
23
23
|
"longDescription": "Prepares byte-faithful public snapshots without rewriting project source files and publishes approved frozen GitHub/npm artifacts. Full happy end verification confirms consumer installation from frozen Git ref.",
|
|
24
|
-
"developerName": "
|
|
24
|
+
"developerName": "广州市风荷科技有限公司",
|
|
25
25
|
"websiteURL": "https://github.com/ifoohoo/release-skill"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -9,7 +9,7 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.1"});
|
|
13
13
|
|
|
14
14
|
var __create = Object.create;
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
@@ -71134,6 +71134,7 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71134
71134
|
}
|
|
71135
71135
|
let offset = 0;
|
|
71136
71136
|
let manifest = null;
|
|
71137
|
+
let readme = null;
|
|
71137
71138
|
while (offset + 512 <= data.length) {
|
|
71138
71139
|
let allZero = true;
|
|
71139
71140
|
for (let i = 0; i < 512; i++) {
|
|
@@ -71183,6 +71184,20 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71183
71184
|
throw new Error(`tarball manifest version "${manifest.version}" does not match expected "${expected.version}"`);
|
|
71184
71185
|
}
|
|
71185
71186
|
}
|
|
71187
|
+
if (entryName.toLowerCase() === "package/readme.md") {
|
|
71188
|
+
if (readme) throw new Error("tarball contains conflicting package README entries");
|
|
71189
|
+
if (!(typeFlag === 0 || typeFlag === 48)) {
|
|
71190
|
+
throw new Error("tarball package README must be a regular file");
|
|
71191
|
+
}
|
|
71192
|
+
const bodyStart = offset + 512;
|
|
71193
|
+
const bodyEnd = bodyStart + size;
|
|
71194
|
+
if (bodyEnd > data.length) throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
71195
|
+
if (size > 10 * 1024 * 1024) throw new Error("tarball package README is unreasonably large");
|
|
71196
|
+
readme = {
|
|
71197
|
+
content: data.subarray(bodyStart, bodyEnd).toString("utf8"),
|
|
71198
|
+
filename: entryName.slice("package/".length)
|
|
71199
|
+
};
|
|
71200
|
+
}
|
|
71186
71201
|
const nextOffset = offset + 512 + Math.ceil(size / 512) * 512;
|
|
71187
71202
|
if (!Number.isSafeInteger(nextOffset) || nextOffset > data.length) {
|
|
71188
71203
|
throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
@@ -71190,6 +71205,10 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71190
71205
|
offset = nextOffset;
|
|
71191
71206
|
}
|
|
71192
71207
|
if (!manifest) throw new Error("tarball does not contain package/package.json");
|
|
71208
|
+
if (readme) {
|
|
71209
|
+
manifest.readme = readme.content;
|
|
71210
|
+
manifest.readmeFilename = readme.filename;
|
|
71211
|
+
}
|
|
71193
71212
|
return manifest;
|
|
71194
71213
|
}
|
|
71195
71214
|
async function verifyFrozenNpmTarballIdentity(action, root) {
|
|
@@ -98,6 +98,12 @@ node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>
|
|
|
98
98
|
node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
## publisher 字段与个人片段泄漏策略
|
|
102
|
+
|
|
103
|
+
setup 生成的 `.release-skill/project.yaml` 中 `publisher` 是**已批准的公开发布身份**:它是人工确认的对外发布署名,属于公开面的一部分,而非需要隐藏的私有信息。
|
|
104
|
+
|
|
105
|
+
若目标仓库用“个人片段”类泄漏策略扫描仓树,而该策略按片段匹配恰好覆盖到 `publisher` 字段,正确做法不是删除或改写策略,而是由贡献者在**本地、gitignore 的个人片段 overlay** 中为该规则声明位置豁免(如 `approvedPlacements`:限定 `publisher` 所在的确切文件路径与行键前缀)。豁免只放行已批准的放置位置,其余出现照常命中;overlay 不入库,个人片段本身不进 committed 策略。
|
|
106
|
+
|
|
101
107
|
## 故障路由
|
|
102
108
|
|
|
103
109
|
- `NEEDS_INPUT`:审阅紧凑摘要;有冲突先修正权威事实并重跑。
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
7
7
|
},
|
|
8
|
-
"license": "
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
9
|
"skills": [
|
|
10
10
|
"./skills/"
|
|
11
11
|
]
|
|
@@ -9,7 +9,7 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.1"});
|
|
13
13
|
|
|
14
14
|
var __create = Object.create;
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
@@ -71134,6 +71134,7 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71134
71134
|
}
|
|
71135
71135
|
let offset = 0;
|
|
71136
71136
|
let manifest = null;
|
|
71137
|
+
let readme = null;
|
|
71137
71138
|
while (offset + 512 <= data.length) {
|
|
71138
71139
|
let allZero = true;
|
|
71139
71140
|
for (let i = 0; i < 512; i++) {
|
|
@@ -71183,6 +71184,20 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71183
71184
|
throw new Error(`tarball manifest version "${manifest.version}" does not match expected "${expected.version}"`);
|
|
71184
71185
|
}
|
|
71185
71186
|
}
|
|
71187
|
+
if (entryName.toLowerCase() === "package/readme.md") {
|
|
71188
|
+
if (readme) throw new Error("tarball contains conflicting package README entries");
|
|
71189
|
+
if (!(typeFlag === 0 || typeFlag === 48)) {
|
|
71190
|
+
throw new Error("tarball package README must be a regular file");
|
|
71191
|
+
}
|
|
71192
|
+
const bodyStart = offset + 512;
|
|
71193
|
+
const bodyEnd = bodyStart + size;
|
|
71194
|
+
if (bodyEnd > data.length) throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
71195
|
+
if (size > 10 * 1024 * 1024) throw new Error("tarball package README is unreasonably large");
|
|
71196
|
+
readme = {
|
|
71197
|
+
content: data.subarray(bodyStart, bodyEnd).toString("utf8"),
|
|
71198
|
+
filename: entryName.slice("package/".length)
|
|
71199
|
+
};
|
|
71200
|
+
}
|
|
71186
71201
|
const nextOffset = offset + 512 + Math.ceil(size / 512) * 512;
|
|
71187
71202
|
if (!Number.isSafeInteger(nextOffset) || nextOffset > data.length) {
|
|
71188
71203
|
throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
@@ -71190,6 +71205,10 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71190
71205
|
offset = nextOffset;
|
|
71191
71206
|
}
|
|
71192
71207
|
if (!manifest) throw new Error("tarball does not contain package/package.json");
|
|
71208
|
+
if (readme) {
|
|
71209
|
+
manifest.readme = readme.content;
|
|
71210
|
+
manifest.readmeFilename = readme.filename;
|
|
71211
|
+
}
|
|
71193
71212
|
return manifest;
|
|
71194
71213
|
}
|
|
71195
71214
|
async function verifyFrozenNpmTarballIdentity(action, root) {
|
|
@@ -91,6 +91,12 @@ node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>
|
|
|
91
91
|
node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
## publisher 字段与个人片段泄漏策略
|
|
95
|
+
|
|
96
|
+
setup 生成的 `.release-skill/project.yaml` 中 `publisher` 是**已批准的公开发布身份**:它是人工确认的对外发布署名,属于公开面的一部分,而非需要隐藏的私有信息。
|
|
97
|
+
|
|
98
|
+
若目标仓库用“个人片段”类泄漏策略扫描仓树,而该策略按片段匹配恰好覆盖到 `publisher` 字段,正确做法不是删除或改写策略,而是由贡献者在**本地、gitignore 的个人片段 overlay** 中为该规则声明位置豁免(如 `approvedPlacements`:限定 `publisher` 所在的确切文件路径与行键前缀)。豁免只放行已批准的放置位置,其余出现照常命中;overlay 不入库,个人片段本身不进 committed 策略。
|
|
99
|
+
|
|
94
100
|
## 故障路由
|
|
95
101
|
|
|
96
102
|
- `NEEDS_INPUT`:审阅紧凑摘要;有冲突先修正权威事实并重跑。
|
|
@@ -9,7 +9,7 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.1"});
|
|
13
13
|
|
|
14
14
|
var __create = Object.create;
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
@@ -71134,6 +71134,7 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71134
71134
|
}
|
|
71135
71135
|
let offset = 0;
|
|
71136
71136
|
let manifest = null;
|
|
71137
|
+
let readme = null;
|
|
71137
71138
|
while (offset + 512 <= data.length) {
|
|
71138
71139
|
let allZero = true;
|
|
71139
71140
|
for (let i = 0; i < 512; i++) {
|
|
@@ -71183,6 +71184,20 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71183
71184
|
throw new Error(`tarball manifest version "${manifest.version}" does not match expected "${expected.version}"`);
|
|
71184
71185
|
}
|
|
71185
71186
|
}
|
|
71187
|
+
if (entryName.toLowerCase() === "package/readme.md") {
|
|
71188
|
+
if (readme) throw new Error("tarball contains conflicting package README entries");
|
|
71189
|
+
if (!(typeFlag === 0 || typeFlag === 48)) {
|
|
71190
|
+
throw new Error("tarball package README must be a regular file");
|
|
71191
|
+
}
|
|
71192
|
+
const bodyStart = offset + 512;
|
|
71193
|
+
const bodyEnd = bodyStart + size;
|
|
71194
|
+
if (bodyEnd > data.length) throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
71195
|
+
if (size > 10 * 1024 * 1024) throw new Error("tarball package README is unreasonably large");
|
|
71196
|
+
readme = {
|
|
71197
|
+
content: data.subarray(bodyStart, bodyEnd).toString("utf8"),
|
|
71198
|
+
filename: entryName.slice("package/".length)
|
|
71199
|
+
};
|
|
71200
|
+
}
|
|
71186
71201
|
const nextOffset = offset + 512 + Math.ceil(size / 512) * 512;
|
|
71187
71202
|
if (!Number.isSafeInteger(nextOffset) || nextOffset > data.length) {
|
|
71188
71203
|
throw new Error("frozen npm tarball entry exceeds archive bounds");
|
|
@@ -71190,6 +71205,10 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
71190
71205
|
offset = nextOffset;
|
|
71191
71206
|
}
|
|
71192
71207
|
if (!manifest) throw new Error("tarball does not contain package/package.json");
|
|
71208
|
+
if (readme) {
|
|
71209
|
+
manifest.readme = readme.content;
|
|
71210
|
+
manifest.readmeFilename = readme.filename;
|
|
71211
|
+
}
|
|
71193
71212
|
return manifest;
|
|
71194
71213
|
}
|
|
71195
71214
|
async function verifyFrozenNpmTarballIdentity(action, root) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"codex",
|
|
95
95
|
"kimi-code"
|
|
96
96
|
],
|
|
97
|
-
"license": "
|
|
97
|
+
"license": "Apache-2.0"
|
|
98
98
|
}
|
|
@@ -91,6 +91,12 @@ node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>
|
|
|
91
91
|
node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
## publisher 字段与个人片段泄漏策略
|
|
95
|
+
|
|
96
|
+
setup 生成的 `.release-skill/project.yaml` 中 `publisher` 是**已批准的公开发布身份**:它是人工确认的对外发布署名,属于公开面的一部分,而非需要隐藏的私有信息。
|
|
97
|
+
|
|
98
|
+
若目标仓库用“个人片段”类泄漏策略扫描仓树,而该策略按片段匹配恰好覆盖到 `publisher` 字段,正确做法不是删除或改写策略,而是由贡献者在**本地、gitignore 的个人片段 overlay** 中为该规则声明位置豁免(如 `approvedPlacements`:限定 `publisher` 所在的确切文件路径与行键前缀)。豁免只放行已批准的放置位置,其余出现照常命中;overlay 不入库,个人片段本身不进 committed 策略。
|
|
99
|
+
|
|
94
100
|
## 故障路由
|
|
95
101
|
|
|
96
102
|
- `NEEDS_INPUT`:审阅紧凑摘要;有冲突先修正权威事实并重跑。
|
|
@@ -91,6 +91,12 @@ node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>
|
|
|
91
91
|
node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
## publisher 字段与个人片段泄漏策略
|
|
95
|
+
|
|
96
|
+
setup 生成的 `.release-skill/project.yaml` 中 `publisher` 是**已批准的公开发布身份**:它是人工确认的对外发布署名,属于公开面的一部分,而非需要隐藏的私有信息。
|
|
97
|
+
|
|
98
|
+
若目标仓库用“个人片段”类泄漏策略扫描仓树,而该策略按片段匹配恰好覆盖到 `publisher` 字段,正确做法不是删除或改写策略,而是由贡献者在**本地、gitignore 的个人片段 overlay** 中为该规则声明位置豁免(如 `approvedPlacements`:限定 `publisher` 所在的确切文件路径与行键前缀)。豁免只放行已批准的放置位置,其余出现照常命中;overlay 不入库,个人片段本身不进 committed 策略。
|
|
99
|
+
|
|
94
100
|
## 故障路由
|
|
95
101
|
|
|
96
102
|
- `NEEDS_INPUT`:审阅紧凑摘要;有冲突先修正权威事实并重跑。
|
package/src/adapters/npm.mjs
CHANGED
|
@@ -257,6 +257,13 @@ async function readVerifiedTarballBytes(action, root) {
|
|
|
257
257
|
* is missing, not valid JSON, or the extracted name/version do not match the
|
|
258
258
|
* expected action values.
|
|
259
259
|
*
|
|
260
|
+
* When the tarball contains a package/README.md entry (matched
|
|
261
|
+
* case-insensitively), its content is injected as manifest.readme and its
|
|
262
|
+
* real entry file name as manifest.readmeFilename, so the registry listing
|
|
263
|
+
* displays the package README. Ambiguous or unsafe README entries
|
|
264
|
+
* (duplicate or case-colliding names, non-regular files, out-of-bounds or
|
|
265
|
+
* oversized bodies) fail closed instead of being treated as metadata.
|
|
266
|
+
*
|
|
260
267
|
* @param {Buffer} tarballBuffer - the raw tarball bytes (gzipped or plain tar)
|
|
261
268
|
* @param {{ name: string, version: string }} expected - must match manifest
|
|
262
269
|
* @returns {object} the parsed package.json manifest
|
|
@@ -275,6 +282,7 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
275
282
|
// Walk tar entries to find package/package.json
|
|
276
283
|
let offset = 0;
|
|
277
284
|
let manifest = null;
|
|
285
|
+
let readme = null;
|
|
278
286
|
while (offset + 512 <= data.length) {
|
|
279
287
|
// Check for all-zero end-of-archive block
|
|
280
288
|
let allZero = true;
|
|
@@ -330,6 +338,25 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
330
338
|
}
|
|
331
339
|
}
|
|
332
340
|
|
|
341
|
+
// Match package/README.md case-insensitively (npm registry metadata).
|
|
342
|
+
// The real entry file name is preserved in readmeFilename, and any
|
|
343
|
+
// duplicate, case-colliding, or non-regular README entry fails closed,
|
|
344
|
+
// mirroring the package/package.json checks above.
|
|
345
|
+
if (entryName.toLowerCase() === 'package/readme.md') {
|
|
346
|
+
if (readme) throw new Error('tarball contains conflicting package README entries');
|
|
347
|
+
if (!(typeFlag === 0 || typeFlag === 48 /* '0' */)) {
|
|
348
|
+
throw new Error('tarball package README must be a regular file');
|
|
349
|
+
}
|
|
350
|
+
const bodyStart = offset + 512;
|
|
351
|
+
const bodyEnd = bodyStart + size;
|
|
352
|
+
if (bodyEnd > data.length) throw new Error('frozen npm tarball entry exceeds archive bounds');
|
|
353
|
+
if (size > 10 * 1024 * 1024) throw new Error('tarball package README is unreasonably large');
|
|
354
|
+
readme = {
|
|
355
|
+
content: data.subarray(bodyStart, bodyEnd).toString('utf8'),
|
|
356
|
+
filename: entryName.slice('package/'.length),
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
333
360
|
// Advance to next header: 512 header + ceil(size/512)*512 data
|
|
334
361
|
const nextOffset = offset + 512 + Math.ceil(size / 512) * 512;
|
|
335
362
|
if (!Number.isSafeInteger(nextOffset) || nextOffset > data.length) {
|
|
@@ -338,6 +365,10 @@ function extractManifestFromTarball(tarballBuffer, expected) {
|
|
|
338
365
|
offset = nextOffset;
|
|
339
366
|
}
|
|
340
367
|
if (!manifest) throw new Error('tarball does not contain package/package.json');
|
|
368
|
+
if (readme) {
|
|
369
|
+
manifest.readme = readme.content;
|
|
370
|
+
manifest.readmeFilename = readme.filename;
|
|
371
|
+
}
|
|
341
372
|
return manifest;
|
|
342
373
|
}
|
|
343
374
|
|