docs(ops): redline evidence batch without capability release
Record SWBOOT L1–L4 (no real repo write), FAV ObserveShadow gates and observation-window prerequisites, D7 Track E ID-only checklist, and stronger PI narrative fallback negatives while keeping all redline flags off.
This commit is contained in:
@@ -123,16 +123,22 @@ func TestResolveChangeReport_FlagOnMalformedFullFallback(t *testing.T) {
|
||||
t.Cleanup(docrevision.ResetPIChangeReportNarrativeForTest)
|
||||
|
||||
fromSHA, toSHA, ruleRisk, impacts, diff := sampleDiff(t)
|
||||
digest := docrevision.NarrativeInputDigest(fromSHA, toSHA, ruleRisk, impacts, diff.Hunks)
|
||||
cases := []struct {
|
||||
name string
|
||||
raw string
|
||||
}{
|
||||
{"bad json", `{not-json`},
|
||||
{"bad schema version", `{"schema_version":99,"schema_kind":"change_report_narrative_v1","input_digest":"x","summary":["a"]}`},
|
||||
{"wrong schema kind", `{"schema_version":1,"schema_kind":"other_v1","input_digest":"` + digest + `","from_sha":"` + fromSHA + `","to_sha":"` + toSHA + `","summary":["PI only"]}`},
|
||||
{"digest mismatch", mustNarrativeJSON(t, fromSHA, toSHA, "deadbeef", []string{"ok"})},
|
||||
{"from_sha mismatch", mustNarrativeJSONWithSHAs(t, "wrong-from", toSHA, digest, []string{"PI only"})},
|
||||
{"to_sha mismatch", mustNarrativeJSONWithSHAs(t, fromSHA, "wrong-to", digest, []string{"PI only"})},
|
||||
{"timeout envelope", `{"result_v1":{"outcome":"error","error_code":"TIMEOUT"},"narrative":{"schema_version":1,"schema_kind":"change_report_narrative_v1"}}`},
|
||||
{"top-level error_code", `{"schema_version":1,"schema_kind":"change_report_narrative_v1","input_digest":"` + digest + `","from_sha":"` + fromSHA + `","to_sha":"` + toSHA + `","error_code":"RUNNER_FAILED","summary":["PI only"]}`},
|
||||
{"partial flag", `{"schema_version":1,"schema_kind":"change_report_narrative_v1","input_digest":"x","partial":true,"summary":["a"]}`},
|
||||
{"empty summary", mustNarrativeJSON(t, fromSHA, toSHA, docrevision.NarrativeInputDigest(fromSHA, toSHA, ruleRisk, impacts, diff.Hunks), nil)},
|
||||
{"empty summary", mustNarrativeJSON(t, fromSHA, toSHA, digest, nil)},
|
||||
{"empty raw", ""},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -154,11 +160,19 @@ func TestResolveChangeReport_FlagOnMalformedFullFallback(t *testing.T) {
|
||||
t.Fatalf("mixed narrative field leaked: %q", s)
|
||||
}
|
||||
}
|
||||
if rep.DeterministicFacts["narrative_applied"] == true {
|
||||
t.Fatal("fallback must not claim narrative_applied")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustNarrativeJSON(t *testing.T, fromSHA, toSHA, digest string, summary []string) string {
|
||||
t.Helper()
|
||||
return mustNarrativeJSONWithSHAs(t, fromSHA, toSHA, digest, summary)
|
||||
}
|
||||
|
||||
func mustNarrativeJSONWithSHAs(t *testing.T, fromSHA, toSHA, digest string, summary []string) string {
|
||||
t.Helper()
|
||||
raw, err := json.Marshal(map[string]any{
|
||||
"schema_version": 1,
|
||||
@@ -174,6 +188,43 @@ func mustNarrativeJSON(t *testing.T, fromSHA, toSHA, digest string, summary []st
|
||||
return string(raw)
|
||||
}
|
||||
|
||||
// TestResolveChangeReport_AuthorizedFlipPathKeepsFlagOffDefault documents the
|
||||
// pre-authorization contract: default remains off; when a future owner flips the
|
||||
// flag for a controlled window, malformed PI output still full-falls-back.
|
||||
func TestResolveChangeReport_AuthorizedFlipPathKeepsFlagOffDefault(t *testing.T) {
|
||||
docrevision.ResetPIChangeReportNarrativeForTest()
|
||||
t.Cleanup(docrevision.ResetPIChangeReportNarrativeForTest)
|
||||
if docrevision.PIChangeReportNarrativeEnabled() {
|
||||
t.Fatal("PI_CHANGE_REPORT_NARRATIVE must remain off until separately authorized")
|
||||
}
|
||||
|
||||
fromSHA, toSHA, ruleRisk, impacts, diff := sampleDiff(t)
|
||||
digest := docrevision.NarrativeInputDigest(fromSHA, toSHA, ruleRisk, impacts, diff.Hunks)
|
||||
piRaw := mustNarrativeJSON(t, fromSHA, toSHA, digest, []string{"should stay ignored while off"})
|
||||
|
||||
offRep, err := docrevision.ResolveChangeReport(piRaw, fromSHA, toSHA, ruleRisk, impacts, diff)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if offRep.AnalysisStatus != docrevision.AnalysisFallback {
|
||||
t.Fatalf("default-off must ignore PI narrative, got %s", offRep.AnalysisStatus)
|
||||
}
|
||||
|
||||
docrevision.SetPIChangeReportNarrativeForTest(true)
|
||||
onBad, err := docrevision.ResolveChangeReport(`{"schema_version":1,"schema_kind":"change_report_narrative_v1"}`, fromSHA, toSHA, ruleRisk, impacts, diff)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if onBad.AnalysisStatus != docrevision.AnalysisFallback {
|
||||
t.Fatalf("authorized-on malformed must still fallback, got %s", onBad.AnalysisStatus)
|
||||
}
|
||||
|
||||
docrevision.SetPIChangeReportNarrativeForTest(false)
|
||||
if docrevision.PIChangeReportNarrativeEnabled() {
|
||||
t.Fatal("test toggle must restore off before exit")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateAgentCandidate_FlagOffIgnoresNarrativeEnrichment(t *testing.T) {
|
||||
docrevision.SetPIChangeReportNarrativeForTest(false)
|
||||
t.Cleanup(docrevision.ResetPIChangeReportNarrativeForTest)
|
||||
@@ -289,6 +340,32 @@ func TestCreateAgentCandidate_FlagOnFetcherErrorFallsBack(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateAgentCandidate_FlagOnEmptyFetcherBodyFallsBack(t *testing.T) {
|
||||
docrevision.SetPIChangeReportNarrativeForTest(true)
|
||||
t.Cleanup(docrevision.ResetPIChangeReportNarrativeForTest)
|
||||
|
||||
svc := docrevision.NewService(nil)
|
||||
svc.NarrativeFetcher = func(_ context.Context, _ docrevision.NarrativeFetchSpec) (string, error) {
|
||||
return " ", nil
|
||||
}
|
||||
ctx := context.Background()
|
||||
st, err := svc.OpenTemplateVersion(ctx, "doc_flag_on_empty", "# base\n\nbody\n", docrevision.ActorSnapshot{DisplayName: "t"}, 1, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cand, rep, err := svc.CreateAgentCandidate(ctx, docrevision.AgentCandidateRequest{
|
||||
DocID: "doc_flag_on_empty", RunID: "r-empty", InputSnapshotID: st.HeadSnapshotID,
|
||||
OutputMarkdown: "# base\n\nbody changed\n",
|
||||
ActorKind: docrevision.ActorAgent,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("empty fetcher body must full-fallback without error, got %v", err)
|
||||
}
|
||||
if cand == nil || rep == nil || rep.AnalysisStatus != docrevision.AnalysisFallback {
|
||||
t.Fatalf("want fallback candidate, got cand=%v rep=%+v", cand, rep)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNarrativeModelInput_IncludesClippedChangeText(t *testing.T) {
|
||||
long := strings.Repeat("甲", 280)
|
||||
spec := docrevision.NarrativeFetchSpec{
|
||||
|
||||
Reference in New Issue
Block a user