aw-spec-cli 0.1.22 → 0.1.23

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.
@@ -101,6 +101,7 @@ Execution strategies (--strategy, overridable per step via `strategy:`):
101
101
  suspend/resume.
102
102
  """
103
103
  import argparse
104
+ import glob
104
105
  import importlib.util
105
106
  import json
106
107
  import os
@@ -1491,7 +1492,7 @@ def _module_script_refs(mpath, base_dir, seen):
1491
1492
  return out
1492
1493
 
1493
1494
 
1494
- def validate_workflow(wf, base_dir):
1495
+ def validate_workflow(wf, base_dir, path=""):
1495
1496
  errors, warnings = [], []
1496
1497
  if not isinstance(wf, dict):
1497
1498
  return (["top-level YAML is not a mapping"], [])
@@ -1621,9 +1622,51 @@ def validate_workflow(wf, base_dir):
1621
1622
  for name in sorted(used):
1622
1623
  if name.split(".")[0] not in produced:
1623
1624
  warnings.append(f"variable {{{{{name}}}}} referenced but never produced")
1625
+ errors_n, warnings_n = _validate_next(wf, base_dir, path)
1626
+ return errors + errors_n, warnings + warnings_n
1627
+
1628
+
1629
+ # outputs.next is the ONLY channel a finished run has for telling the operator what
1630
+ # to run next: the engine returns wf["outputs"] and the launching agent relays it.
1631
+ # Both faults it guards are silent — a next: indented out of the outputs map is
1632
+ # parsed and dropped, and a retired command name still reads as a valid sentence —
1633
+ # so the run ends looking successful and the agent invents a successor to fill the
1634
+ # gap. Warnings, not errors: a workflow may legitimately name a command that is
1635
+ # designed but not yet built, and pre-flight refuses to start on errors alone.
1636
+ def _validate_next(wf, base_dir, path=""):
1637
+ errors, warnings = [], []
1638
+ outputs = wf.get("outputs") or {}
1639
+ known = {os.path.basename(p)[len("aw-spec-"):-len(".orch.yaml")]
1640
+ for p in glob.glob(os.path.join(base_dir, "aw-spec-*.orch.yaml"))}
1641
+ # A module has no successor to name: it is included INTO a caller, and the caller's
1642
+ # own next covers the run. Only a launchable aw-spec-<name> workflow is asked for one.
1643
+ launchable = os.path.basename(path).startswith("aw-spec-") if path else bool(known)
1644
+ if launchable and "next" not in outputs:
1645
+ where = " (it is at the document's top level, OUTSIDE outputs:, so the " \
1646
+ "engine parses it and then drops it)" if "next" in wf else ""
1647
+ warnings.append(f"outputs: declares no 'next' — the run ends with no "
1648
+ f"suggested successor{where}")
1649
+ if not known: # validating a module, or a workflow read from elsewhere
1650
+ return errors, warnings
1651
+ for text in _output_strings(outputs):
1652
+ for cmd in re.findall(r"/appweaver\s+([a-z][a-z0-9-]*)", text):
1653
+ if cmd not in known:
1654
+ warnings.append(f"outputs names '/appweaver {cmd}', which resolves "
1655
+ f"to no aw-spec-{cmd}.orch.yaml")
1624
1656
  return errors, warnings
1625
1657
 
1626
1658
 
1659
+ def _output_strings(v):
1660
+ if isinstance(v, str):
1661
+ yield v
1662
+ elif isinstance(v, list):
1663
+ for x in v:
1664
+ yield from _output_strings(x)
1665
+ elif isinstance(v, dict):
1666
+ for x in v.values():
1667
+ yield from _output_strings(x)
1668
+
1669
+
1627
1670
  def _print_suspended(pending, opts):
1628
1671
  """Checkpoint transport: hand the pending request to the INVOKING agent."""
1629
1672
  if opts.json:
@@ -1710,7 +1753,7 @@ def main(argv=None):
1710
1753
  if opts.json else f"ERROR: parse: {e}")
1711
1754
  return 1
1712
1755
  errors, warnings = validate_workflow(
1713
- wf, os.path.dirname(os.path.abspath(opts.workflow)))
1756
+ wf, os.path.dirname(os.path.abspath(opts.workflow)), opts.workflow)
1714
1757
  if opts.json:
1715
1758
  print(json.dumps({"status": "valid" if not errors else "invalid",
1716
1759
  "errors": errors, "warnings": warnings}, indent=2))
@@ -1732,7 +1775,8 @@ def main(argv=None):
1732
1775
  try:
1733
1776
  with open(opts.workflow, encoding="utf-8") as fh:
1734
1777
  wf = load_yaml(fh.read())
1735
- errors, _ = validate_workflow(wf, os.path.dirname(os.path.abspath(opts.workflow)))
1778
+ errors, _ = validate_workflow(
1779
+ wf, os.path.dirname(os.path.abspath(opts.workflow)), opts.workflow)
1736
1780
  except Exception as e:
1737
1781
  wf, errors = None, [f"parse: {e}"]
1738
1782
  if errors:
@@ -724,4 +724,4 @@ outputs:
724
724
  ui_validation_ok: "{{ui_ok}}"
725
725
  ui_validation_issues: "{{ui_issues}}"
726
726
  note: "Split constitution authored, one half per LANE the project declared in .appweaver/stacks.json. service_lane / ui_lane report which lanes were found there, and the declaration is the ONLY signal read: a half is a lane's standing governance, so a lane declared `(none)` in select-stack gets no half AND no file. constitution.technical.md is the service lane's base (standing input to the SERVICE lane of plan + implement); constitution.ui.md is the UI lane's UX-* base (standing input to their FRONTEND lane); constitution.domain.md is the domain addenda (standing input to specify + a gate checklist), and it is always authored because domain is not a lane — it addends whichever halves exist. All are composed into constitution.md, which now tolerates an absent technical half: a UI-only project's domain half opens the roman-numeral sequence at I instead of continuing one, and numbering_checked reports false because that check has no subject rather than because it silently passed. Mapping ## /aw-spec-ui-constitution supplies the rules the UI half ratifies but no longer creates the lane on its own — a mapped rule set with no declared lane produces a warning naming both fixes. ui_lane false with ui_included true means a lane was retired after its half was authored: the file is left alone and the log says so, because a ratified governance file is never deleted automatically. If a validation_ok is false, the matching validation_issues lists what still needs a manual touch. See each half's Sync Impact Report for its version bump. Suggested commit: 'docs: amend split constitution'."
727
- next: "Loaded per concern — /appweaver specify loads constitution.domain.md; the SERVICE lane of plan + implement loads constitution.technical.md; their FRONTEND lane loads constitution.ui.md. Re-run /appweaver constitution to amend, including to pick up a lane declared or dropped after this run — re-run /appweaver select-stack first to change which lanes exist."
727
+ next: "/appweaver select-feature → specify. select-feature picks the feature to build and every stage from specify onward reads that active feature and stops without it; on a brownfield workspace pick the bounded context first with /appweaver select-bounded-context. From specify the greenfield sequence runs plan → analyze-plan → implement → build → analyze-slice → run → deploy. THE HALVES ARE LOADED PER CONCERN, not all at once — /appweaver specify loads constitution.domain.md; the SERVICE lane of plan + implement loads constitution.technical.md; their FRONTEND lane loads constitution.ui.md. Re-run /appweaver constitution to amend, including to pick up a lane declared or dropped after this run — re-run /appweaver select-stack first to change which lanes exist."
@@ -66,4 +66,7 @@ outputs:
66
66
  tree_file: "{{tree_file}}"
67
67
  sequence_file: "{{sequence_file}}"
68
68
  note: "Migration Hierarchy Tree generated in {{tree_file}} and {{sequence_file}}."
69
- next: "Human Gate H0.1: Review specs/migration-tree.md and proceed to /appweaver mr per slice."
69
+ # Migration is a MODE of the ordinary brownfield loop, not a pipeline of its own:
70
+ # the tree only fixes the ORDER the slices are taken in, and each slice then runs
71
+ # adopt → (characterize on touch) → the CR delta loop like any other.
72
+ next: "Human Gate H0.1: Review {{tree_file}} — it orders {{aggregate_count}} aggregate(s) into {{wave_count}} migration wave(s), and that order is the only thing it decides. Take the slices in it ONE AT A TIME through the ordinary brownfield loop: /appweaver adopt <Feature> reverse-engineers the slice into spec.md + backend-plan.md + source-map.md, then every change to it goes through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta). If the slice has untested legacy behaviour with blast radius, run /appweaver characterize first to fence it. /appweaver parity is the cutover gate — run it per slice before the seam is routed away from the legacy path."
@@ -366,4 +366,8 @@ outputs:
366
366
  sentinel_clean: "{{clean}}"
367
367
  sentinel_residue: "{{residue}}"
368
368
  note: "Foundation scaffolded into the {{lane_id}} lane at {{lane_root}} ({{written}} file(s), sentinel renamed to {{app}}); {{tests_message}}. Everything written is inside the subtree that lane owns, which is where implement generates and build/test/run act. Configure your AppWeaver.* NuGet feed and run the AppHost to confirm the scaffold starts before building on it."
369
- next: "Another lane still to scaffold? Run /appweaver foundation again and pick it — one bundle fills one lane. Otherwise /appweaver select-feature (pick the feature to build; every stage from specify onward reads that active feature and stops without it. If this workspace has governed projects under guardrails/projects/, run /appweaver select-domain first — it is one-time and optional.)"
369
+ # constitution is named here because specify declares constitution.domain.md a
370
+ # REQUIRED context file. It announces rather than stops when the file is absent,
371
+ # so a sequence that skips this step produces a spec authored with no domain
372
+ # frame and only a [context] MISSING line to show for it.
373
+ next: "Another lane still to scaffold? Run /appweaver foundation again and pick it — one bundle fills one lane. Otherwise carry on with /appweaver select-domain → constitution → select-feature → specify. select-domain binds this workspace to a governed project under guardrails/projects/ and is one-time; skip it only where no such project exists. /appweaver constitution is NOT optional — it authors the constitution halves, and specify declares constitution.domain.md as REQUIRED context while plan and implement read constitution.technical.md (plus constitution.ui.md on a frontend lane); it also needs the lane declaration select-stack wrote, which is why it runs after this. /appweaver select-feature then picks the feature to build — every stage from specify onward reads that active feature and stops without it."
@@ -264,18 +264,7 @@ outputs:
264
264
  coverage_pct: "{{coverage_pct}}"
265
265
  split_candidates: "{{split_candidates}}"
266
266
  contexts_ordered: "{{contexts_ordered}}"
267
-
268
- next: >
269
- {{feature_count}} feature(s) across {{context_count}} bounded context(s) were
270
- proposed from `{{chosen_strategy}}` evidence ({{coverage_pct}}% of source
271
- covered), ordered into {{wave_count}} dependency wave(s).
272
-
273
- READ AND EDIT specs/proposed-inventory.md — it is the boundary map, and it is
274
- yours. Rename features and contexts, move a feature to another context, merge
275
- two by giving them one name, split one by adding a row with the same Aggregate,
276
- and set Depends On to change the order. {{split_candidates}} split(s) were
277
- PROPOSED with their evidence and none were applied.
278
-
279
- Then run `/appweaver inventory apply` to validate those edits and regenerate the
280
- machine map, and onboard the contexts one at a time in the order it reports:
281
- {{contexts_ordered}}
267
+ # Sits INSIDE outputs: — the engine resolves and returns wf["outputs"] only, so a
268
+ # next: at the document's top level is parsed and then dropped, and the workflow
269
+ # ends with no suggested successor at all.
270
+ next: "{{feature_count}} feature(s) across {{context_count}} bounded context(s) were proposed from `{{chosen_strategy}}` evidence ({{coverage_pct}}% of source covered), ordered into {{wave_count}} dependency wave(s). READ AND EDIT specs/proposed-inventory.md — it is the boundary map, and it is yours. Rename features and contexts, move a feature to another context, merge two by giving them one name, split one by adding a row with the same Aggregate, and set Depends On to change the order. {{split_candidates}} split(s) were PROPOSED with their evidence and none were applied. Then run /appweaver inventory apply to validate those edits and regenerate the machine map. Next: /appweaver onboard <Context> — once per bounded context, one at a time, in the order inventory apply reports: {{contexts_ordered}}. Then /appweaver adopt <Feature> per feature you are about to change."
@@ -2210,4 +2210,4 @@ outputs:
2210
2210
  ui_delta_design_template_files: "{{ui_delta_design_template_files}}"
2211
2211
  technical_validation_ok: "{{technical_ok}}"
2212
2212
  domain_validation_ok: "{{domain_ok}}"
2213
- next: "Onboarded bounded context {{bc}} ({{bc_feature_count}} feature(s): {{bc_features}}). Its aggregate concepts ({{bc_aggregates}}) are in {{bundle_dir}}, each keyed `bounded_context: {{bc}}` and listing the features that act on it — the bundle is the project's knowledge, one concept per aggregate, never one per feature — and its specs tree now exists at {{bc_dir}}/ with a directory per feature ({{feature_dirs}}) — EMPTY on purpose: the directory says the feature is known, and the documents that describe it are written per feature by /appweaver adopt and per context by /appweaver specify. {{bc}} is now the ACTIVE bounded context (.appweaver/context.json), so /appweaver select-feature lists exactly these features and nothing from a neighbouring context; switch with /appweaver select-bounded-context. ONBOARD RUNS ONCE PER CONTEXT: contexts already done — {{onboarded_contexts}}; still open — {{remaining_contexts}}; the order the map gives is {{contexts_ordered}}. Run /appweaver onboard <NextContext> for each remaining one, or with no argument to take the next one automatically. THE PROJECT TIER IS WRITTEN ONCE, BY THE FIRST CONTEXT (this run was first: {{is_first}}). That tier is the PROVISIONAL governance scaffold — the split constitution, the domain rule set at guardrails/projects/{{domain_slug}}/domain/*.domain.md + domain-rule-bindings.md, each declared LANE\'s rule set and constitution half, the activated domain {{active_domain}}, and the code-derived design / delta-design / domain-model template overrides in .appweaver/templates/overrides/. A later context does NOT re-author any of it: re-deriving project principles from one context\'s evidence is the scoping bias the governance tier exists to avoid. Amend it with /appweaver constitution. ONE HALF AND ONE RULE SET PER LANE: service_lane / ui_lane report which lanes .appweaver/stacks.json declared, and the declaration is what decided. A lane declared (none) in select-stack gets none of it, which is the correct outcome and not an omission. LANE DECLARATION: read, never written — select-stack is its sole writer, and this run scanned the source paths it named (scanned_service_root / scanned_ui_root); scanned_backend_files / scanned_ui_files report each. ui_source_evidence_found false means the UI lane\'s declared path held nothing a scan recognises as UI, so its governance is thin — move the source path with /appweaver select-stack and re-run. The build/test/run commands on each lane are that PROFILE\'s defaults and may not match a legacy layout — review them. Because the domain is activated, resolve-domain + resolve-tech route the WHOLE forward pipeline to these code-derived rules — never another project\'s rules as a fallback. THE BOUNDARIES CAME FROM THE MAP, not from this run: /appweaver inventory proposed them and you confirmed them in specs/proposed-inventory.md. To change a boundary, edit that file and run /appweaver inventory apply — a context whose concepts already exist is not re-onboarded. Develop an EXISTING feature just-in-time: /appweaver adopt <Feature> reverse-engineers its spec.md + design.md + source-map.md and deepens the OKF concept of the aggregate it acts on. Develop a NEW feature straight through the forward pipeline (/appweaver specify → plan → implement). Then drive every change through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta). If a validation_ok is false, its constitution half needs a manual touch (see its Sync Impact Report)."
2213
+ next: "Onboarded bounded context {{bc}} ({{bc_feature_count}} feature(s): {{bc_features}}). Its aggregate concepts ({{bc_aggregates}}) are in {{bundle_dir}}, each keyed `bounded_context: {{bc}}` and listing the features that act on it — the bundle is the project's knowledge, one concept per aggregate, never one per feature — and its specs tree now exists at {{bc_dir}}/ with a directory per feature ({{feature_dirs}}) — EMPTY on purpose: the directory says the feature is known, and the documents that describe it are written per feature by /appweaver adopt and per context by /appweaver specify. {{bc}} is now the ACTIVE bounded context (.appweaver/context.json), so /appweaver select-feature lists exactly these features and nothing from a neighbouring context; switch with /appweaver select-bounded-context. ONBOARD RUNS ONCE PER CONTEXT: contexts already done — {{onboarded_contexts}}; still open — {{remaining_contexts}}; the order the map gives is {{contexts_ordered}}. Run /appweaver onboard <NextContext> for each remaining one, or with no argument to take the next one automatically. THE PROJECT TIER IS WRITTEN ONCE, BY THE FIRST CONTEXT (this run was first: {{is_first}}). That tier is the PROVISIONAL governance scaffold — the split constitution, the domain rule set at guardrails/projects/{{domain_slug}}/domain/*.domain.md + domain-rule-bindings.md, each declared LANE\'s rule set and constitution half, the activated domain {{active_domain}}, and the code-derived design / delta-design / domain-model template overrides in .appweaver/templates/overrides/. A later context does NOT re-author any of it: re-deriving project principles from one context\'s evidence is the scoping bias the governance tier exists to avoid. Amend it with /appweaver constitution. ONE HALF AND ONE RULE SET PER LANE: service_lane / ui_lane report which lanes .appweaver/stacks.json declared, and the declaration is what decided. A lane declared (none) in select-stack gets none of it, which is the correct outcome and not an omission. LANE DECLARATION: read, never written — select-stack is its sole writer, and this run scanned the source paths it named (scanned_service_root / scanned_ui_root); scanned_backend_files / scanned_ui_files report each. ui_source_evidence_found false means the UI lane\'s declared path held nothing a scan recognises as UI, so its governance is thin — move the source path with /appweaver select-stack and re-run. The build/test/run commands on each lane are that PROFILE\'s defaults and may not match a legacy layout — review them. Because the domain is activated, resolve-domain + resolve-tech route the WHOLE forward pipeline to these code-derived rules — never another project\'s rules as a fallback. THE BOUNDARIES CAME FROM THE MAP, not from this run: /appweaver inventory proposed them and you confirmed them in specs/proposed-inventory.md. To change a boundary, edit that file and run /appweaver inventory apply — a context whose concepts already exist is not re-onboarded. Develop an EXISTING feature just-in-time: /appweaver adopt <Feature> reverse-engineers its spec.md + backend-plan.md + source-map.md and deepens the OKF concept of the aggregate it acts on. Develop a NEW feature straight through the forward pipeline — /appweaver select-feature FIRST (specify and every stage after it read the active feature and STOP without one), then specify → plan → analyze-plan → implement → build → analyze-slice → run. Then drive every change through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta). If a validation_ok is false, its constitution half needs a manual touch (see its Sync Impact Report)."
@@ -80,4 +80,6 @@ outputs:
80
80
  domain_rule_bindings: "{{map_path}}"
81
81
  domain_rule_bindings_exists: "{{map_exists}}"
82
82
  note: "Active project '{{domain}}' persisted to .appweaver/domain.json. It selects TWO rule maps under guardrails/projects/{{domain}}/ — domain-rule-bindings.md (DOMAIN rules; read by constitution + specify only, because the spec is the pivot) and tech-rule-bindings.md (TECHNICAL rules; read by 10 workflows incl. design, implement, build and run). The rule FILES themselves live in shared corpora — guardrails/technology/<stack>/ and guardrails/domain/<industry>/ — and the maps are what bind this project to them, so two projects can share a corpus and differ only in their maps and their own three requirements files. domain_rule_bindings_exists reports the domain half only. A map that is absent, or a command with no heading in one, loads nothing for that class and SOFT-CONTINUES — an absent heading is a valid state, never a failure."
83
- next: "/appweaver select-feature (then specify — the per-feature path). Re-run /appweaver select-domain any time to switch projects; it rebinds both maps at once."
83
+ # constitution comes BEFORE select-feature: it reads the domain rule map this
84
+ # workflow just bound, and specify declares its domain half as REQUIRED context.
85
+ next: "/appweaver constitution → select-feature → specify. /appweaver constitution authors the constitution halves from the domain rule map this run just bound — specify declares constitution.domain.md as REQUIRED context, and plan and implement read constitution.technical.md (plus constitution.ui.md on a frontend lane), so it runs before the first feature rather than after. /appweaver select-feature then picks the feature to build; every stage from specify onward reads that active feature and stops without it. Re-run /appweaver select-domain any time to switch projects; it rebinds both maps at once, and /appweaver constitution picks the new bindings up on its next run."
@@ -771,4 +771,7 @@ outputs:
771
771
  checklist_file: "{{checklist_file}}"
772
772
  checklist_quality: "{{checklist_passed}}/{{checklist_total}} items passing"
773
773
  note: "Behaviour and structure were authored together: the spec says what the system must do, {{domain_model}} says what the domain IS. The aggregate root, its entities and its invariants (BR-n) live in the model and are cited from the spec by id — never restated there, because several specs act on one aggregate and a per-spec copy drifts. On the DELTA path neither master was touched: this run wrote changes/{{cr_id}}/delta-spec.md and {{delta_model}}, and that model delta sits BESIDE the master where every other open delta can see it while being authored. WAVE {{wave}} is its parallel-development level — deltas sharing a wave are independent, a higher wave is implemented only after the lower ones land. The wave is DERIVED from the model delta's `## Depends on`: one above the highest delta named there, stamped into both halves as soon as it was authored ({{wave_message}}). To move it, correct that section and re-run `.appweaver/scripts/bash/aw-spec-actions.sh cr-wave-derive --cr-id {{cr_id}} --stamp`; finalize-delta refuses a change whose wave contradicts it. {{open_count}} change(s) are open on this feature."
774
- next: "/appweaver plan — BOOTSTRAP authors backend-plan.md from the spec + the domain model; a DELTA (this run opened change {{cr_id}}, wave {{wave}}) authors the delta plans for it. A change then flows: analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta (finalize-delta merges the delta into spec.md + domain-model.md — not the lane plans, which are derived from those two — but leaves the change open; analyze-slice verifies the slice against the merged master; close-delta archives the change and bumps the version). ⚠️ With more than one change open, plan, analyze-plan-delta and implement ASK which one they are for (pass the id as the argument to skip the prompt) and activate the answer; finalize-delta and close-delta still act on whichever change is active — so finish or close the others deliberately."
774
+ # Both paths spell out their WHOLE remaining chain. The bootstrap path named only
775
+ # `plan` and stopped there, which left a first greenfield run with no successor at
776
+ # the exact point the delta path was fully documented.
777
+ next: "/appweaver plan — BOOTSTRAP authors backend-plan.md from the spec + the domain model (plus frontend-plan.md where a UI lane is declared); a DELTA (this run opened change {{cr_id}}, wave {{wave}}) authors the delta plans for it. BOOTSTRAP then flows: plan → analyze-plan → implement → build → analyze-slice → run → deploy (analyze-plan is the spec↔plan gate and it repairs and stops only while NO change is open). A change instead flows: analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta (finalize-delta merges the delta into spec.md + domain-model.md — not the lane plans, which are derived from those two — but leaves the change open; analyze-slice verifies the slice against the merged master; close-delta archives the change and bumps the version). ⚠️ With more than one change open, plan, analyze-plan-delta and implement ASK which one they are for (pass the id as the argument to skip the prompt) and activate the answer; finalize-delta and close-delta still act on whichever change is active — so finish or close the others deliberately."
@@ -52,11 +52,29 @@ workflow:
52
52
  outputs:
53
53
  - { name: feature, from: "$.feature" }
54
54
  - { name: feature_dir, from: "$.feature_dir" }
55
- - { name: feature_slug, from: "$.feature_slug" }
55
+ - { name: feature_slug, from: "$.feature_slug" } # kebab-case route segment
56
56
  - { name: spec_file, from: "$.spec_file" }
57
57
  - { name: spec_exists, from: "$.spec_exists" }
58
- - { name: domain, from: "$.domain" }
59
- - { name: prototype_root, from: "$.prototype_root" }
58
+
59
+ # domain and prototype_root have their OWN resolvers — feature-paths answers for the
60
+ # feature's documents and nothing else, so binding them here left both empty and the
61
+ # emptiness reached the prompts as a blank path segment rather than an error.
62
+ - id: resolve_domain
63
+ action: execute_script
64
+ on_error: continue
65
+ script: { ref: actions }
66
+ subcommand: resolve-domain
67
+ args: ["--command", "/aw-spec-ui-model"]
68
+ outputs:
69
+ - { name: domain, from: "$.domain" }
70
+
71
+ - id: resolve_prototype_lane
72
+ action: execute_script
73
+ on_error: continue
74
+ script: { ref: actions }
75
+ subcommand: lane-resolve
76
+ outputs:
77
+ - { name: prototype_root, from: "$.prototype.root" }
60
78
 
61
79
  - id: require_feature
62
80
  action: verify_context
@@ -49,11 +49,29 @@ workflow:
49
49
  outputs:
50
50
  - { name: feature, from: "$.feature" }
51
51
  - { name: feature_dir, from: "$.feature_dir" }
52
- - { name: feature_slug, from: "$.feature_slug" }
52
+ - { name: feature_slug, from: "$.feature_slug" } # kebab-case route segment
53
53
  - { name: spec_file, from: "$.spec_file" }
54
54
  - { name: spec_exists, from: "$.spec_exists" }
55
- - { name: domain, from: "$.domain" }
56
- - { name: prototype_root, from: "$.prototype_root" }
55
+
56
+ # domain and prototype_root have their OWN resolvers — feature-paths answers for the
57
+ # feature's documents and nothing else, so binding them here left both empty and the
58
+ # emptiness reached the prompts as a blank path segment rather than an error.
59
+ - id: resolve_domain
60
+ action: execute_script
61
+ on_error: continue
62
+ script: { ref: actions }
63
+ subcommand: resolve-domain
64
+ args: ["--command", "/aw-spec-workflow-model"]
65
+ outputs:
66
+ - { name: domain, from: "$.domain" }
67
+
68
+ - id: resolve_prototype_lane
69
+ action: execute_script
70
+ on_error: continue
71
+ script: { ref: actions }
72
+ subcommand: lane-resolve
73
+ outputs:
74
+ - { name: prototype_root, from: "$.prototype.root" }
57
75
 
58
76
  - id: require_feature
59
77
  action: verify_context
@@ -49,7 +49,7 @@
49
49
  # version-read [--feature-dir <path>] -> {feature, version, active_change, exists, bootstrap_pending}
50
50
  # version-init [--feature-dir <path>] [--bootstrap] -> {…, created, bootstrap_pending} (create active_version.json v1.0; --bootstrap marks a FIRST draft in progress)
51
51
  # version-bootstrap-done [--feature-dir <path>] -> {…, cleared} (the ONLY clearer of the --bootstrap marker; call it when the first draft is finished)
52
- # feature-paths -> {feature, feature_dir, spec_file, backend_plan, frontend_plan, *_exists,
52
+ # feature-paths -> {feature, feature_slug, feature_dir, spec_file, backend_plan, frontend_plan, *_exists,
53
53
  # design_file/ui_design_file (aliases of the two plans), spec_exists, bootstrap_pending, needs_bootstrap}
54
54
  # checklist-read --file <path> -> {exists, total, checked, items[]}
55
55
  # checklist-apply --file <path> --results <json>-> {exists, before_checked, after_checked, total, newly_passing[], regressions[]}
@@ -1676,6 +1676,16 @@ cmd_feature_paths() {
1676
1676
  fi
1677
1677
  [[ "$fd" != /* ]] && fd="$repo_root/$fd"
1678
1678
  local feature; feature=$(basename "$fd") # the aggregate name (feature = specs/<Feature>)
1679
+ # feature_slug is the URL-safe form of that name, and it is what the UI stages use
1680
+ # as a route segment and a directory name (app/<slug>/page.tsx). It is derived here
1681
+ # rather than per workflow so every reader gets the same segment for one feature.
1682
+ # CamelCase splits on the case boundary before the non-alphanumeric squeeze, so
1683
+ # OrderManagement and "Order Management" both reach order-management.
1684
+ local feature_slug
1685
+ feature_slug=$(printf '%s' "$feature" \
1686
+ | sed -E 's/([a-z0-9])([A-Z])/\1-\2/g; s/([A-Z]+)([A-Z][a-z])/\1-\2/g' \
1687
+ | tr '[:upper:]' '[:lower:]' \
1688
+ | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//')
1679
1689
  # The master documents of a feature: spec.md (WHAT/WHY) + one LANE PLAN per declared
1680
1690
  # lane (each lane's HOW) — backend-plan.md for the service lane, frontend-plan.md for
1681
1691
  # the frontend lane. `plan` writes them; nothing else does.
@@ -1708,8 +1718,8 @@ cmd_feature_paths() {
1708
1718
  local needs_bootstrap=false
1709
1719
  [ "$spec_exists" = false ] && needs_bootstrap=true
1710
1720
  [ "$bootstrap_pending" = true ] && needs_bootstrap=true
1711
- printf '{"feature":"%s","feature_dir":"%s","spec_file":"%s","backend_plan":"%s","frontend_plan":"%s","backend_plan_exists":%s,"frontend_plan_exists":%s,"design_file":"%s","ui_design_file":"%s","spec_exists":%s,"design_exists":%s,"ui_design_exists":%s,"bootstrap_pending":%s,"needs_bootstrap":%s}\n' \
1712
- "$(json_escape "$feature")" "$(json_escape "$fd")" "$(json_escape "$spec")" \
1721
+ printf '{"feature":"%s","feature_slug":"%s","feature_dir":"%s","spec_file":"%s","backend_plan":"%s","frontend_plan":"%s","backend_plan_exists":%s,"frontend_plan_exists":%s,"design_file":"%s","ui_design_file":"%s","spec_exists":%s,"design_exists":%s,"ui_design_exists":%s,"bootstrap_pending":%s,"needs_bootstrap":%s}\n' \
1722
+ "$(json_escape "$feature")" "$(json_escape "$feature_slug")" "$(json_escape "$fd")" "$(json_escape "$spec")" \
1713
1723
  "$(json_escape "$design")" "$(json_escape "$ui_design")" "$design_exists" "$ui_design_exists" \
1714
1724
  "$(json_escape "$design")" "$(json_escape "$ui_design")" "$spec_exists" "$design_exists" "$ui_design_exists" \
1715
1725
  "$bootstrap_pending" "$needs_bootstrap"
@@ -1230,6 +1230,14 @@ function Invoke-FeaturePaths {
1230
1230
  if (-not $fd) { Write-Error 'feature-paths: no feature set (run /appweaver select-feature first)'; exit 1 }
1231
1231
  if (-not [System.IO.Path]::IsPathRooted($fd)) { $fd = Join-Path $repo $fd }
1232
1232
  $feature = Split-Path $fd -Leaf # the aggregate name (feature = specs/<Feature>)
1233
+ # feature_slug is the URL-safe form of that name, and it is what the UI stages use
1234
+ # as a route segment and a directory name (app/<slug>/page.tsx). It is derived here
1235
+ # rather than per workflow so every reader gets the same segment for one feature.
1236
+ # CamelCase splits on the case boundary before the non-alphanumeric squeeze, so
1237
+ # OrderManagement and "Order Management" both reach order-management.
1238
+ $featureSlug = $feature -creplace '([a-z0-9])([A-Z])', '$1-$2'
1239
+ $featureSlug = $featureSlug -creplace '([A-Z]+)([A-Z][a-z])', '$1-$2'
1240
+ $featureSlug = ($featureSlug.ToLowerInvariant() -replace '[^a-z0-9]+', '-').Trim('-')
1233
1241
  # The master documents of a feature: spec.md (WHAT/WHY) + one LANE PLAN per declared
1234
1242
  # lane (each lane's HOW) — backend-plan.md for the service lane, frontend-plan.md for
1235
1243
  # the frontend lane. `plan` writes them; nothing else does.
@@ -1264,6 +1272,7 @@ function Invoke-FeaturePaths {
1264
1272
  $specExists = (Test-Path $spec)
1265
1273
  Write-Json ([ordered]@{
1266
1274
  feature = $feature
1275
+ feature_slug = $featureSlug
1267
1276
  feature_dir = $fd
1268
1277
  spec_file = $spec
1269
1278
  backend_plan = $design
@@ -1,7 +1,7 @@
1
1
  # AW-SPEC FOUNDATION PACK
2
2
  # foundation: ModularMonolith
3
3
  # sentinel: AppWeaver.ModularMonolith
4
- # generated: 2026-09-14T11:40:41.0000000Z
4
+ # generated: 2026-09-23T10:25:01.0000000Z
5
5
  # files: 77
6
6
  # format: aw-spec-pack/v1
7
7
  # --- replacement contract (ordinal, case-sensitive, longest-first) ---
@@ -3873,8 +3873,8 @@ public class {AggregateName}Configuration : IEntityTypeConfiguration<{AggregateN
3873
3873
  <!-- ⚠️ TEMPORARY: Embedded PAT for internal testing only -->
3874
3874
  <packageSourceCredentials>
3875
3875
  <appweaver-framework>
3876
- <add key="Username" value="az" />
3877
- <add key="ClearTextPassword" value="64q8qlyZP7YZsJ2364v68PcpWQ6t20rcu3DF3KxmJ3t8jOexSIHGJQQJ99CFACAAAAAj3gtBAAASAZDO4ffH" />
3876
+ <add key="Username" value="YOUR_PAT_USERNAME" />
3877
+ <add key="ClearTextPassword" value="YOUR_PAT" />
3878
3878
  </appweaver-framework>
3879
3879
  </packageSourceCredentials>
3880
3880
 
@@ -1,8 +1,8 @@
1
1
  # AW-SPEC FOUNDATION PACK
2
2
  # foundation: VerticalSlice
3
3
  # sentinel: AppWeaver.VerticalSlice
4
- # generated: 2026-09-14T11:40:20.0000000Z
5
- # files: 56
4
+ # generated: 2026-09-23T10:21:27.0000000Z
5
+ # files: 55
6
6
  # format: aw-spec-pack/v1
7
7
  # --- replacement contract (ordinal, case-sensitive, longest-first) ---
8
8
  # <Sentinel> -> <AppName> (dotted: namespaces, csproj/sln, refs)
@@ -212,8 +212,8 @@
212
212
  <!-- ⚠️ TEMPORARY: Embedded PAT for internal testing only -->
213
213
  <packageSourceCredentials>
214
214
  <appweaver-framework>
215
- <add key="Username" value="az" />
216
- <add key="ClearTextPassword" value="64q8qlyZP7YZsJ2364v68PcpWQ6t20rcu3DF3KxmJ3t8jOexSIHGJQQJ99CFACAAAAAj3gtBAAASAZDO4ffH" />
215
+ <add key="Username" value="YOUR_PAT_USERNAME" />
216
+ <add key="ClearTextPassword" value="YOUR_PAT" />
217
217
  </appweaver-framework>
218
218
  </packageSourceCredentials>
219
219
 
@@ -240,7 +240,7 @@
240
240
  <<<FILE path="README.md">>>
241
241
  # AppWeaver MinimalMonolith Template
242
242
 
243
- A production-ready modular monolith template built with .NET 10, following Clean Architecture and Domain-Driven Design principles. **Now with .NET Aspire integration** for enhanced observability, service orchestration, and cloud-ready deployment.
243
+ A production-ready modular monolith template built with .10, following Clean Architecture and Domain-Driven Design principles. **Now with .NET Aspire integration** for enhanced observability, service orchestration, and cloud-ready deployment.
244
244
 
245
245
  ## 🚀 Quick Start
246
246
 
@@ -4862,121 +4862,3 @@ h1:focus {
4862
4862
  <<<FILE path="src/AppWeaver.VerticalSlice.Web/wwwroot/favicon.png" encoding="base64">>>
4863
4863
  iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEQ0lEQVR4XsVWTWxMURQ+XgaqagiFRkwjQcRCoxIrdKkJDFY0RRdUbEotREOMaFiAsWtZgEAkpEGiK6YsqZBIRRFGiqCio+0U8Jzv5n7JzctkzDTwJSd59+fdc853fu4d4vu+/E+E5B9hYGCgVAcnVXpU4gUFBQnMe39JWVQlprLFmY6rLFJZrnKTawjBn1a+XgcnnKkalTEqRzBo2vNeNu0uxmdKpdT7kxSrtFD53UQ/l2BQDINLxz7K7Wu98qh9AMOwSjSUR/wgFZIZZZZaSff+lNOHP0j3628yr6JQLO2S7Pwql49/FKDtWp/MKi+QbAZAKWjbYj2ISA64pd7By+4332XlhrECUHlj7WshwAANz2gAEsTSFqZXyc4v5qB+/SZcBTg03cc1kYVLiwRoPZ+CUe6aMdAiEgp6bbN1HS29fv6TtLf1Sz6YNXeE+bfRshEEnRpZ5LEKhAYkEDMsIltdxSNHeRKZMcz1ml4NCvvOTjHnhRzlcSrfq/F6+eSrAOWLCqVy9WgmDcFYGnof3fss+YLOeFY5srvOVQ6Ptx6YKPUHJ8r4kqFy5tAHJBLFjIGdzSXYh/2Db8W2RWq8U1DOg2GlUdR6ISVBwGvMgyE0FuxvqOrKOUcs2jzrfeS9JgvrtLp+HJTDU6MkG5AnYK14csj8lwPccN73bJ3Lrau9AozXgxavDjO2nDM0n70zjSLHb5TK1OkmjmAN+/Gf2fsbsEEBCY/dja2zUpUjF1C/VL4fGTtzuFFCuaue71LaqRBMgUX8/xv6mYApvRFb8HeEXpCeDqeprNo4Vvr1u2FNF+d4kCxcUmSoZ623qxM4PBvAkpt3HpuCWx6ocQJKEJ4cah5dEg5k8570g944DTDU/W2gTGtjEzjEg+QFDSBtQmOKS0ICMDfQ14N1Tk/RIwj8RzaDqNVSRbgUD1R5jPOeayG7Gw/nHV6oa6hz1DxoxGHIDYRqrZZetRWEC70kk3JSz6ojJJ1OJ1T8xs3P/RWzH/oN1U99jA9vT2JspC7a6SeffcK8ke63fWa9an6H33rxLef8M/FX2E9x1yE9KmW4e1wZopO4eo/gLm/WCwjY2TRZwzJcdlR1McNZkmCKFZMV6BGbNOYsOZS7Un9fCCcELcx2KOC7Dag/OAkHufd4VuU0EpTvPzeFMQd6qDwIz2bjKRX0dCpie0WzwesGB2dVukAdQLc8emWqzNNcwR2CZmUxxrw1guCr2C7CkDBDwcSs3maSixWCt17GauAbAUmIhsT/LFag60kQrAJd7LEtOQVloBBA84ExdcteGo+Sj78I4VZJk92jtyH2oGKgnLGvofJMCL6IorZFhuFtc+wdL6Sckq5yTdj1OqkSZexzMYBGlFkj5pB2UNrR/lmbzA8h2IRKNcvLKwqZcMQelbhlVvIxIPgyhkQkNyRhOIRtFhisAQSfa5QgoAgUJ4JU52XA/8QvRgye1rf4g4QAAAAASUVORK5CYII=
4864
4864
  <<<ENDFILE>>>
4865
- <<<FILE path="tests/AppWeaver.VerticalSlice.Tests/ef-debug-log.txt">>>
4866
- [2026-09-04 12:03:11Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4867
- [2026-09-04 12:03:11Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4868
- [2026-09-04 12:03:11Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4869
- [2026-09-04 12:03:12Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4870
- [2026-09-04 12:03:12Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4871
- [2026-09-04 12:03:12Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4872
- [2026-09-04 12:03:12Z] Using PostgreSQL (Aspire mode)
4873
- [2026-09-04 12:03:12Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4874
- [2026-09-04 12:03:12Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4875
- [2026-09-04 12:03:12Z] Using SQLite (Regular mode)
4876
- [2026-09-04 12:03:12Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4877
- [2026-09-04 12:19:21Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4878
- [2026-09-04 12:19:21Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4879
- [2026-09-04 12:19:21Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4880
- [2026-09-04 12:19:21Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4881
- [2026-09-04 12:19:21Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4882
- [2026-09-04 12:19:21Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4883
- [2026-09-04 12:19:21Z] Using PostgreSQL (Aspire mode)
4884
- [2026-09-04 12:19:21Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4885
- [2026-09-04 12:19:22Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4886
- [2026-09-04 12:19:22Z] Using SQLite (Regular mode)
4887
- [2026-09-04 12:19:22Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4888
- [2026-09-07 04:45:42Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4889
- [2026-09-07 04:45:42Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4890
- [2026-09-07 04:45:42Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4891
- [2026-09-07 04:45:43Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4892
- [2026-09-07 04:45:43Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4893
- [2026-09-07 04:45:43Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4894
- [2026-09-07 04:45:43Z] Using PostgreSQL (Aspire mode)
4895
- [2026-09-07 04:45:43Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4896
- [2026-09-07 04:45:43Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4897
- [2026-09-07 04:45:43Z] Using SQLite (Regular mode)
4898
- [2026-09-07 04:45:43Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4899
- [2026-09-07 04:49:09Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4900
- [2026-09-07 04:49:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4901
- [2026-09-07 04:49:10Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4902
- [2026-09-07 04:49:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4903
- [2026-09-07 04:49:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4904
- [2026-09-07 04:49:10Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4905
- [2026-09-07 04:49:10Z] Using PostgreSQL (Aspire mode)
4906
- [2026-09-07 04:49:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4907
- [2026-09-07 04:49:10Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4908
- [2026-09-07 04:49:10Z] Using SQLite (Regular mode)
4909
- [2026-09-07 04:49:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4910
- [2026-09-07 05:09:32Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4911
- [2026-09-07 05:09:32Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4912
- [2026-09-07 05:09:32Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4913
- [2026-09-07 05:09:33Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4914
- [2026-09-07 05:09:33Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4915
- [2026-09-07 05:09:33Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4916
- [2026-09-07 05:09:33Z] Using PostgreSQL (Aspire mode)
4917
- [2026-09-07 05:09:33Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4918
- [2026-09-07 05:09:33Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4919
- [2026-09-07 05:09:33Z] Using SQLite (Regular mode)
4920
- [2026-09-07 05:09:33Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4921
- [2026-09-07 09:13:08Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4922
- [2026-09-07 09:13:08Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4923
- [2026-09-07 09:13:08Z] Using PostgreSQL (Aspire mode)
4924
- [2026-09-07 09:13:13Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4925
- [2026-09-07 09:13:13Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4926
- [2026-09-07 09:13:13Z] Using PostgreSQL (Aspire mode)
4927
- [2026-09-08 04:24:24Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4928
- [2026-09-08 04:24:24Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4929
- [2026-09-08 04:24:25Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4930
- [2026-09-08 04:24:25Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4931
- [2026-09-08 04:24:25Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4932
- [2026-09-08 04:24:25Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4933
- [2026-09-08 04:24:25Z] Using PostgreSQL (Aspire mode)
4934
- [2026-09-08 04:24:25Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4935
- [2026-09-08 04:24:25Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4936
- [2026-09-08 04:24:25Z] Using SQLite (Regular mode)
4937
- [2026-09-08 04:24:25Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4938
- [2026-09-08 04:36:19Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4939
- [2026-09-08 04:36:20Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4940
- [2026-09-08 04:36:20Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4941
- [2026-09-08 04:36:20Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4942
- [2026-09-08 04:36:20Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4943
- [2026-09-08 04:36:20Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4944
- [2026-09-08 04:36:20Z] Using PostgreSQL (Aspire mode)
4945
- [2026-09-08 04:36:20Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4946
- [2026-09-08 04:36:20Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4947
- [2026-09-08 04:36:20Z] Using SQLite (Regular mode)
4948
- [2026-09-08 04:36:20Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4949
- [2026-09-08 04:40:52Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4950
- [2026-09-08 04:40:52Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4951
- [2026-09-08 04:40:52Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4952
- [2026-09-08 04:40:52Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4953
- [2026-09-08 04:40:52Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4954
- [2026-09-08 04:40:52Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4955
- [2026-09-08 04:40:52Z] Using PostgreSQL (Aspire mode)
4956
- [2026-09-08 04:40:52Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4957
- [2026-09-08 04:40:52Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4958
- [2026-09-08 04:40:52Z] Using SQLite (Regular mode)
4959
- [2026-09-08 04:40:52Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4960
- [2026-09-08 05:00:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4961
- [2026-09-08 05:00:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4962
- [2026-09-08 05:00:10Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4963
- [2026-09-08 05:00:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4964
- [2026-09-08 05:00:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4965
- [2026-09-08 05:00:10Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4966
- [2026-09-08 05:00:10Z] Using PostgreSQL (Aspire mode)
4967
- [2026-09-08 05:00:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4968
- [2026-09-08 05:00:10Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4969
- [2026-09-08 05:00:10Z] Using SQLite (Regular mode)
4970
- [2026-09-08 05:00:10Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4971
- [2026-09-08 05:01:44Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4972
- [2026-09-08 05:01:44Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4973
- [2026-09-08 05:01:44Z] PostgreSQL Connection For DataStore: Host=localhost;Database=test;Username=postgres;Password=******
4974
- [2026-09-08 05:01:44Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4975
- [2026-09-08 05:01:44Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4976
- [2026-09-08 05:01:44Z] PostgreSQL Connection: Host=localhost;Database=test;Username=postgres;Password=******
4977
- [2026-09-08 05:01:44Z] Using PostgreSQL (Aspire mode)
4978
- [2026-09-08 05:01:44Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4979
- [2026-09-08 05:01:44Z] SQLite Database: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/test_db_factory.db
4980
- [2026-09-08 05:01:44Z] Using SQLite (Regular mode)
4981
- [2026-09-08 05:01:44Z] [EnvLoader] No .env file found at: /Users/anagha.eg/Documents/Workspace/appweaver/templates/AppWeaver.VerticalSlice.V1/tests/AppWeaver.VerticalSlice.Tests/bin/Debug/net10.0/.env
4982
- <<<ENDFILE>>>