owfadev 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/.owfa/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
@@ -16,8 +16,13 @@ import owfa_kernel as k # noqa: E402
16
16
 
17
17
  class VersionSchemeTests(unittest.TestCase):
18
18
  def test_framework_version_parses_three_part_anchor(self):
19
- # the repo's own VERSION is the full release version now
20
- self.assertEqual(k.framework_version(), (0, 4, 0))
19
+ # the repo's own VERSION is the full release version now — expect
20
+ # exactly the anchor's own three-part tuple (version-agnostic: the
21
+ # test survives release bumps)
22
+ text = open(os.path.join(k.ROOT, ".owfa", "VERSION"), encoding="utf-8").read().strip()
23
+ expected = tuple(int(x) for x in text.split("."))
24
+ self.assertEqual(len(expected), 3)
25
+ self.assertEqual(k.framework_version(), expected)
21
26
 
22
27
  def test_framework_version_tolerates_legacy_two_part(self):
23
28
  import tempfile
@@ -35,12 +40,12 @@ class VersionSchemeTests(unittest.TestCase):
35
40
  self.assertEqual(k._vline("0.2"), (0, 2))
36
41
 
37
42
  def test_compat_floor_tuple_semantics(self):
38
- fw = k.framework_version() # (0, 4, 0)
39
- self.assertFalse((0, 3) > fw) # floor below the line passes
40
- self.assertFalse((0, 4) > fw) # floor at the line passes
41
- self.assertFalse((0, 4, 0) > fw) # floor equal to the release passes
42
- self.assertTrue((0, 4, 1) > fw) # floor demanding a later patch refuses
43
- self.assertTrue((0, 5) > fw) # floor above the line refuses
43
+ fw = k.framework_version() # the live anchor, whatever release it says
44
+ self.assertFalse((0, 3) > fw) # floor below the line passes
45
+ self.assertFalse(fw[:2] > fw) # floor at the line passes
46
+ self.assertFalse(fw > fw) # floor equal to the release passes
47
+ self.assertTrue((fw[0], fw[1], fw[2] + 1) > fw) # floor demanding a later patch refuses
48
+ self.assertTrue((fw[0] + 1,) > fw) # floor above the line refuses
44
49
 
45
50
  def test_staging_line_range(self):
46
51
  # mirror of the _stage_migrations predicate: stage when prev_line <= from_line < new_line
package/bin/owfa.js CHANGED
@@ -298,14 +298,12 @@ function rescueCoreForConversion(target, attic, freshOwfa) {
298
298
  // (--yes is legitimate here: the channel itself is converting its own former
299
299
  // payload, a mechanical adoption, not a trust decision).
300
300
  //
301
- // Family closure (kernel D5 invariant): every member must reach the family root
302
- // through depends. The rescued set's own dependency roots (members whose depends
303
- // has no edge into the rescued set — today: domain, instance-git, wiki) get a
304
- // synthetic `- personal` edge in the STAGING copies only, so the adopted roster
305
- // validates. When the real owfa-personal suite later replaces this package via
306
- // `kernel upgrade`, the canonical manifests take over. The conversion stages no
307
- // semantic migration (no migrations/ dir: nothing semantic changes — plugin
308
- // bodies and projections are byte-identical), so there is nothing to verify-clear.
301
+ // Rootless-suite conversion (kind: suite): the kernel's family-root/closure law
302
+ // does not apply, so no synthesized root plugin and no synthetic dependency
303
+ // edges — the staged package matches the canonical owfa-personal shape (21
304
+ // members, no root). The conversion stages no semantic migration (no
305
+ // migrations/ dir: nothing semantic changes — plugin bodies and projections are
306
+ // byte-identical), so there is nothing to verify-clear.
309
307
  function convertCoreToPersonal(target) {
310
308
  const hold = path.join(target, MIGRATE_SCRATCH, "convert", "core");
311
309
  if (!fs.existsSync(hold)) return;
@@ -368,49 +366,12 @@ function convertCoreToPersonal(target) {
368
366
  }
369
367
  }
370
368
 
371
- // family-root edge: dependency roots of the rescued set adopt `personal`
372
- const memberSet = new Set(members);
373
- for (const m of members) {
374
- const mf = path.join(staging, m, "PLUGIN.yaml");
375
- let text = fs.readFileSync(mf, "utf8");
376
- const depMatch = text.match(/^depends:\s*(.*)$/m);
377
- const deps = depMatch
378
- ? depMatch[1].replace(/^\[|\]$/g, "").split(",").map((s) => s.trim().replace(/^"|"$/g, "")).filter(Boolean)
379
- : [];
380
- if (deps.some((d) => memberSet.has(d) || d === "personal")) continue; // reaches the family through the set already
381
- if (depMatch && depMatch[1].trim() === "[]") {
382
- text = text.replace(/^depends:\s*\[\]\s*$/m, "depends:\n - personal");
383
- } else if (depMatch) {
384
- text = text.replace(/^depends:.*$/m, (line) => line + "\n - personal");
385
- } else {
386
- text = text.replace(/^(id:.*)$/m, "$1\ndepends:\n - personal");
387
- }
388
- fs.writeFileSync(mf, text, "utf8");
389
- }
390
-
391
- // synthesize the family root plugin
392
- const root = path.join(staging, "personal");
393
- fs.mkdirSync(root, { recursive: true });
394
- const today = new Date().toISOString().slice(0, 10);
395
- fs.writeFileSync(
396
- path.join(root, "PLUGIN.yaml"),
397
- [
398
- `# synthesized by the owfa channel: v0.4 core de-parasitization conversion (upgrade)`,
399
- `# adopts the framework-shipped core masters as a package; replaced by the`,
400
- `# canonical owfa-personal suite on the next \`kernel upgrade personal\`.`,
401
- `id: personal`,
402
- `schema_version: 1`,
403
- `version: 0.1`,
404
- `depends: []`,
405
- `updated: ${today}`,
406
- `attachment: []`,
407
- `fields: {}`,
408
- `inject: ${JSON.stringify("personal suite (converted from framework core by the 0.4 channel upgrade) — family identity anchor; members, skeleton and teardown anchors are declared in PKG.yaml; canonical source: owfadev/owfa-personal")}`,
409
- ``,
410
- ].join("\n"),
411
- "utf8"
412
- );
413
- fs.writeFileSync(path.join(root, "PLUGIN.md"), "# personal\n\nSynthesized family root for the converted core suite (0.4 channel upgrade).\nSee PKG.yaml for members, skeleton and teardown anchors.\n", "utf8");
369
+ // rootless suite: kind=suite skips the family-root/closure law entirely
370
+ // (owfa_kernel validate_packages), so no synthesized root plugin and no
371
+ // synthetic `personal` dependency edges — the converted package matches the
372
+ // canonical owfa-personal shape (21 members, no root). This also keeps the
373
+ // projected injection region within the 16 KiB budget: near-capacity 0.3
374
+ // instances (domains installed) have no headroom for an extra block.
414
375
 
415
376
  // synthesize PKG.yaml — skeleton and anchors preserve the pre-0.4 channel
416
377
  // contract mechanically (INSTANCE_DIRS and the kernel's former teardown
@@ -419,15 +380,12 @@ function convertCoreToPersonal(target) {
419
380
  const lines = [
420
381
  `# synthesized by the owfa channel: v0.4 core de-parasitization conversion (upgrade)`,
421
382
  `id: personal`,
422
- // kind: suite — the conversion product is a rootless-suite package (the
423
- // owfa-personal shape): the synthesized root below is a family-identity
424
- // anchor only, the closure law does not apply, and the canonical rootless
425
- // suite can replace this package via `kernel upgrade personal` cleanly
383
+ // kind: suite — the conversion product is a rootless-suite package: the
384
+ // canonical owfa-personal shape, replaceable via `kernel upgrade personal`
426
385
  `kind: suite`,
427
386
  `version: 0.1.0`,
428
387
  `compat: ">= 0.4"`,
429
388
  `members:`,
430
- ` - personal`,
431
389
  ...members.map((m) => ` - ${m}`),
432
390
  `skeleton: [vault/, wiki/notes/, wiki/sessions/, wiki/vault/]`,
433
391
  `uninstall:`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "owfadev",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "OWFA — One Workspace For All (agents). Install, initialize and upgrade the owfa agent workspace framework.",
5
5
  "keywords": [
6
6
  "owfa",