@ikon85/agent-workflow-kit 0.36.0 → 0.36.2

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.
@@ -54,6 +54,10 @@ release contain the same artifact.
54
54
  data, infer an external fact, or manufacture `pending`/`not-applicable` to
55
55
  make a capability appear ready.
56
56
 
57
+ File identity includes the package-declared mode as well as bytes. A
58
+ mode-only Core delta is an update and must be applied transactionally; it
59
+ must not survive preview as `unchanged` only to fail candidate verification.
60
+
57
61
  Readiness-schema adoption also keeps the Claude and Codex instruction
58
62
  surfaces compatible. When exactly one applicable instruction surface has a
59
63
  non-empty `## Prod` section and another has no such section, the staged
@@ -112,7 +116,9 @@ release contain the same artifact.
112
116
  request, but the latter still needs a sanitized exact preview and separate
113
117
  explicit approval before any remote command. For a project-specific edit, recommend
114
118
  `npx @ikon85/agent-workflow-kit@latest own <path> --as=explicit-fork` so
115
- future updates treat that path as an independent fork. A generic experiment
119
+ future updates treat that path as an independent fork. `own` snapshots the
120
+ path's current local bytes as the explicit-fork ledger identity, including
121
+ when it follows an already-detected local edit. A generic experiment
116
122
  retained only until it returns upstream uses
117
123
  `npx @ikon85/agent-workflow-kit@latest contribute start <path>`. Prepare its
118
124
  bounded local artifact, when the route report permits it, with `contribute prepare <path>
@@ -54,6 +54,10 @@ release contain the same artifact.
54
54
  data, infer an external fact, or manufacture `pending`/`not-applicable` to
55
55
  make a capability appear ready.
56
56
 
57
+ File identity includes the package-declared mode as well as bytes. A
58
+ mode-only Core delta is an update and must be applied transactionally; it
59
+ must not survive preview as `unchanged` only to fail candidate verification.
60
+
57
61
  Readiness-schema adoption also keeps the Claude and Codex instruction
58
62
  surfaces compatible. When exactly one applicable instruction surface has a
59
63
  non-empty `## Prod` section and another has no such section, the staged
@@ -112,7 +116,9 @@ release contain the same artifact.
112
116
  request, but the latter still needs a sanitized exact preview and separate
113
117
  explicit approval before any remote command. For a project-specific edit, recommend
114
118
  `npx @ikon85/agent-workflow-kit@latest own <path> --as=explicit-fork` so
115
- future updates treat that path as an independent fork. A generic experiment
119
+ future updates treat that path as an independent fork. `own` snapshots the
120
+ path's current local bytes as the explicit-fork ledger identity, including
121
+ when it follows an already-detected local edit. A generic experiment
116
122
  retained only until it returns upstream uses
117
123
  `npx @ikon85/agent-workflow-kit@latest contribute start <path>`. Prepare its
118
124
  bounded local artifact, when the route report permits it, with `contribute prepare <path>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: to-issues
3
- description: Break a Feature or Program plan, spec, or PRD into independently-grabbable issues on the project issue tracker. This is the single public Planning facade: explicit Feature identity uses tracer-bullet decomposition; explicit Program identity delegates to the internal graph engine.
3
+ description: "Break a Feature or Program plan, spec, or PRD into independently-grabbable issues on the project issue tracker. This is the single public Planning facade: explicit Feature identity uses tracer-bullet decomposition; explicit Program identity delegates to the internal graph engine."
4
4
  ---
5
5
 
6
6
  <!-- project-extension:protocol-v1:start -->
package/README.md CHANGED
@@ -445,6 +445,16 @@ the old way. Decision record:
445
445
 
446
446
  ## Release notes
447
447
 
448
+ ### 0.36.2
449
+
450
+ - changed: `.claude/skills/to-issues/SKILL.md`
451
+
452
+ ### 0.36.1
453
+
454
+ - changed: `.agents/skills/kit-update/SKILL.md`
455
+ - changed: `.claude/skills/kit-update/SKILL.md`
456
+ - changed: `src/lib/manifest.mjs`
457
+
448
458
  ### 0.36.0
449
459
 
450
460
  - added: `.agents/skills/setup-workflow/contribution-routing.md`
@@ -1,5 +1,5 @@
1
1
  {
2
- "kitVersion": "0.36.0",
2
+ "kitVersion": "0.36.2",
3
3
  "files": [
4
4
  {
5
5
  "path": ".agents/skills/ask-matt/SKILL.md",
@@ -377,7 +377,7 @@
377
377
  "ownerSkill": "kit-update",
378
378
  "surface": "codex",
379
379
  "installRole": "consumer",
380
- "sha256": "e00b50698ac5f03caaf8b389ad478789ce43bfa01c01d180557e001a8c46d20c",
380
+ "sha256": "ea34bd16072783325c263b4afc4eefc39f0aabdbb53731b84500b46db69ef2c1",
381
381
  "mode": 420,
382
382
  "origin": "kit"
383
383
  },
@@ -1699,7 +1699,7 @@
1699
1699
  "ownerSkill": "kit-update",
1700
1700
  "surface": "claude",
1701
1701
  "installRole": "consumer",
1702
- "sha256": "e00b50698ac5f03caaf8b389ad478789ce43bfa01c01d180557e001a8c46d20c",
1702
+ "sha256": "ea34bd16072783325c263b4afc4eefc39f0aabdbb53731b84500b46db69ef2c1",
1703
1703
  "mode": 420,
1704
1704
  "origin": "kit"
1705
1705
  },
@@ -2207,7 +2207,7 @@
2207
2207
  "ownerSkill": "to-issues",
2208
2208
  "surface": "claude",
2209
2209
  "installRole": "consumer",
2210
- "sha256": "dee58a06620f21ccdd753e6d575cc5006ce67236ec43c77c4439d4552cca8e94",
2210
+ "sha256": "7cc957d9883ac205904df9fc3ba2d29e7f13661b6511b355f56115ac992e2a09",
2211
2211
  "mode": 420,
2212
2212
  "origin": "kit"
2213
2213
  },
@@ -2883,7 +2883,7 @@
2883
2883
  "path": "src/lib/manifest.mjs",
2884
2884
  "kind": "script",
2885
2885
  "installRole": "consumer",
2886
- "sha256": "a1a01efa6bca0fc5ed2fcac1d2434d6c013f5e528adecfc63a597b9d52475e15",
2886
+ "sha256": "f2920f2b25a700be080fbba122a809bf509080673b806aaab2b0c773c8d8267f",
2887
2887
  "mode": 420,
2888
2888
  "origin": "kit"
2889
2889
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikon85/agent-workflow-kit",
3
- "version": "0.36.0",
3
+ "version": "0.36.2",
4
4
  "description": "Portable AI-agent workflow skills (plan → execute → land → learn) for Claude Code & Codex — grilling, TDD, diagnosis, two-axis code review, cross-model Codex review, design & domain-modeling, plus a skill router (ask-matt). npx init/update/diff/uninstall.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -74,6 +74,8 @@ def parse_scalar(value: str) -> str:
74
74
  if len(value) < 2 or not value.endswith("'"):
75
75
  raise FrontmatterError("unterminated single-quoted scalar")
76
76
  return value[1:-1].replace("''", "'")
77
+ if ": " in value:
78
+ raise FrontmatterError("mapping values are not allowed in a plain scalar")
77
79
  return value.split(" #", 1)[0].strip()
78
80
 
79
81
 
@@ -193,6 +195,12 @@ class ValidatorBehaves(unittest.TestCase):
193
195
  md = self._tmp_skill('---\nname: demo\ndescription: "Use „x" then y, z"\n---\nbody\n')
194
196
  self.assertTrue(any("does not parse" in p for p in validate(md)))
195
197
 
198
+ def test_plain_scalar_colon_followed_by_space_is_flagged(self):
199
+ md = self._tmp_skill(
200
+ "---\nname: demo\ndescription: This is invalid YAML: mapping-like text.\n---\nbody\n"
201
+ )
202
+ self.assertTrue(any("does not parse" in p for p in validate(md)))
203
+
196
204
  def test_name_dir_mismatch_is_flagged(self):
197
205
  md = self._tmp_skill("---\nname: wrong\ndescription: ok\n---\nbody\n")
198
206
  self.assertTrue(any("but directory is 'demo'" in p for p in validate(md)))
@@ -3,6 +3,7 @@ import { validateConsumerFile } from '../lib/consumerPath.mjs';
3
3
  import {
4
4
  CONSUMER_MANIFEST_NAME, readManifest, withOrigin, writeManifest,
5
5
  } from '../lib/manifest.mjs';
6
+ import { sha256File } from '../lib/hash.mjs';
6
7
 
7
8
  /** Mark one tracked consumer file as kit- or consumer-owned. */
8
9
  export async function setOwnership({ consumerRoot, path, origin, ownershipState }) {
@@ -12,8 +13,13 @@ export async function setOwnership({ consumerRoot, path, origin, ownershipState
12
13
  const manifestPath = join(consumerRoot, CONSUMER_MANIFEST_NAME);
13
14
  const manifest = await readManifest(manifestPath);
14
15
  if (!manifest) throw new Error('not initialised — run `init` first');
15
- const next = withOrigin(manifest, path, origin, ownershipState);
16
+ const validatedOwnership = withOrigin(manifest, path, origin, ownershipState);
16
17
  await validateConsumerFile(consumerRoot, path);
18
+ const installedSha256 = origin === 'consumer'
19
+ ? await sha256File(join(consumerRoot, path)) : undefined;
20
+ const next = installedSha256
21
+ ? withOrigin(manifest, path, origin, ownershipState, installedSha256)
22
+ : validatedOwnership;
17
23
  await writeManifest(manifestPath, next);
18
24
  return { path, origin, ownershipState: origin === 'consumer'
19
25
  ? (ownershipState ?? 'explicit-fork') : undefined };
@@ -95,7 +95,9 @@ export function indexByPath(manifest, key) {
95
95
  }
96
96
 
97
97
  /** Return a manifest with one tracked entry moved to the requested ownership state. */
98
- export function withOrigin(manifest, path, origin, ownershipState = 'explicit-fork') {
98
+ export function withOrigin(
99
+ manifest, path, origin, ownershipState = 'explicit-fork', installedSha256,
100
+ ) {
99
101
  if (![KIT_ORIGIN, CONSUMER_ORIGIN].includes(origin)) {
100
102
  throw new Error(`invalid manifest origin: ${origin}`);
101
103
  }
@@ -119,7 +121,12 @@ export function withOrigin(manifest, path, origin, ownershipState = 'explicit-fo
119
121
  if (ownershipState !== 'explicit-fork') {
120
122
  throw new Error(`invalid consumer ownership state: ${ownershipState}`);
121
123
  }
122
- return { ...entry, origin, ownershipState };
124
+ return {
125
+ ...entry,
126
+ ...(installedSha256 ? { installedSha256 } : {}),
127
+ origin,
128
+ ownershipState,
129
+ };
123
130
  }),
124
131
  };
125
132
  }
@@ -1,4 +1,4 @@
1
- import { access, readFile, rm } from 'node:fs/promises';
1
+ import { access, lstat, readFile, rm } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import { sha256File } from './hash.mjs';
4
4
  import { lineDiff, writeAtomic } from './atomicWrite.mjs';
@@ -141,7 +141,9 @@ export async function reconcile({ kitRoot, consumerRoot, decide = () => false, d
141
141
  continue;
142
142
  }
143
143
  const userEdited = current !== prior.installedSha256;
144
- const upstreamChanged = file.sha256 !== prior.installedSha256;
144
+ const currentMode = (await lstat(dest)).mode & 0o777;
145
+ const upstreamChanged = file.sha256 !== prior.installedSha256
146
+ || currentMode !== file.mode;
145
147
  if (!userEdited && upstreamChanged) {
146
148
  if (!dryRun) await writeAtomic(dest, await readFile(join(kitRoot, file.path)), file.mode);
147
149
  nextInstalled.push(entry(file, file.sha256));