Commit Graph

1 Commits

Author SHA1 Message Date
Garry Tan 2b54677398 feat: bin/gstack-developer-profile — unified profile with migration
bin/gstack-developer-profile supersedes bin/gstack-builder-profile. The old
binary becomes a one-line legacy shim delegating to --read for /office-hours
backward compat.

Subcommands:
  --read              legacy KEY:VALUE output (tier, session_count, etc)
  --migrate           folds ~/.gstack/builder-profile.jsonl into
                      ~/.gstack/developer-profile.json. Atomic (temp + rename),
                      idempotent (no-op when target exists or source absent),
                      archives source as .migrated-YYYY-MM-DD-HHMMSS
  --derive            recomputes inferred dimensions from question-log.jsonl
                      using the signal map in scripts/psychographic-signals.ts
  --profile           full profile JSON
  --gap               declared vs inferred diff JSON
  --trace <dim>       event-level trace of what contributed to a dimension
  --check-mismatch    flags dimensions where declared and inferred disagree by
                      > 0.3 (requires >= 10 events first)
  --vibe              archetype name + description from scripts/archetypes.ts
  --narrative         (v2 stub)

Auto-migration on first read: if legacy file exists and new file doesn't,
migrate before reading. Creates a neutral (all-0.5) stub if nothing exists.

Unified schema (see docs/designs/PLAN_TUNING_V0.md §Architecture):
  {identity, declared, inferred: {values, sample_size, diversity},
   gap, overrides, sessions, signals_accumulated, schema_version}

25 new tests across subcommand behaviors:
- --read defaults + stub creation
- --migrate: 3 sessions preserved with signal tallies, idempotency, archival
- Tier calculation: welcome_back / regular / inner_circle boundaries
- --derive: neutral-when-empty, upward nudge on 'expand', downward on 'reduce',
  recomputable (same input → same output), ad-hoc unregistered ids ignored
- --trace: contributing events, empty for untouched dims, error without arg
- --gap: empty when no declared, correctly computed otherwise
- --vibe: returns archetype name + description
- --check-mismatch: threshold behavior, 10+ sample requirement
- Unknown subcommand errors

25 pass, 0 fail, 60 expect() calls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 06:20:25 +08:00