feat: P1 profile/portrait API and freeze local-dev environment

Add host-first environment contracts (Local vs CI vs Prod), deps-only
compose, and the Profile → Portrait → deep-access mock payment slice
with device identity and auto-migrate on API startup.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-02 16:24:57 +08:00
co-authored by Cursor
parent dd94e57277
commit 0f320e040b
49 changed files with 1907 additions and 191 deletions
+25
View File
@@ -0,0 +1,25 @@
package portrait
import (
"strings"
"testing"
"time"
)
func TestBuildDeterministic(t *testing.T) {
birth := time.Date(1990, 1, 15, 0, 0, 0, 0, time.UTC)
a := Build(birth, "小愈")
b := Build(birth, "小愈")
if a.Summary["headline"] != b.Summary["headline"] {
t.Fatalf("expected deterministic headline")
}
if a.Summary["one_liner"] == nil || a.Detail["growth_direction"] == nil {
t.Fatalf("missing summary/detail fields")
}
for _, kw := range []string{"运势", "吉凶", "算命"} {
s := a.Summary["one_liner"].(string) + a.Detail["behavior_pattern"].(string)
if strings.Contains(s, kw) {
t.Fatalf("forbidden word %q in portrait copy", kw)
}
}
}