Skip to content

Auto-publish journey.yaml to Skene Cloud on first analysis - #85

Merged
bmichele merged 5 commits into
mainfrom
feat/auto-publish-journey
Jun 30, 2026
Merged

Auto-publish journey.yaml to Skene Cloud on first analysis#85
bmichele merged 5 commits into
mainfrom
feat/auto-publish-journey

Conversation

@bmichele

@bmichele bmichele commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

First-time Skene TUI users who link a workspace and run journey analysis land on an empty Customer Journey canvas after following the visualization's link to skene.ai (they haven't pushed journey.yaml yet). This change auto-publishes the generated journey.yaml right after analysis, so the cloud canvas is populated by the time they click through.

It only fires when both hold:

  1. running with the skene provider (TUI linked to a workspace), and
  2. no journey.yaml exists upstream yet.

The gate is split between the TUI (knows it's linked) and the CLI (does the check + push):

  • TUI (tui/internal/services/growth/engine.go): extracted analyse-journey arg building into journeyArgs(), which appends --auto-publish only when linked (skene provider + upstream URL + key). The flag's presence marks a TUI-initiated, linked run.
  • CLI (src/skene/cli/commands/analyse_journey.py): hidden --auto-publish flag + _maybe_auto_publish, gated on skene provider + linked workspace + definitive remote absence. Already-present or indeterminate results skip silently; a publish failure never fails analysis.
  • Presence check (src/skene/growth_loops/upstream.py): journey_exists_upstream() calls GET /api/v1/journey/status; returns None on any indeterminate result (non-200, network error, endpoint not deployed) so callers can skip safely.
  • Refactor (src/skene/growth_loops/push.py): extracted publish_bundle() so the existing push command and the new auto-publish path build an identical manifest (no behavior change to skene push).

Design decisions

  • Indeterminate check -> skip silently. Only a definitive "absent" triggers a push; we never push when the check can't be completed.
  • TUI-initiated only. Direct skene analyse-journey CLI runs never auto-publish, even when linked — it's gated on the flag the TUI sets.

Dependency

Needs the dashboard endpoint GET /api/v1/journey/status (SkeneTechnologies/skene-dashboard#200). Until that's deployed the presence check is indeterminate and auto-publish is a no-op, so this can merge/ship independently.

Test Plan

Automated (run locally):

  • uv run pytest (395 passed, incl. the new test_upstream.py + test_analyse_journey_auto_publish.py)
  • uv run ruff check clean.
  • cd tui && go test ./internal/services/growth/

What the unit tests cover:

  • journey_exists_upstream — 200 exists true/false; non-200 and exceptions → None (indeterminate).
  • _maybe_auto_publish — full gating matrix: disabled, non-skene provider, missing upstream/token, already-present,
    indeterminate, absent→publish; plus publish-failure-never-raises.
  • journeyArgs — appends --auto-publish only when provider=skene + upstream + key; omitted otherwise.

Manual end-to-end

  • Deploy GET /api/v1/journey/status; curl -H "X-API-Key: " …/api/v1/journey/status → { "data": { "exists": false } } on a fresh workspace.
  • Link the TUI (skene provider) and run journey analysis → expect a "Published journey to Skene Cloud" line; re-check returns exists: true and the skene.ai canvas renders.
  • Re-run on the same workspace → check returns true → no re-push.
  • Non-skene provider → no --auto-publish, no upstream call.
  • Endpoint unreachable → publish skipped silently, analysis still succeeds.

Checklist

  • PR is focused on a single change (no unrelated refactoring or cleanup)
  • Tests added or updated for any behavioral change
  • Documentation updated (if behavior, flags, config, or APIs changed)
  • Cursor plugin updated (if commands, skills, or core CLI behavior changed) n/a
  • Linting and tests pass locally
  • No merge conflicts

bmichele and others added 4 commits June 9, 2026 14:51
When analyse-journey runs with --auto-publish (set by the TUI when linked
to a skene workspace), publish the freshly written journey.yaml to Skene
Cloud iff no journey.yaml exists upstream yet. This stops first-time users
from landing on an empty cloud canvas after following the visualization
link to skene.ai.

- upstream: add journey_exists_upstream() presence check (GET /journey/status);
  returns None on any indeterminate result so callers can skip safely.
- push: extract publish_bundle() so the push command and the new auto-publish
  path build an identical manifest; refactor the push command onto it.
- analyse-journey: add hidden --auto-publish flag + _maybe_auto_publish,
  gated on skene provider + linked workspace + definitive remote absence.
  Indeterminate/already-present results skip silently; failures never raise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- test_upstream: cover journey_exists_upstream (exists true/false, non-200
  and exceptions are indeterminate/None, missing field is falsey).
- test_analyse_journey_auto_publish: cover the _maybe_auto_publish gating
  matrix (disabled, non-skene provider, missing upstream/token, already
  present, indeterminate, absent-so-publish) and that a publish failure
  does not raise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract analyse-journey arg building into journeyArgs() and append
--auto-publish when the run is linked to a Skene workspace (skene provider
+ upstream URL + key). The flag marks this as a TUI-initiated, linked run;
the CLI gates the actual push further on the journey being absent upstream.
Add tests covering the linked case and the omit cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a stopgap note that first journey analysis from the TUI auto-publishes
journey.yaml to Skene Cloud when none exists upstream:
- push.md: new "Automatic first publish (journey analysis)" section.
- quickstart.md: note in the upstream/deploy step linking to it.

Fuller docs (analyse-journey command reference + a journey guide) tracked
in #86.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bmichele
bmichele marked this pull request as ready for review June 12, 2026 12:18
@bmichele
bmichele requested a review from eretjohannes as a code owner June 12, 2026 12:18

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32c5d9aa36

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

return

try:
result = publish_bundle(project_root, config, upstream=upstream, token=token)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Publish the generated journey file, not config output dir

When TUI users have a custom output_dir, runUVX exports that value as SKENE_OUTPUT_DIR, but journeyArgs() still writes the generated journey to e.bundleOutputDir()/journey.yaml. This call then lets publish_bundle() collect files from config.output_dir, so the auto-publish can upload the wrong directory (or an empty payload) and report success while the freshly generated journey.yaml never reaches Skene Cloud. Pass the actual journey output path/directory through, or make the TUI and publisher use the same directory.

Useful? React with 👍 / 👎.

@bmichele
bmichele merged commit 2fe11a6 into main Jun 30, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant