From 1791d954acb8a08d6ee9e039f836ce691cd8bad8 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 22 Jul 2026 05:27:23 +0300 Subject: [PATCH 1/3] Add General responses document --- General responses.docx | Bin 0 -> 10837 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 General responses.docx diff --git a/General responses.docx b/General responses.docx new file mode 100644 index 0000000000000000000000000000000000000000..183bd80de9f3906f0c636b5bf9754e6bee7a9503 GIT binary patch literal 10837 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 Date: Wed, 22 Jul 2026 05:32:46 +0300 Subject: [PATCH 2/3] Require complete public Dialogue Lab replies --- .agents/skills/dialogue-lab-followup/SKILL.md | 5 +- AGENTS.history.json | 51 +++++++++++++++++++ AGENTS.md | 2 + 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/.agents/skills/dialogue-lab-followup/SKILL.md b/.agents/skills/dialogue-lab-followup/SKILL.md index aca248e..25c2e62 100644 --- a/.agents/skills/dialogue-lab-followup/SKILL.md +++ b/.agents/skills/dialogue-lab-followup/SKILL.md @@ -17,8 +17,9 @@ description: Process supplied public content in an existing Israel Facebook Dial 3. When sibling branches already stored in one Case must be tracked independently, prepare one `case-split-branch` command with an outside-Git backup and exact new title/topic. After explicit approval, run `dialogue-lab check`; if it passes, run the split and use its committed Case/Turn mapping. 4. Assign or reuse only `P1`, `P2`, ... or `USER`. Resolve the direct parent from visible context or user confirmation and retain Parent Confidence; ask only when ambiguity changes the reply. 5. Build one incoming Turn payload. A supplied `reply_comment_id` is its strongest duplicate identity; without one, the transaction uses Case ID + Parent Turn ID (including a null root) + Direction + Exact Text. The transaction returns the existing Turn on a duplicate or allocates a Turn ID, validates the complete parent graph, appends, commits, and reads back. -6. Read repository strategy and evidence Markdown only as needed, verify material claims, and answer the operative claim without treating private planning as public context. -7. Return the standard output. After explicit approval, run `dialogue-lab check`; if it passes, run exactly one `dialogue-lab case-followup --case-id --approved` transaction and report its compact receipt. +6. Read repository strategy and evidence Markdown only as needed and verify material claims. +7. Base the public reply's substantive response only on the supplied public post, target comment chain, and verified relevant facts; never treat private planning, predicted replies, or unrelated conversation context as public content. +8. Return the standard output. After explicit approval, run `dialogue-lab check`; if it passes, run exactly one `dialogue-lab case-followup --case-id --approved` transaction and report its compact receipt. ## Output diff --git a/AGENTS.history.json b/AGENTS.history.json index 4fd6d60..db7db77 100644 --- a/AGENTS.history.json +++ b/AGENTS.history.json @@ -83,6 +83,57 @@ "original_sha256": "a13eb777209419f0fd81ee29bde8c2c3091041ec8e737d3e1970529f7c18c0ca", "rules_sha256": "0c66144eed98d6320a6d0ccbad65e84257a28f7856e28e3bc0e50b4b763f6497", "global_rules_sha256": "8ef798b3330613534c7b03ca75aeb7fb9413a4c6774e2f7388d258a09140ed42" + }, + { + "id": "2026-07-22-complete-public-replies", + "date": "2026-07-22", + "rules": [ + "DL-REPLY-01" + ], + "related_global_rules": [ + "OUT-03" + ], + "reason": "A recommended public reply was delivered as staged fragments and was later expanded using private planning instead of as one complete response to the supplied public exchange.", + "preserved": "Reply brevity, one-pivotal-point focus, verified external fact use, and the follow-up skill's public-context boundary remain unchanged.", + "introduced": "DL-REPLY-01 requires complete ready-to-post text for the supplied post and target comment chain unless the user requests partial or staged content.", + "validation": "Replayed the fragmentary-reply and private-context failures; the rule requires a complete public-exchange reply while retaining user-requested fragments and verified external facts.", + "global_rules_sha256": "8ef798b3330613534c7b03ca75aeb7fb9413a4c6774e2f7388d258a09140ed42", + "rules_sha256": "8cb6faeeee366a2b175440bc30f776821acb9739a06ed47765ab59d78e18dfea", + "source_history": "Targeted Git history was used because no prior local AGENTS.history.json existed." + }, + { + "id": "2026-07-22-unconditional-complete-public-replies", + "date": "2026-07-22", + "rules": [ + "DL-REPLY-01" + ], + "related_global_rules": [ + "OUT-03" + ], + "reason": "The user required every proposed public Dialogue Lab reply to be complete and ready to post, without a partial-or-staged exception.", + "preserved": "Self-contained ready-to-post output remains required; fact verification and public-context isolation remain separate in the follow-up skill.", + "introduced": "DL-REPLY-01 now unconditionally requires one complete, self-contained, ready-to-post response.", + "validation": "Replayed full and partial reply outputs; a complete ready-to-post response passes, while partial or staged output fails regardless of request wording.", + "global_rules_sha256": "8ef798b3330613534c7b03ca75aeb7fb9413a4c6774e2f7388d258a09140ed42", + "rules_sha256": "cbf29456442e949912c4af8e0419f2cb36cf3b8f10d2c5400486d848734dc4ba", + "source_history": "Prior structured local history and the related global OUT-03 history were consulted." + }, + { + "id": "2026-07-22-reapply-complete-public-replies-to-current-release", + "date": "2026-07-22", + "rules": [ + "DL-REPLY-01" + ], + "related_global_rules": [ + "OUT-03" + ], + "reason": "Apply the approved complete-public-reply rule and public-context boundary to release/local rebuilt from current main.", + "preserved": "All shipped Case and Turn identity rules, earlier history records, current global output brevity, fact verification, and unrelated Dialogue Lab behavior remain unchanged.", + "introduced": "The final DL-REPLY-01 wording and matching follow-up skill boundary coexist with the shipped identity model on release/local.", + "validation": "Current global OUT-03 and every existing local rule were re-read; concise output remains compatible with one complete ready-to-post public reply, and no prior history relation was rewritten.", + "global_rules_sha256": "b0df68cb05e31cf808cbcc932b71241c672471146720d99601de168c2e4ce5ce", + "rules_sha256": "9f6fd346849cf39880007660957e0a432944004f18c5bf5e80118eb5fbea824e", + "source_history": "The uncommitted full-reply-rule history, shipped local history, and current global OUT-03 history were consulted." } ] } diff --git a/AGENTS.md b/AGENTS.md index a901737..443177e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,6 +16,8 @@ - [HASBARA-IDENTITY-02] Deduplicate Turns by supplied `reply_comment_id`; when absent, use Case ID + Parent Turn ID (including null roots) + Direction + Exact Text; never use mutable latest-reply state as identity. - [HASBARA-OPEN-CASES-01] When presenting open Cases, use each Case's latest public Turn supplied exact URL; never substitute the Case root URL, and mark a missing link explicitly. - Invoke the matching Dialogue Lab skill for intake, follow-up, posting confirmation, closeout, or strategy review. +- [DL-REPLY-01] When proposing a public Dialogue Lab reply, provide one + complete, self-contained, ready-to-post response - Never edit, move, rename, replace, delete, import, or summarize `General responses` without the user's explicit instruction for that exact action. - Perform canonical writes only through explicit-approval `dialogue-lab` commands that use SQLite transactions and committed read-back verification. - After a failed canonical write, verify rollback and database integrity; block further writes while either remains unresolved. From 4aef26aebe7ee6a6a8e291dd0cae09a3b0dabf9e Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 22 Jul 2026 16:15:59 +0300 Subject: [PATCH 3/3] Add active rule relations and optimize open case reads --- AGENTS.history.json | 28 +++++++++++++++ AGENTS.md | 6 ++++ src/dialogue_lab/storage.py | 66 +++++++++++++++++++++--------------- tests/test_sqlite_storage.py | 14 +++++++- 4 files changed, 85 insertions(+), 29 deletions(-) diff --git a/AGENTS.history.json b/AGENTS.history.json index db7db77..4d2a605 100644 --- a/AGENTS.history.json +++ b/AGENTS.history.json @@ -134,6 +134,34 @@ "global_rules_sha256": "b0df68cb05e31cf808cbcc932b71241c672471146720d99601de168c2e4ce5ce", "rules_sha256": "9f6fd346849cf39880007660957e0a432944004f18c5bf5e80118eb5fbea824e", "source_history": "The uncommitted full-reply-rule history, shipped local history, and current global OUT-03 history were consulted." + }, + { + "id": "2026-07-22-active-rule-relation-metadata", + "date": "2026-07-22", + "rules": [ + "HASBARA-CHECK-01", + "HASBARA-IDENTITY-01", + "HASBARA-IDENTITY-02", + "HASBARA-OPEN-CASES-01", + "DL-REPLY-01" + ], + "relation_neighbors": [ + "HASBARA-CANONICAL-01", + "HASBARA-IDENTITY-01", + "HASBARA-IDENTITY-02", + "HASBARA-OPEN-CASES-01", + "OUT-03" + ], + "related_global_rules": [ + "OUT-03" + ], + "reason": "Make current rule interactions queryable instead of inferring them from historical entries.", + "preserved": "Every prior history entry remains unchanged, and HASBARA-CHECK-01 has no current relation to HASBARA-OPEN-CASES-01.", + "introduced": "Active requires and limits metadata for canonical state, Case and Turn identity, open-Case presentation, and complete public replies.", + "validation": "The rule-history helper resolves direct current neighbors across the local and global rule sources without unknown IDs.", + "global_rules_sha256": "b0df68cb05e31cf808cbcc932b71241c672471146720d99601de168c2e4ce5ce", + "original_sha256": "9f6fd346849cf39880007660957e0a432944004f18c5bf5e80118eb5fbea824e", + "rules_sha256": "ae6738bd2deca5db34ee3c1ec0832aec84c6d84d0c2c0bfb0080fb93fe830a68" } ] } diff --git a/AGENTS.md b/AGENTS.md index 443177e..eb44d8e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,13 +11,19 @@ ## HasbaraTops - [HASBARA-CHECK-01] Run `dialogue-lab check` before a canonical write, after a failed write or readiness check, or when database state is uncertain; ordinary read-only queries must reuse fresh sufficient evidence. + - requires: HASBARA-CANONICAL-01 - [HASBARA-CANONICAL-01] Treat repository Markdown as canonical governance, strategy, and evidence content and the configured SQLite database as canonical Case and Turn state; do not use MCP for Dialogue Lab work. - [HASBARA-IDENTITY-01] Use `config/storage.toml`; preserve the SQLite schema version; treat Case ID as definitive, allow multiple Cases per `Post ID + Root Comment ID`, and treat root lookup as candidate discovery only. + - requires: HASBARA-CANONICAL-01 - [HASBARA-IDENTITY-02] Deduplicate Turns by supplied `reply_comment_id`; when absent, use Case ID + Parent Turn ID (including null roots) + Direction + Exact Text; never use mutable latest-reply state as identity. + - requires: HASBARA-IDENTITY-01 + - limits: HASBARA-OPEN-CASES-01 - [HASBARA-OPEN-CASES-01] When presenting open Cases, use each Case's latest public Turn supplied exact URL; never substitute the Case root URL, and mark a missing link explicitly. + - requires: HASBARA-CANONICAL-01 - Invoke the matching Dialogue Lab skill for intake, follow-up, posting confirmation, closeout, or strategy review. - [DL-REPLY-01] When proposing a public Dialogue Lab reply, provide one complete, self-contained, ready-to-post response + - limits: OUT-03 - Never edit, move, rename, replace, delete, import, or summarize `General responses` without the user's explicit instruction for that exact action. - Perform canonical writes only through explicit-approval `dialogue-lab` commands that use SQLite transactions and committed read-back verification. - After a failed canonical write, verify rollback and database integrity; block further writes while either remains unresolved. diff --git a/src/dialogue_lab/storage.py b/src/dialogue_lab/storage.py index 2ff94fd..2383030 100644 --- a/src/dialogue_lab/storage.py +++ b/src/dialogue_lab/storage.py @@ -795,37 +795,47 @@ def find_turn_duplicate(self, turn: TurnRecord) -> TurnRecord | None: return _find_turn_duplicate(connection, turn) def list_open_summaries(self) -> list[dict[str, object]]: + closed_statuses = tuple(sorted(status.value for status in CLOSED_STATUSES)) + closed_placeholders = ", ".join("?" for _ in closed_statuses) with self._connect() as connection: rows = connection.execute( - "SELECT * FROM cases " - "ORDER BY CAST(substr(case_id, 6) AS INTEGER)" - ).fetchall() - output: list[dict[str, object]] = [] - for row in rows: - case = _case_from_row(row) - if case.status in CLOSED_STATUSES: - continue - public_turns = [ - turn - for turn in self._get_turns(connection, case.case_id) - if turn.state not in {TurnState.DRAFT, TurnState.REPLACED} - ] - latest = max( - public_turns, - key=lambda turn: (turn.observed_at, int(turn.turn_id[1:])), - default=None, - ) - permalink = latest.exact_url if latest is not None else None - output.append( - { - "case_id": case.case_id, - "status": case.status.value, - "last_turn_id": latest.turn_id if latest is not None else None, - "last_comment_permalink": permalink, - "permalink_status": "supplied" if permalink else "missing", - } + f"""WITH ranked_public_turns AS ( + SELECT case_id, turn_id, exact_url, + ROW_NUMBER() OVER ( + PARTITION BY case_id + ORDER BY observed_at DESC, + CAST(substr(turn_id, 2) AS INTEGER) DESC + ) AS turn_rank + FROM turns + WHERE state NOT IN (?, ?) ) - return output + SELECT cases.case_id, cases.status, + latest.turn_id AS last_turn_id, + latest.exact_url AS last_comment_permalink + FROM cases + LEFT JOIN ranked_public_turns AS latest + ON latest.case_id = cases.case_id + AND latest.turn_rank = 1 + WHERE cases.status NOT IN ({closed_placeholders}) + ORDER BY CAST(substr(cases.case_id, 6) AS INTEGER)""", + ( + TurnState.DRAFT.value, + TurnState.REPLACED.value, + *closed_statuses, + ), + ).fetchall() + return [ + { + "case_id": str(row["case_id"]), + "status": str(row["status"]), + "last_turn_id": row["last_turn_id"], + "last_comment_permalink": row["last_comment_permalink"], + "permalink_status": ( + "supplied" if row["last_comment_permalink"] else "missing" + ), + } + for row in rows + ] def strategy_dataset(self) -> Mapping[str, object]: with self._connect() as connection: diff --git a/tests/test_sqlite_storage.py b/tests/test_sqlite_storage.py index 6c49551..eddaec9 100644 --- a/tests/test_sqlite_storage.py +++ b/tests/test_sqlite_storage.py @@ -306,7 +306,19 @@ def test_open_case_returns_latest_turn_permalink_without_root_fallback( reply_comment_id="789", observed_at="2026-07-17 11:00", ) - store.create_case(case, [root, reply], approved=True) + later_draft = make_reply( + "T003", + "T002", + direction=TurnDirection.OUTGOING, + state=TurnState.DRAFT, + exact_url=( + "https://www.facebook.com/example/posts/123" + "?comment_id=456&reply_comment_id=999" + ), + reply_comment_id="999", + observed_at="2026-07-17 12:00", + ) + store.create_case(case, [root, reply, later_draft], approved=True) missing_case = make_case(case_id="Case-002") missing_turn = make_turn( case_id="Case-002",