@topy-ai/maggie 0.7.20 → 0.7.22

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/README.md CHANGED
@@ -76,6 +76,15 @@ maggie qa summary --project . --run <run-id>
76
76
  The QA workflow stores secret-free run state under `.maggie/qa-runs/` and
77
77
  keeps project-specific scenarios and evidence outside the npm package.
78
78
 
79
+ Before recording a passing user-facing assertion, lint it against runtime
80
+ evidence; source-only class or markup checks are rejected:
81
+
82
+ ```bash
83
+ maggie qa assertion-audit --project . \
84
+ --assertions .maggie/qa-assertions.json \
85
+ --output docs/qa-assertion-audit.json
86
+ ```
87
+
79
88
  Dashboard and documentation audits are provider-neutral and keep host data
80
89
  behind explicit evidence files:
81
90
 
@@ -123,6 +132,24 @@ variants use market/locale-aware canonical routes and reciprocal hreflang.
123
132
  Release preflight consumes the latest matching scenario QA run when one is
124
133
  configured and blocks incomplete evidence.
125
134
 
135
+ The provider-owned parser also supports safe catalogue and lifecycle review:
136
+
137
+ ```bash
138
+ maggie service catalogue-check "<provider-location-url>" \
139
+ --treatment "Lymphatic drainage massage"
140
+ maggie service sync-report --project .
141
+ maggie service retirement-audit --project . \
142
+ --catalogue .maggie/booking/services.json \
143
+ --evidence .maggie/booking/retirement-evidence.json
144
+ ```
145
+
146
+ `catalogue-check` avoids marketplace noise when the provider exposes an
147
+ authoritative embedded catalogue. `sync-report` shows field and variant
148
+ before/after changes. `retirement-audit` validates sanitized runtime evidence
149
+ for `pending`, `redirect`, `tombstone`, or `gone` endings, including HTTP
150
+ status, booking suppression, noindex/unavailable signals, and sitemap
151
+ exclusion. Response bodies are never stored.
152
+
126
153
  For Google integrations, validate a redacted provider matrix before reporting
127
154
  access. The command fails closed on unknown scopes, missing Ads prerequisites,
128
155
  duplicate provider resources, and unverified edit/publish claims:
@@ -183,7 +210,7 @@ maggie memory ... # confirmed preferences and lessons
183
210
  maggie feedback ... # redact, preview, submit, list
184
211
  maggie qa ... # scenario browser QA, fix/retest, release gate
185
212
  maggie localization ... # plan, validate, review, publish, stale
186
- maggie service ... # import, sync, capability audit, validate
213
+ maggie service ... # import, sync/report, catalogue, lifecycle, validate
187
214
  maggie seo performance ... # sampled PageSpeed/CWV report and baseline
188
215
  maggie seo images ... # inventory, variants, confirmation, validate
189
216
  maggie seo sitemap ... # typed/semantic plan, agent-files, apply, rollback
@@ -192,6 +219,7 @@ maggie seo social-cards ... # per-page og:image format/dimension audit
192
219
  maggie seo head-tags ... # rendered-shell head metadata drift audit
193
220
  maggie ops favicon-check ... # served favicon behaviour check
194
221
  maggie deployment | migration | release | analytics | schedule
222
+ maggie deployment readiness --project PATH
195
223
  maggie migration identity --identity-file FILE [--expected-file FILE]
196
224
  maggie deployment canary --asset URL=SHA256 --render-report report.json
197
225
  maggie design icon-inventory --source-dir src --runtime assets/icons.css
@@ -280,6 +308,25 @@ The canary report requires a screenshot and zero console errors, missing
280
308
  assets, and visual placeholders for every route. It records safe cache headers
281
309
  only and never stores response bodies, cookies, or credentials.
282
310
 
311
+ Unit regression does not establish runtime release readiness. Produce unit
312
+ evidence and then validate all five release evidence slots:
313
+
314
+ ```bash
315
+ python3 tools/tests/run_regression.py \
316
+ --report .maggie/verification/unit-regression.json
317
+ maggie deployment readiness --project . \
318
+ --package-report .maggie/verification/package-smoke.json \
319
+ --browser-report .maggie/verification/browser-evidence.json \
320
+ --rendered-canary .maggie/deployment-canary.json \
321
+ --deployment-preflight .maggie/release-preflight.json \
322
+ --output .maggie/deployment-readiness.json
323
+ ```
324
+
325
+ The readiness report follows `maggie-deployment-readiness.v1`. It reports unit
326
+ regression, package smoke, host browser evidence, rendered canary, and
327
+ deployment preflight separately. Missing host adapter evidence is
328
+ `inconclusive`; only five passing slots produce `passed`.
329
+
283
330
  ### Localization and analytics release gates
284
331
 
285
332
  Extract real page strings before creating a localization job, then require a
@@ -305,8 +352,8 @@ artifact schemas.
305
352
  Recommended upgrade sequence for the current release:
306
353
 
307
354
  ```bash
308
- npx @topy-ai/maggie@0.7.20 update --project . --force
309
- npx @topy-ai/maggie@0.7.20 cleanup --project .
355
+ npx @topy-ai/maggie@0.7.22 update --project . --force
356
+ npx @topy-ai/maggie@0.7.22 cleanup --project .
310
357
  ```
311
358
 
312
359
  Maintainers should pass npm credentials through the repository helper, never
@@ -316,6 +363,11 @@ as a command-line argument:
316
363
  node scripts/publish-npm.mjs --maggie-env-file ../.env
317
364
  ```
318
365
 
366
+ The 0.7.22 workflow adds provider-catalogue authority checks, field/variant
367
+ sync reports, separate supply/display states, site-owned slug proposals,
368
+ withdrawal endings, retirement evidence audits, and runtime QA assertion lint.
369
+ The 0.7.21 workflow adds operation-specific localization quality checks,
370
+ explicit deployment readiness evidence states, and serialized package assembly.
319
371
  The 0.7.20 workflow completes the MaggieDash Activity and Navigation
320
372
  workspaces and dashboard UI v3 contract. The 0.7.19 workflow adds
321
373
  documentation hygiene audits, live URL API contract
package/README.zh-TW.md CHANGED
@@ -8,7 +8,7 @@ Codex、Claude Code 與相容的 coding agents。
8
8
  ## 安裝
9
9
 
10
10
  ```bash
11
- npx @topy-ai/maggie@0.7.20 init --agent all
11
+ npx @topy-ai/maggie@0.7.22 init --agent all
12
12
  npx @topy-ai/maggie doctor --project .
13
13
  ```
14
14
 
@@ -25,6 +25,11 @@ maggie doctor --project . --require-bootstrap --strict
25
25
  deployment、memory、feedback 和 MaggieDash。內容先 draft/review,外部寫入、
26
26
  publish 與 production deployment 需要明確確認。
27
27
 
28
+ 0.7.22 加入 provider catalogue authority check、field/variant sync report、
29
+ supply/display lifecycle state、site-owned slug proposal、withdrawal ending、
30
+ retirement evidence audit,以及 runtime QA assertion lint。
31
+ 0.7.21 增加 localization polish/rewrite 的 operation-specific quality checks、
32
+ deployment readiness evidence 狀態,以及並發 package assembly 保護。
28
33
  0.7.20 完成 MaggieDash Activity 與 Navigation workspace,以及 dashboard UI v3
29
34
  contract。0.7.19 加入文件 hygiene audit、live URL API contract、schema reader audit、
30
35
  dashboard runtime evidence,以及 activity-log 和 managed-navigation contracts。
@@ -38,6 +43,10 @@ MaggieDash 也提供穩定 section identity、可重用 section arrangement、
38
43
  section registry、短期 agent content bridge,以及 translation out-of-band write
39
44
  後的 restart gate。`maggie doctor` 會比較 install manifest 與磁碟上的實際 skills。
40
45
 
46
+ `maggie deployment readiness` 會分開檢查 unit regression、package smoke、host
47
+ browser evidence、rendered canary 與 deployment preflight。缺少必要 adapter 時
48
+ 回傳 `inconclusive`,只有五組 evidence 全部通過才回傳 `passed`。
49
+
41
50
  新版 release gates:
42
51
 
43
52
  ```bash
@@ -70,6 +79,14 @@ maggie service capability-audit --project . \
70
79
  --catalogue .maggie/booking/services.json \
71
80
  --capabilities-file .maggie/booking/provider-capabilities.json \
72
81
  --fixture .maggie/booking/fixtures/provider.json
82
+
83
+ # Provider catalogue and withdrawal lifecycle review
84
+ maggie service catalogue-check "<provider-location-url>" \
85
+ --treatment "Lymphatic drainage massage"
86
+ maggie service sync-report --project .
87
+ maggie service retirement-audit --project . \
88
+ --catalogue .maggie/booking/services.json \
89
+ --evidence .maggie/booking/retirement-evidence.json
73
90
  ```
74
91
 
75
92
  完整中文說明、19 個 skills 清單和 roadmap:
package/bin/maggie.js CHANGED
@@ -100,6 +100,9 @@ Usage:
100
100
  maggie design status <job-id>
101
101
  maggie service import <provider-url> --project PATH
102
102
  maggie service sync <provider-url> --project PATH
103
+ maggie service catalogue-check <provider-url> --treatment NAME
104
+ maggie service sync-report --project PATH
105
+ maggie service retirement-audit --project PATH --evidence FILE
103
106
  maggie service generate --project PATH
104
107
  maggie service capability-audit --project PATH --catalogue FILE --capabilities-file FILE --fixture FILE
105
108
  maggie service validate --project PATH
@@ -108,6 +111,7 @@ Usage:
108
111
  maggie service convert-page <page-path> --project PATH
109
112
  maggie service match-pages --project PATH --pages-dir src/pages
110
113
  maggie deployment --project PATH --target vps-with-cloudflare-dns
114
+ maggie deployment readiness --project PATH
111
115
  maggie deployment canary --project PATH --asset URL=SHA256 --render-report report.json --output docs/deployment-canary.json
112
116
  maggie migration --project PATH --environment staging
113
117
  maggie migration identity --identity-file FILE [--expected-file FILE]
@@ -119,7 +123,7 @@ Usage:
119
123
  maggie localization <extract|plan|generate|preview|validate|review|publish|stale|glossary> [options]
120
124
  maggie seo performance|images|sitemap|indexnow|social-cards|head-tags [options] (sitemap supports strict validate and agent-files)
121
125
  maggie feedback <collect|preview|submit|list> [options]
122
- maggie qa <start|record|summary|export> [options]
126
+ maggie qa <start|record|summary|export|assertion-audit> [options]
123
127
  maggie site-audit URL [--crawl] [--access-log FILE] [--require-sitemap-request] [--languages en-GB,es-MX,ja-JP] [--check-hreflang]
124
128
  maggie site-audit URL --crawl --save-baseline FILE --reviewer NAME
125
129
  maggie site-audit URL --crawl --baseline FILE
@@ -408,6 +412,7 @@ try {
408
412
  else if (command === "seo") seo(args);
409
413
  else if (command === "ops") workflowCli("maggie_ops.py", args);
410
414
  else if (command === "deployment" && args[0] === "canary") workflowCli("maggie_deployment_canary.py", args.slice(1));
415
+ else if (command === "deployment" && args[0] === "readiness") workflowCli("maggie_deployment_readiness.py", args.slice(1));
411
416
  else if (command === "deployment") workflowCli("maggie_deployment.py", args);
412
417
  else if (command === "migration") workflowCli("maggie_migration.py", args);
413
418
  else if (command === "schedule") workflowCli("maggie_schedule.py", args);
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/deployment-readiness-v1.json",
4
+ "title": "Maggie deployment readiness evidence summary",
5
+ "type": "object",
6
+ "required": ["schemaVersion", "status", "checks"],
7
+ "properties": {
8
+ "schemaVersion": {"const": "maggie-deployment-readiness.v1"},
9
+ "status": {"enum": ["passed", "failed", "inconclusive"]},
10
+ "checks": {
11
+ "type": "object",
12
+ "required": ["unitRegression", "packageSmoke", "browserEvidence", "renderedCanary", "deploymentPreflight"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "unitRegression": {"$ref": "#/$defs/check"},
16
+ "packageSmoke": {"$ref": "#/$defs/check"},
17
+ "browserEvidence": {"$ref": "#/$defs/check"},
18
+ "renderedCanary": {"$ref": "#/$defs/check"},
19
+ "deploymentPreflight": {"$ref": "#/$defs/check"}
20
+ }
21
+ }
22
+ },
23
+ "$defs": {
24
+ "check": {
25
+ "type": "object",
26
+ "required": ["state", "configured"],
27
+ "properties": {
28
+ "state": {"enum": ["passed", "failed", "inconclusive", "not-configured"]},
29
+ "configured": {"type": "boolean"},
30
+ "path": {"type": "string"},
31
+ "reason": {"type": "string"}
32
+ },
33
+ "additionalProperties": true
34
+ }
35
+ },
36
+ "additionalProperties": false
37
+ }
@@ -61,6 +61,15 @@ Supported operations are distinct: `translate`, `polish`, `rewrite`,
61
61
  source. A source revision change marks dependent translations stale. Fallback
62
62
  content is never indexable.
63
63
 
64
+ `polish` and `rewrite` validation includes deterministic output checks. Polish
65
+ must keep the source language, change the copy, preserve protected fact tokens,
66
+ and show a clarity signal (shorter maximum sentence, clearer sentence
67
+ segmentation, placeholder reduction, or explicit quality evidence). Rewrite
68
+ must change the copy and its observable structure, while preserving protected
69
+ fact tokens. These are conservative heuristics, not semantic equivalence
70
+ proof: every result contains `quality.humanReview.required: true` and marks
71
+ semantic equivalence as `not-certified` until a named reviewer approves it.
72
+
64
73
  The following are protected by default: price, currency, rating, provider
65
74
  facts, booking URL, legal/health claims, content ID, slug, canonical owner,
66
75
  and translation group. Changes require structured approval and evidence.
@@ -57,7 +57,7 @@ The stable model is deliberately small and provider-neutral:
57
57
  - **category**: `level1` and `level2`; a service may belong to more than one
58
58
  provider category through `additional.provider.categories`;
59
59
  - **service**: identity, slug, title, description, active/archived status,
60
- timestamps, and variants;
60
+ timestamps, supply/display state, and variants;
61
61
  - **variant**: identity, display name, duration, price, currency, discount or
62
62
  price range when the provider exposes them;
63
63
  - **booking actions**: booking URL, payment URL, and optional action metadata;
@@ -67,6 +67,44 @@ The stable model is deliberately small and provider-neutral:
67
67
  - **sync**: source, fetched time, content hash, parser version, and change
68
68
  status.
69
69
 
70
+ The portable lifecycle model keeps two owners separate:
71
+
72
+ - `supplyState`: provider sync state, either `live` or `withdrawn`;
73
+ - `displayState`: human publication decision, either `published`, `hidden`, or
74
+ `retired`.
75
+
76
+ Sync may change `supplyState` when the provider adds or removes a service, but
77
+ must preserve `displayState`. A withdrawn/published record is an explicit
78
+ interim state: keep the URL answerable, suppress booking and indexing, and
79
+ open a human retirement decision. The legacy `status` field may remain for
80
+ backwards compatibility, but it must not be used as both provider availability
81
+ and display policy.
82
+
83
+ The `slug` is site-owned. A provider rename may produce a `slugProposal` in a
84
+ sync report, but the stored slug remains unchanged until a person accepts the
85
+ proposal and the host writes the new slug plus its redirect in one transaction.
86
+
87
+ ## Withdrawal and retirement contract
88
+
89
+ Provider removal is not permission to delete a public route. The adapter keeps
90
+ the record with `supplyState: "withdrawn"` and the host chooses a reviewed
91
+ `retirement.ending`:
92
+
93
+ | Ending | Required host response | Required safety signals |
94
+ |---|---|---|
95
+ | `pending` | HTTP 200 interim page | unavailable notice, no booking action, `noindex`, absent from sitemap |
96
+ | `redirect` | HTTP 301 or 308 to a different same-site route | no booking action, absent from sitemap |
97
+ | `tombstone` | HTTP 200 unavailable page | unavailable notice, no booking action, `noindex`, absent from sitemap |
98
+ | `gone` | HTTP 410 | no booking action, absent from sitemap |
99
+
100
+ The host must preserve the old route long enough to apply its chosen ending,
101
+ and must not return a generic 404 as a substitute for the reviewed contract.
102
+ `maggie service retirement-audit` validates sanitized runtime evidence against
103
+ the catalogue and records only service IDs, ending decisions, statuses, and
104
+ safe pass/fail metadata. It does not fetch private routes, store response
105
+ bodies, or invent redirect targets. A person must review redirect destination,
106
+ copy, and accessibility before publication.
107
+
70
108
  The service page must render only canonical fields. `additional` is an
71
109
  explicit extension point for provider-specific or future fields and must be
72
110
  namespaced by concern (`provider`, `location`, `presentation`, `compliance`,
@@ -74,6 +112,21 @@ namespaced by concern (`provider`, `location`, `presentation`, `compliance`,
74
112
  nullable-safe, and must never override canonical fields. Unknown data stays in
75
113
  `additional`; it is not guessed into the stable model.
76
114
 
115
+ ## Source ownership and onboarding precedence
116
+
117
+ When a host onboarding flow collects a value directly from the merchant, that
118
+ explicit value is authoritative for the project. Provider research, imported
119
+ profiles, search results, and inferred metadata may fill an empty field only;
120
+ they must never replace a non-empty merchant entry. Persist the source of each
121
+ value when the host supports it, and show a conflict for human review when two
122
+ non-empty sources disagree. This rule applies to the website URL as well as
123
+ business name, address, phone, category, and booking-provider identity.
124
+
125
+ The shared service-booking parser does not implement a host's onboarding UI.
126
+ Adapters must enforce this precedence before passing project identity into
127
+ provider research or sync. A provider URL is evidence about the provider
128
+ catalogue, not permission to overwrite the merchant's website URL.
129
+
77
130
  Pages can also enter the model without a provider. A normal page conversion
78
131
  creates a `draft` service with `additional.conversion.sourcePage` and no
79
132
  invented price, duration, or booking URL. It becomes `active` only after the
@@ -104,6 +157,14 @@ silent conversion, idempotent add/update/archive synchronisation, source
104
157
  snapshots/checksums, import-run audit records and generated service pages with
105
158
  provider booking CTAs.
106
159
 
160
+ When a provider exposes an authoritative venue-owned catalogue, use that
161
+ adapter extraction for sync decisions and treatment-presence checks. Generic
162
+ JSON-LD, navigation links, and page-wide text can contain marketplace or other
163
+ business entities and are not proof that the connected venue still sells a
164
+ treatment. A read-only catalogue query should call the same parser as import
165
+ and sync so an operator can review a reproducible answer before applying a
166
+ withdrawal.
167
+
107
168
  It must not claim real-time availability, booking creation, cancellation sync
108
169
  or webhooks unless an official Fresha partner/API capability is available for
109
170
  that account. Public booking links remain the safe fallback. The paid Fresha
@@ -14,9 +14,12 @@ metadata:
14
14
  changes; translate and polish preserve meaning; localise enables market
15
15
  adaptation. A host generation adapter or the authoring agent must apply these
16
16
  instructions when producing copy. Planning does not invoke a model or generate
17
- translations. Validation currently checks mode consistency and rewrite
18
- permission, not whether prose was actually restructured. Review the produced
19
- copy against the requested operation before approval.
17
+ translations. Validation now applies deterministic operation-specific checks to
18
+ polish and rewrite outputs: source/output text must be present, protected fact
19
+ tokens must remain unchanged, polish must show a clarity signal, and rewrite
20
+ must change observable structure. These checks are conservative heuristics,
21
+ not semantic equivalence proof. Every result requires named human review and
22
+ reports `semanticEquivalence: not-certified` until approval.
20
23
 
21
24
  ### Resumable draft generation
22
25
 
@@ -37,6 +37,31 @@ visitor-facing files. The canary must include screenshots, zero console or
37
37
  network errors, and zero placeholder matches. Query-driven routes belong in
38
38
  behavior/API checks, not static byte baselines.
39
39
 
40
+ ## Release readiness evidence
41
+
42
+ Unit regression is necessary but does not prove runtime release readiness. The
43
+ readiness command keeps five evidence slots separate: dependency-free unit
44
+ regression, package smoke, host browser evidence, rendered canary, and
45
+ deployment preflight:
46
+
47
+ ```bash
48
+ python3 tools/tests/run_regression.py \
49
+ --report .maggie/verification/unit-regression.json
50
+ maggie deployment readiness --project . \
51
+ --package-report .maggie/verification/package-smoke.json \
52
+ --browser-report .maggie/verification/browser-evidence.json \
53
+ --rendered-canary .maggie/deployment-canary.json \
54
+ --deployment-preflight .maggie/release-preflight.json \
55
+ --output .maggie/deployment-readiness.json
56
+ ```
57
+
58
+ The report follows `maggie-deployment-readiness.v1`. A failed evidence file
59
+ returns `failed`; a missing or unavailable host/browser adapter returns
60
+ `inconclusive`; only five passing evidence slots return `passed`. Maggie does
61
+ not fabricate browser, rendered, or deployment evidence and does not deploy
62
+ from this command. See
63
+ [`readiness-v1.schema.json`](../../bundled-contracts/maggie-deployment/readiness-v1.schema.json).
64
+
40
65
  ## Automatic memory hook
41
66
 
42
67
  Follow [Maggie Memory Hook](../../references/memory-hook.md) at invocation and completion.
@@ -74,6 +74,26 @@ the host browser adapter. The adapter owns console, network, authentication,
74
74
  URL, viewport, and screenshot capture; this skill stores only a relative path,
75
75
  URL reference, and hash when a local file exists.
76
76
 
77
+ ## Assert the requirement at runtime
78
+
79
+ Do not use a source class, edited markup fragment, or implementation detail as
80
+ the proof of a user-facing requirement. Describe runtime assertions in a
81
+ project-local manifest and lint it before recording a passing scenario:
82
+
83
+ ```bash
84
+ maggie qa assertion-audit --project . \
85
+ --assertions .maggie/qa-assertions.json \
86
+ --output docs/qa-assertion-audit.json
87
+ ```
88
+
89
+ The `maggie.qa-assertions.v1` manifest requires a route, `transport: "http"`,
90
+ HTTP status evidence, a screenshot/reference, and boolean results for runtime
91
+ checks such as `text-present`, `text-absent`, `meta`, `link-absent`, or
92
+ `redirect`. Source/class/markup-only checks are rejected. The audit stores
93
+ assertion IDs and safe pass/fail metadata, never response bodies, credentials,
94
+ or cookies. A passing assertion audit complements browser evidence; it does
95
+ not replace the host adapter's actual HTTP and screenshot capture.
96
+
77
97
  ## Gate and release evidence
78
98
 
79
99
  The run gate is `fail` when any scenario fails, `blocked` when there is no
@@ -2,7 +2,7 @@
2
2
  name: maggie-service-booking
3
3
  description: Import, synchronise, validate, and design SPA service pages from a booking provider such as Fresha. Use for service catalogues, treatment variants, prices, durations, booking links, payment links, and booking-aware page generation.
4
4
  metadata:
5
- version: 1.1.0
5
+ version: 1.2.0
6
6
  ---
7
7
 
8
8
  # Maggie Service Booking
@@ -49,6 +49,13 @@ passed the provider capability check. A project without Fresha may use Google
49
49
  Calendar as a simple fallback, but it must be recorded as a separate
50
50
  BookingProvider.
51
51
 
52
+ If onboarding also asks the merchant for a website or business identity, the
53
+ merchant's non-empty answer owns that field. Imported provider/profile/search
54
+ values are fallback evidence for empty fields only; a disagreement must become
55
+ a visible review item, never a silent replacement. This skill does not own the
56
+ host onboarding UI, so enforce the rule in the host adapter before starting
57
+ provider research.
58
+
52
59
  ## CLI workflow
53
60
 
54
61
  Run from the project root:
@@ -62,6 +69,8 @@ python3 tools/clis/maggie_service_booking.py sync \
62
69
  "https://www.fresha.com/a/spa-chevy-chase-chevy-chase-4500-north-park-avenue-sbic60h4?pId=512061" \
63
70
  --project .
64
71
 
72
+ python3 tools/clis/maggie_service_booking.py sync-report --project .
73
+
65
74
  python3 tools/clis/maggie_service_booking.py generate --project . --copy-data docs/service-page-copy.json
66
75
  python3 tools/clis/maggie_service_booking.py validate --project .
67
76
 
@@ -116,17 +125,40 @@ python3 tools/clis/maggie_service_booking.py capability-audit \
116
125
  --catalogue .maggie/booking/services.json \
117
126
  --capabilities-file .maggie/booking/provider-capabilities.json \
118
127
  --fixture .maggie/booking/fixtures/provider.json
128
+
129
+ # Answer whether provider-owned treatments are present using the same parser
130
+ # as import/sync; do not search the whole provider page for a name.
131
+ python3 tools/clis/maggie_service_booking.py catalogue-check \
132
+ "https://www.fresha.com/a/your-location" \
133
+ --provider fresha --treatment "Lymphatic drainage massage"
134
+
135
+ python3 tools/clis/maggie_service_booking.py retirement-audit \
136
+ --project . \
137
+ --catalogue .maggie/booking/services.json \
138
+ --evidence .maggie/booking/retirement-evidence.json
119
139
  ```
120
140
 
121
141
  `import` creates the first catalogue. `sync` compares the newly imported
122
142
  catalogue with the previous snapshot and records `added`, `updated`,
123
- `removed`, and `unchanged` services. Removed services are archived in the
124
- manifest before any page is deleted. `generate` is retained as a compatibility
143
+ `removed`, and `unchanged` services. Updated records include field-level
144
+ before/after values, variant-level changes, and any pending slug proposal.
145
+ `sync-report` is read-only and loads a saved `maggie-service-sync-report.v1`
146
+ artifact for review. Removed services are archived in the manifest before any
147
+ page is deleted. `generate` is retained as a compatibility
125
148
  guard and refuses to author public copy. The AI agent and the MaggieDash renderer
126
149
  must consume an approved copy artifact instead. `run` executes parse → persist
127
150
  → validate, then stops before public generation until an AI-authored copy
128
151
  artifact and editorial review are present; it records `.maggie/booking/job.json`.
129
152
  `inspect` is read-only and `status` reports the latest job state.
153
+ `catalogue-check` is read-only and answers one or more treatment-presence
154
+ questions from the same provider-owned extraction used by `import` and `sync`.
155
+ It does not use arbitrary page links or marketplace JSON-LD as evidence when
156
+ the provider exposes an authoritative embedded catalogue.
157
+ `retirement-audit` is also read-only. It consumes a sanitized host-browser/HTTP
158
+ evidence artifact and validates the selected ending (`pending`, `redirect`,
159
+ `tombstone`, or `gone`), HTTP status, booking suppression, unavailable/noindex
160
+ signals, and sitemap exclusion. It never stores response bodies or decides a
161
+ redirect destination for the host.
130
162
  `convert-page` imports a normal page as a draft service without inventing
131
163
  booking facts. `match-pages` reads filesystem pages plus `docs/pages.json` and
132
164
  `docs/page-content.json`, writes candidate evidence to both `.maggie/booking`
@@ -220,6 +252,19 @@ Every active service must have:
220
252
  - a booking URL, and a payment URL only when explicitly supplied;
221
253
  - provider, source URL, `firstSeenAt`, `lastSeenAt`, and sync status.
222
254
 
255
+ The portable catalogue also carries `supplyState` (`live` or `withdrawn`) and
256
+ `displayState` (`published`, `hidden`, or `retired`). The sync owns only
257
+ `supplyState`; it must preserve a person's `displayState` and must not silently
258
+ republish a hidden or retired service. Keep legacy `status` only for
259
+ compatibility, never as both meanings at once.
260
+
261
+ Withdrawn services remain available for an explicit retirement decision. Set
262
+ `retirement.ending` to `pending` while a host still serves a safe interim
263
+ response, or to an approved `redirect`, `tombstone`, or `gone` ending. A
264
+ withdrawn route must suppress booking and sitemap inclusion; the host owns the
265
+ actual route/HTTP implementation and supplies sanitized evidence to
266
+ `retirement-audit` before release.
267
+
223
268
  The canonical shape is documented in
224
269
  [`references/universal-booking-adapter.md`](../../references/universal-booking-adapter.md).
225
270
  Do not invent prices, availability, practitioner claims, ratings, medical