Deckhand API Presence-Sync
New API paths (workflows) land roughly daily in the Deckhand routing catalog
(deckhand/config/deckhand/routing/domain-workflows.yaml). This skill runs weekly,
computes the delta of new API paths since the last run, and refreshes the public
presence surfaces by opening HITL draft PRs in the relevant repos.
It is read-and-propose only: it NEVER pushes to a default branch, NEVER publishes, and NEVER merges. The owner reviews and merges every draft PR.
When to Use
- The weekly cadence fires (see Cadence & install), OR
- The owner asks to re-sync presence surfaces after new workflows landed.
Scope guardrails (read first)
- Only
live_publicpaths may be claimed as capability on public surfaces — those withartifact_residency: public-sandbox(a publicreport.htmlon deckhand-sandbox). live_private(client-wiki delivery) andinternal(router/escalation) paths are tracked but never claimed on public surfaces.roadmappaths (bound channel domains with no workflow row yet) are listed as "coming" at most — never claimed as an existing capability.- Respect the locked messaging in
aceengineer-strategy#94/aceengineer-strategy/strategy/messaging/api-centric-claims-2026-06-28.md(approved tagline + approved/banned claims). Do not invent claims beyond that file. - PII-free. No client identifiers in public copy (legal gate enforces this — Step 4).
Inputs
- Canonical catalog (single source of truth):
deckhand/docs/deckhand/api-catalog.json— Deckhand's PUBLISHED, already-public-safe API-path catalog (generated by deckhand#501). It contains onlylive_public+roadmaprows, with every private/internal client path reduced toprivate_internal_count(no codenames, refs, or descriptions).catalog_delta.pyPREFERS this artifact. (resolved via--canonical,$DECKHAND_API_CATALOG,$DECKHAND_REPO, or the sibling../deckhandcheckout — no hardcoded absolute path). - Routing catalog (derive fallback):
deckhand/config/deckhand/routing/domain-workflows.yaml— the skill derives the same public-safe view from this routing file when the canonical artifact is absent (legacy behaviour). (resolved via--catalog,$DECKHAND_CATALOG,$DECKHAND_REPO, or../deckhand). - Snapshot:
state/api-catalog-snapshot.json(last-synced view; seestate/README.md).
Source resolution (--source {canonical,derive,auto}, default auto)
catalog_delta.py resolves the current path list from one of two sources, and both
yield the identical public-safe shape the rest of the skill consumes (live_public +
roadmap rows only; private/internal reduced to a count; codename-free):
canonical— read the publishedapi-catalog.jsondirectly (single source of truth).derive— build the public-safe view fromdomain-workflows.yaml(fallback).auto(default) — PREFERcanonicalwhen the published artifact exists; otherwise FALL BACK toderive.
Procedure
Step 1 — Read the current catalog → API-path list
cd .claude/skills/business-marketing/deckhand-api-presence-sync
uv run --no-project --with pyyaml python catalog_delta.py --emit-current
By default (--source auto) this reads Deckhand's published canonical catalog
deckhand/docs/deckhand/api-catalog.json (already public-safe: live_public +
roadmap rows, private/internal reduced to private_internal_count). When that
artifact is absent it derives the same view from domain-workflows.yaml: each
workflow row becomes a path record with ref, route triple
(scope / channel_domain / subdomains), residency, and a derived status
(live_public | live_private | internal | roadmap); bound channel domains with
no workflow row are emitted as roadmap:<domain> rows. Force one source with
--source canonical or --source derive. The emitted JSON reports which source
was used.
Step 2 — Diff vs the saved snapshot → "new paths this week"
uv run --no-project --with pyyaml python catalog_delta.py
The JSON delta reports new_paths, new_live_public, new_roadmap, removed_paths,
and status_changed (e.g. a roadmap row that became live_public). If new_live_public
is empty, there is no public copy to draft this week — note it and stop before Step 3.
Step 3 — Draft surface updates (per new path)
For each path in new_live_public, draft (do not commit yet):
- (a) teamresumes — add a "recent work" bullet for the new capability and bump the
LinkedIn Featured / About capability counts. Tie the bullet to the public report
URL (
report_url_hint). Cross-linkteamresumes#19. - (b) aceengineer-website — add a row to
content/api-catalog.htmlfor the new path (ref, domain/subdomain, one-line description, public report link). - (c) repo READMEs — update catalog-link counts in the relevant repo READMEs (e.g. "N live Open Deck workflows") so the numbers match the catalog.
For paths in new_roadmap: list them as roadmap/"coming" only — do not add capability
claims, resume bullets, or website catalog rows that imply they are live.
Use only language permitted by the locked messaging file (scope guardrails above).
Step 4 — Legal/PII gate on proposed public copy (blocking)
bash scripts/legal/legal-sanity-scan.sh --diff-only
Run against the staged/proposed public copy in each repo. Block on failure — do not open PRs with copy that trips the legal/PII gate. Fix or drop the offending line first.
Step 5 — Open one HITL draft PR per repo (never push direct, never merge)
For each affected repo (teamresumes, aceengineer-website, and any repo whose README counts changed), on a feature branch:
gh pr create --draft --repo vamseeachanta/<repo> \
--title "presence-sync: reflect new Deckhand API path(s) <refs>" \
--body "<delta summary + report links + 'draft, HITL — do not merge without owner review'>"
- Draft only. Never
--fillontomain, never push to a default branch, never merge. - Each PR body links the new path(s), the public report URL(s), and states the no-publish guarantee.
Only after every PR is opened, refresh the snapshot so these paths are not re-surfaced next week:
uv run --no-project --with pyyaml python catalog_delta.py --update-snapshot
If a run aborts before PRs open, leave the snapshot untouched — the next run re-surfaces
the same paths. (Snapshot lifecycle: state/README.md.)
Cadence & install
Declared weekly in config/scheduled-tasks/schedule-tasks.yaml as
deckhand-api-presence-sync (Sunday, dev-primary role). The skill does not
self-schedule — an operator installs the cron line:
# Canonical, safe installer (idempotent; skips lines already present):
bash scripts/cron/setup-cron.sh
crontab -l | grep deckhand-api-presence-sync
Note:
setup-cron.sh --replaceis disabled (#2969 — it would delete uncataloged live cron lines such as deckhand Telegram automation). The historical "weekly refresh documents its own--replace" pattern (e.g.ai/provider-utilization-scorecard) is superseded by the safe transactional path:uv run --script scripts/cron/cron-audit.py # audit live crontab first uv run --script scripts/cron/cron_apply.py # dry-run uv run --script scripts/cron/cron_apply.py --apply # commit: backup + CAS + rollback
Validate the declaration parses (no cron side effects):
uv run --no-project --with pyyaml python scripts/cron/validate-schedule.py
Cross-links: aceengineer-strategy#94 (locked messaging), teamresumes#19 (resume/
LinkedIn surface), deckhand canonical catalog deckhand/docs/deckhand/api-catalog.json
(deckhand#501, single source of truth) with derive-from-domain-workflows.yaml fallback.
Pitfalls
- Claiming
live_private,internal, orroadmappaths as public capability. Onlylive_publicis claimable. - Opening a non-draft PR, pushing to
main, or merging — all forbidden; HITL only. - Updating the snapshot before PRs are opened (drops paths from "new this week").
- Drafting copy outside the locked messaging file's approved claims.
- Skipping the legal/PII scan, or running it after PRs are already open.