feat(intent-plan): independent PU8 U9–U12 flags default off
Dry-run/fail-closed adapters; does not raise plan tier. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
# PU8 U9–U12 独立 flag 测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
覆盖 no-go 全量 backlog 实施。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
见计划对应章节。
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
Go unit / flag default off。
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
默认 off;开启路径 fail-closed 或 shadow。
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
- Verdict: PASS(单元)
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
见各 worktree `go test` 输出。
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
默认 flag off;不升 MULTI_INTENT_PLAN_TIER。
|
||||
@@ -0,0 +1,85 @@
|
||||
package intentflow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Expansion adapters for PU8. All gated by independent flags (default OFF).
|
||||
|
||||
// SegmentProposal is a fail-closed LLM segment proposal when U9 is on.
|
||||
type SegmentProposal struct {
|
||||
SchemaVersion string `json:"schema_version"`
|
||||
Spans []string `json:"spans"`
|
||||
Digest string `json:"digest"`
|
||||
}
|
||||
|
||||
// ProposeSegments returns ErrExpansionDisabled when flag off; when on, rejects
|
||||
// empty/malformed input fail-closed (no silent legacy bypass).
|
||||
func ProposeSegments(ctx context.Context, text string) (*SegmentProposal, error) {
|
||||
_ = ctx
|
||||
if !CurrentFeatureFlags().U9Segment {
|
||||
return nil, ErrExpansionDisabled
|
||||
}
|
||||
if len(text) == 0 {
|
||||
return nil, fmt.Errorf("u9 segment: empty input (fail closed)")
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("u9 segment: timeout/cancel (fail closed): %w", ctx.Err())
|
||||
default:
|
||||
}
|
||||
// Deterministic stub proposal (no LLM) for gate wiring; real model behind same schema.
|
||||
return &SegmentProposal{
|
||||
SchemaVersion: "u9-segment-v1",
|
||||
Spans: []string{text},
|
||||
Digest: fmt.Sprintf("sha-stub-%d", len(text)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MutateDryRun validates mutate adapters when U10 on; never applies side effects here.
|
||||
func MutateDryRun(ctx context.Context, action string, expectedRev int64) error {
|
||||
_ = ctx
|
||||
if !CurrentFeatureFlags().U10Mutate {
|
||||
return ErrExpansionDisabled
|
||||
}
|
||||
if action == "" || expectedRev <= 0 {
|
||||
return fmt.Errorf("u10 mutate: missing action or expected revision (fail closed)")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DocGovDryRun validates docgov action when U11 on.
|
||||
func DocGovDryRun(ctx context.Context, action string, expectedDocVersion int64) error {
|
||||
_ = ctx
|
||||
if !CurrentFeatureFlags().U11DocGov {
|
||||
return ErrExpansionDisabled
|
||||
}
|
||||
if action == "" || expectedDocVersion <= 0 {
|
||||
return fmt.Errorf("u11 docgov: missing action or document version (fail closed)")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunControlDryRun validates workflow/run-control when U12 on.
|
||||
func RunControlDryRun(ctx context.Context, kind string) error {
|
||||
_ = ctx
|
||||
if !CurrentFeatureFlags().U12RunControl {
|
||||
return ErrExpansionDisabled
|
||||
}
|
||||
switch kind {
|
||||
case "workflow_switch", "run_resume", "run_restart", "run_cancel":
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("u12 run-control: unknown kind %q (fail closed)", kind)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrExpansionDisabled means the independent PU8 flag is off (legacy path).
|
||||
var ErrExpansionDisabled = fmt.Errorf("intentflow expansion disabled")
|
||||
|
||||
// WithTimeout is a small helper for U9 fail-closed timeouts in tests.
|
||||
func WithTimeout(parent context.Context, d time.Duration) (context.Context, context.CancelFunc) {
|
||||
return context.WithTimeout(parent, d)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package intentflow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPU8FlagsDefaultOff(t *testing.T) {
|
||||
t.Setenv("MULTI_INTENT_U9_SEGMENT", "")
|
||||
t.Setenv("MULTI_INTENT_U10_MUTATE", "")
|
||||
t.Setenv("MULTI_INTENT_U11_DOCGOV", "")
|
||||
t.Setenv("MULTI_INTENT_U12_RUN_CONTROL", "")
|
||||
t.Setenv("MULTI_INTENT_PLAN_TIER", "")
|
||||
ResetFeatureFlagsForTest()
|
||||
f := CurrentFeatureFlags()
|
||||
if f.U9Segment || f.U10Mutate || f.U11DocGov || f.U12RunControl {
|
||||
t.Fatalf("PU8 flags must default off: %+v", f)
|
||||
}
|
||||
if f.PlanTier != TierLegacy {
|
||||
t.Fatalf("tier=%s want legacy", f.PlanTier)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPU8ExpansionDisabledWhenOff(t *testing.T) {
|
||||
ResetFeatureFlagsForTest()
|
||||
SetFeatureFlagsForTest(FeatureFlags{PlanTier: TierLegacy})
|
||||
if _, err := ProposeSegments(context.Background(), "x"); !errors.Is(err, ErrExpansionDisabled) {
|
||||
t.Fatalf("u9: %v", err)
|
||||
}
|
||||
if err := MutateDryRun(context.Background(), "edit", 1); !errors.Is(err, ErrExpansionDisabled) {
|
||||
t.Fatalf("u10: %v", err)
|
||||
}
|
||||
if err := DocGovDryRun(context.Background(), "claim", 1); !errors.Is(err, ErrExpansionDisabled) {
|
||||
t.Fatalf("u11: %v", err)
|
||||
}
|
||||
if err := RunControlDryRun(context.Background(), "run_cancel"); !errors.Is(err, ErrExpansionDisabled) {
|
||||
t.Fatalf("u12: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPU8ExpansionEnablePaths(t *testing.T) {
|
||||
SetFeatureFlagsForTest(FeatureFlags{
|
||||
PlanTier: TierLegacy, U9Segment: true, U10Mutate: true, U11DocGov: true, U12RunControl: true,
|
||||
})
|
||||
defer ResetFeatureFlagsForTest()
|
||||
p, err := ProposeSegments(context.Background(), "hello")
|
||||
if err != nil || p == nil || p.SchemaVersion != "u9-segment-v1" {
|
||||
t.Fatalf("u9 on: %v %+v", err, p)
|
||||
}
|
||||
if _, err := ProposeSegments(context.Background(), ""); err == nil {
|
||||
t.Fatal("u9 empty must fail closed")
|
||||
}
|
||||
if err := MutateDryRun(context.Background(), "edit", 2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := DocGovDryRun(context.Background(), "submit", 3); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := RunControlDryRun(context.Background(), "run_resume"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,11 @@ const (
|
||||
|
||||
type FeatureFlags struct {
|
||||
PlanTier PlanTier
|
||||
// Independent PU8 expansion gates. Default OFF; do not couple to PlanTier.
|
||||
U9Segment bool // MULTI_INTENT_U9_SEGMENT — LLM segment proposal
|
||||
U10Mutate bool // MULTI_INTENT_U10_MUTATE — low/medium mutate adapters
|
||||
U11DocGov bool // MULTI_INTENT_U11_DOCGOV — docgov action adapters
|
||||
U12RunControl bool // MULTI_INTENT_U12_RUN_CONTROL — workflow/run-control adapters
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -28,7 +33,21 @@ var (
|
||||
)
|
||||
|
||||
func defaultFeatureFlags() FeatureFlags {
|
||||
return FeatureFlags{PlanTier: parsePlanTier(os.Getenv("MULTI_INTENT_PLAN_TIER"))}
|
||||
return FeatureFlags{
|
||||
PlanTier: parsePlanTier(os.Getenv("MULTI_INTENT_PLAN_TIER")),
|
||||
U9Segment: envBool("MULTI_INTENT_U9_SEGMENT", false),
|
||||
U10Mutate: envBool("MULTI_INTENT_U10_MUTATE", false),
|
||||
U11DocGov: envBool("MULTI_INTENT_U11_DOCGOV", false),
|
||||
U12RunControl: envBool("MULTI_INTENT_U12_RUN_CONTROL", false),
|
||||
}
|
||||
}
|
||||
|
||||
func envBool(key string, def bool) bool {
|
||||
v := strings.TrimSpace(os.Getenv(key))
|
||||
if v == "" {
|
||||
return def
|
||||
}
|
||||
return v == "1" || strings.EqualFold(v, "true") || strings.EqualFold(v, "yes")
|
||||
}
|
||||
|
||||
func parsePlanTier(raw string) PlanTier {
|
||||
|
||||
@@ -27,6 +27,18 @@ func TestPlanTierIndependentOfLegacyMultiIntentFlag(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanTierIndependentOfExpansionFlags(t *testing.T) {
|
||||
t.Setenv("MULTI_INTENT_PLAN_TIER", "")
|
||||
t.Setenv("MULTI_INTENT_U9_SEGMENT", "true")
|
||||
t.Setenv("MULTI_INTENT_U10_MUTATE", "true")
|
||||
t.Setenv("MULTI_INTENT_U11_DOCGOV", "true")
|
||||
t.Setenv("MULTI_INTENT_U12_RUN_CONTROL", "true")
|
||||
ResetFeatureFlagsForTest()
|
||||
if CurrentFeatureFlags().PlanTier != TierLegacy {
|
||||
t.Fatal("U9–U12 flags must not raise MULTI_INTENT_PLAN_TIER")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanTierEnv(t *testing.T) {
|
||||
if parsePlanTier("shadow") != TierShadow {
|
||||
t.Fatal("shadow")
|
||||
|
||||
Reference in New Issue
Block a user