P26-01-LEDGER: 原P26-01 全必要内容の台帳

This commit is contained in:
Agent Control Runner
2026-10-18 09:42:51 +09:00
parent f10907d8db
commit cec295f34b
5 changed files with 3216 additions and 800 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -12,13 +12,17 @@ build/owner-handoff/p26-repair3/ の ACTUAL_WHOLE_REVIEW.json、ACTUAL_OPUS_REPA
現在の実承認は a13f7c0b791dd385ff8113c3d321c0e3fe7d7c94 の docs/plans/original-completion-2026-10-02/execution/p04-01-owner-approval-20261018/D05_ACTUAL_HUMAN_APPROVAL.json、SHA256 cd365ded1b777a0327d090709f0a4161f5005562819183455d9f2e106fba3e96。チェッカーはこのgit objectのhashを照合し、4回答の原レコードを台帳に保存する。質問IDは call_5fa8987f83284eb58b685002499cb9df。破壊/完了、日付境界、停止理由、退出順序の承認であり、P04への製品採用・内容完成・P26受入ではない。D08/D09は未解決。
## 修復5: 証拠のAR別帰属
## 修復6: 直接読解マップによる証拠のAR別帰属
今回の変更前に build/owner-handoff/p26-support-attribution-repair/ACTUAL_OPUS_ASTRA_ATTRIBUTION_DIRECTION.json と ACTUAL_WHOLE_REVIEW_DA80360A.json を全文読了し、D05の上記4資料も再確認した。修復5は証拠帰属に限定する。
今回の変更前に build/owner-handoff/p26-direct-support-r06/ の ACTUAL_OPUS_DIRECT_SOURCE_MAP.json、ACTUAL_WHOLE_REVIEW_F10907D8.json、DIRECT_POLICY_AUTHORITY_SNAPSHOT.json を全フィールド・全ソース本文まで読了した。確定済みの直接読解マップを転記し、証拠帰属だけを修復する。モデル指定はgpt-6.1-solのまま。新しい意味判断・仕様・承認は加えない。
結合した引用文のキーワードからpartialを付ける処理を削除した。SUPPORT_POLICYは証拠種別→許容ARの閉じた対応表である。関係状態は21ルートと感情3軸/盾最大値の明示状態・保存だけ、覗きは記録係/観察/証拠収集に関する列挙ARの停止中コンテナだけ、夜間は2 ARの欲求入力だけ、赤字は終端計算ARだけを支援する。人物のidentity/技能や任意のrelationship/route_action全域へは拡張しない。視点・角度・介入そのものを支援する証拠とはしない。
SUPPORT_POLICYの4種をマップの許容リストに限定する。relationship-containerは21人物ルートARとAR.relationship.three_emotions / affection_shield_max、peeping-containerはAR.underground.observation / AR.observation.recorder、night-inputはAR.guest.need_sexual_night_peak、bankruptcy-bookkeepingはAR.progression.three_deficits_gameoverだけ。以前のキーワードpartial処理の廃止、voice修復、全先行修復は保持する。
各行のscoped_supportは対象AR・証拠種別・限定範囲・content_status=missingを明記する。unsupported_atomic_requirement_idsはその行で基盤支援がない残りのARを列挙する(用途行の既存placeholder/code-drawingは従来どおり別記)。L9は21ルートのコンテナだけpartialで、全エンド/図鑑/所要時間は未支援。L257とclause.productionは観察工程のコンテナだけpartialで、ボイス収録/実装を含む他ARは未支援。voice.all、endings全3行、encyclopedia.allはmissing、証拠なし。声に関するどのARも対応表に入れない。行数・AR対応・引用・制作数量は増減させない。
各行のscoped_supportは対象AR・証拠種別・限定範囲・content_status=missingを明記する。unsupported_atomic_requirement_idsはその行で基盤支援がない残りのARを列挙する(用途行の既存placeholder/code-drawingは従来どおり別記)。L9は21ルートのコンテナだけpartialで、全エンド/図鑑/所要時間は未支援。L21 / L156 / L221 / L222 / L257とclause.productionは支援が空になるためmissing、evidence=[]。L34は観察状態、L53は記録フィールド、L65は客欲求入力、L72は赤字終端計算だけpartialを保持する。voice.all、endings全3行、encyclopedia.allはmissing、証拠なし。声に関するどのARも対応表に入れない。行数・AR対応・引用・制作数量は増減させない。
独立したEXCLUDED_ATTRIBUTIONS表で、AR.ui.observation_camera_entry(カメラアイコン/専用画面遷移)、AR.ui.observation_capture(スクリーンショット)、AR.underground.blackmail(取引状態/収支)、AR.route_action.observation_progress(観察部屋のルート進行確認)、AR.schedule.B-14.3.observation(専用観察モード達成)、AR.events.ntr_night_peak(NTRイベント夜ピーク)を拒否する。関連コードは uncredited precursor, not required behaviour と理由文に記す。コードの不存在は主張せず、これらARに証拠pinを帰属させない。SUPPORT_POLICYへの再追加も、行のscoped_support主張も独立層で拒否する。6個の個別負例は双方を注入し、許容ARの正例と復旧後の正例を伴う。破損ポリシーで再生成した台帳も拒否する。
chapters.all / dialogue.allはstatus=undefinedを保持し、制作内容は欠損、undefinedは範囲・数量のみと理由文で明示する。owner精度の追加判断は引き続きdeferred。
verify_authorityはexpectedやcanonicalを呼ばず、提出された各claimのARと行の種類、固定出典・抜粋全文、支援/未支援ARの分割、状態と範囲文を検査する。有効なSHAでも無関係な証拠、無根拠なpartial、声への同一引用行の観察証拠の流用は拒否する。負例はmissingの音声/立ち絵/エンド/図鑑への証拠注入、混合行内の支援AR拡張、正しい夜間支援への無関係な証拠追加を含む。route、L65、L53の実際のpartialを正例にする。既存負例は維持し、AR削除負例だけ新しい分割フィールドも整合して削除する。
@@ -44,11 +48,11 @@ verify_authorityはexpectedやcanonicalを呼ばず、提出された各claimの
## 現物の部分支援と欠損
scripts/relationship/original_relationship_state.gd の明示値検証と relationship_service.gd の保存コンテナを直接参照する。route行と対応する原文行はpartialであり、content_status=missingを別記する。更新・攻撃・閾値・固有物語を実装済みとはしない。
scripts/relationship/original_relationship_state.gd:6、21–25、26でaffection/lust/netorareと有限値検証、shield_max==affection / 0<=shield_current<=shield_maxを引用する。relationship_service.gd:38–58はsubject_idキーの原本記録登録、315–355は別の汎用route_lock/route_id記録だけ。元ルートID・自然到達・内容はない。whole-file pinをこの抜粋へ狭める。21 route行はpartial、content_status=missingを保持し、更新・攻撃・閾値・固有物語を実装済みとはしない。
scripts/special/peeping_room_service.gd:127–162 と autoload/simulation_runtime.gd:10860–10880 を直接引用する。停止・対象参照・証拠キーの基盤はあるが、製品配置はBUILD_DEFINITION_PENDING_D04、記録はRECORDER_ELIGIBILITY_PENDING_D04_D08_P16で止まる。閉じた対応表にあるARのscoped_supportだけがこの基盤を指し、視界、専用画面、スクリーンショット、介入や制作イベントを証明しない。L13の自律観察/介入、L53の専用視点、L222の角度/介入にはこの証拠を帰属させない。
scripts/special/peeping_room_service.gd:127–138はstopped/link_state/targetと前提優先順、140–142は製品記録のRECORDER_ELIGIBILITY_PENDING_D04_D08_P16、155–164はfixture専用書込みのevidence_id/room_id/target_instance_id/source_event_key/minuteを引用する。autoload/simulation_runtime.gd:10863–10864は配置のBUILD_DEFINITION_PENDING_D04だけ。通常入口・記録係配置は欠損。視界、専用画面、スクリーンショット、ルート確認、取引、介入や制作イベントへ帰属させない。
scripts/guest/guest_service.gd:355–360 は夜間の欲求入力の切替のみ。L65のNTRイベント内容の制作証拠ではない。scripts/operations/operations_coordinator.gd:1183–1195 の赤字連続による終端計算は存在するが、完成シナリオ/画像/声ではない。L196の専用代物弁済イベントは現物制作証拠なしとしてmissing。数量/シーン列はundefinedのまま。
scripts/guest/guest_service.gd:355–359はadult intimacy needのis_nightによるintimacy_night/intimacy_day入力選択だけ。ピーク値・NTRイベントの制作証拠はない。scripts/operations/operations_coordinator.gd:1190–1194は負のnet_profit連続カウンタがconfig bankruptcy_close_countに達するとTERMINAL_BANKRUPTを選ぶ処理だけ。設定値が3だとは主張せず、著作されたゲームオーバー内容は欠損。L196の専用代物弁済イベントは現物制作証拠なしとしてmissing。数量/シーン列はundefinedのまま。
P19/P22の旧状態をそのまま合否にしない。P19の正確な21セルと自然到達未完成の事実を版固定し、現在の関係ソースも独立参照する。P22全614用途レコードと全296mediaを保存し、表現先の現物SHAを監査アンカーへ再結合する。表現型からcode-drawing / placeholder / missingを区別し、歴史的inventoryのSHAと現在アンカーのSHAを別々に保持する。全assetsのパス/SHAも保存する。P22-03はdraft/unaccepted reference only。
@@ -64,7 +68,7 @@ authorities()は提出行や旧監査の合否を使わず、BASELINE本文の
このworkerはJSON/Markdownの生成処理と読取による実装確認だけを行った。p26-ledger / p26-negative / p26-source-binding、--check、--source-binding-only、unittestは実行していない。PASSは主張しない。正式試験はRunnerが契約の3コマンドを実行する。
修復5の生成後の読取比較では762行、1309 AR処置、675関連ARを保持し、全行のID・引用・ARリンクは開始時と同一。全required_count/completed_countはnull。JSONの変更した最上位領域はrowsとatomic_dispositionsのみで、D05の4回答を含む他の領域は同一。JSONとMDはexpected/markdownによる決定的生成であり、試験実行結果ではない。生成後に変更したcheckerの独立検証と負例はRunnerでの実行待ち。
修復6の生成後の読取比較では762行、1309 AR処置、675関連ARを保持し、全行のID・引用・ARリンクは開始時と同一。全required_count/completed_countはnull。JSONの変更した最上位領域はrowsのみで、D05の4回答、atomic_dispositions、source pinsを含む他領域は同一。JSONとMDはexpected/markdownによる決定的生成であり、試験実行結果ではない。生成後に変更したcheckerの独立検証と負例はRunnerでの実行待ち。今回の実装担当指示「試験はRunnerが正式実行します」に従い、登録済み3チェックはworker未実行、結果は未取得。
## 新Sと受入の残ゲート
@@ -42,25 +42,38 @@ SUPPORT_POLICY = {
'ars': frozenset({'AR.relationship.three_emotions',
'AR.relationship.affection_shield_max'} |
{'AR.heroine.' + p + '.route.' + r for p, _ in PEOPLE for r in ROUTES}),
'sources': [('scripts/relationship/original_relationship_state.gd', None),
('scripts/relationship/relationship_service.gd', None)],
'scope': 'shared explicit relationship state/validation/save container only; no updates, attacks, thresholds, authored content or natural route completion'},
'sources': [('scripts/relationship/original_relationship_state.gd', (6, 6)),
('scripts/relationship/original_relationship_state.gd', (21, 25)),
('scripts/relationship/original_relationship_state.gd', (26, 26)),
('scripts/relationship/relationship_service.gd', (38, 58)),
('scripts/relationship/relationship_service.gd', (315, 355))],
'scope': 'affection/lust/netorare fields and finite-number validation; shield_max==affection and 0<=shield_current<=shield_max invariant; subject_id-keyed original record registration; separate generic route_lock/route_id record only, with no original route IDs, natural reach or content'},
'peeping-container': {
'ars': frozenset({'AR.observation.recorder', 'AR.underground.observation',
'AR.underground.blackmail', 'AR.route_action.observation_progress',
'AR.ui.observation_camera_entry', 'AR.ui.observation_capture',
'AR.schedule.B-14.3.observation'}),
'sources': [('scripts/special/peeping_room_service.gd', (127, 162)),
('autoload/simulation_runtime.gd', (10860, 10880))],
'scope': 'stopped room/target reference and fixture evidence-key container only; production placement/recorder eligibility pending; no view, camera UI, screenshot, intervention, transaction or authored content'},
'ars': frozenset({'AR.observation.recorder', 'AR.underground.observation'}),
'sources': [('scripts/special/peeping_room_service.gd', (127, 138)),
('scripts/special/peeping_room_service.gd', (140, 142)),
('scripts/special/peeping_room_service.gd', (155, 164)),
('autoload/simulation_runtime.gd', (10863, 10864))],
'scope': 'observation state half only: stopped/link_state/target and precondition precedence; recorder ledger fields evidence_id/room_id/target_instance_id/source_event_key/minute with fixture-only writes; production record_evidence returns RECORDER_ELIGIBILITY_PENDING_D04_D08_P16, placement returns BUILD_DEFINITION_PENDING_D04; no normal entry, recorder placement, view, camera UI, screenshot, route progress, dedicated mode, intervention, transaction or authored content'},
'night-input': {
'ars': frozenset({'AR.events.ntr_night_peak', 'AR.guest.need_sexual_night_peak'}),
'sources': [('scripts/guest/guest_service.gd', (355, 360))],
'scope': 'night-dependent guest need input only; no event production or peak-frequency implementation'},
'ars': frozenset({'AR.guest.need_sexual_night_peak'}),
'sources': [('scripts/guest/guest_service.gd', (355, 359))],
'scope': 'adult intimacy need selects intimacy_night or intimacy_day input key from is_night only; no peak values, NTR events or event production'},
'bankruptcy-bookkeeping': {
'ars': frozenset({'AR.progression.three_deficits_gameover'}),
'sources': [('scripts/operations/operations_coordinator.gd', (1183, 1195))],
'scope': 'bankruptcy terminal bookkeeping only; no authored ending'},
'sources': [('scripts/operations/operations_coordinator.gd', (1190, 1194))],
'scope': 'consecutive negative-net-profit counter reaches config bankruptcy_close_count and selects TERMINAL_BANKRUPT only; configured value 3 is not established; no authored game-over ending'},
}
# Independent exclusions from the direct source-read map. Never derive these
# from SUPPORT_POLICY: a policy re-add must itself be rejected.
EXCLUDED_ATTRIBUTIONS = {
'AR.ui.observation_camera_entry': 'camera icon and dedicated observation screen transition',
'AR.ui.observation_capture': 'screenshot evidence collection',
'AR.underground.blackmail': 'blackmail transaction state and income',
'AR.route_action.observation_progress': 'route progress from observation room',
'AR.schedule.B-14.3.observation': 'dedicated observation mode achievement',
'AR.events.ntr_night_peak': 'NTR event night peak',
}
@@ -262,7 +275,8 @@ def expected(root):
'evidence': evidence or [], 'missing': 'original production content missing or undefined',
'reason': reason, 'owner': owner})
add('chapters.all', 'chapter', [(8,), (26,), (27,30), (256,)],
'メインストーリー全章。原本の仕様書章番号をシナリオ章と混同しない。章名・章数・順序・場面一覧は未定義。', 'D08')
'メインストーリー全章。原本の仕様書章番号をシナリオ章と混同しない。章名・章数・順序・場面一覧は未定義。', 'D08',
reason='欠損: 制作内容は欠損。undefinedは章の範囲・数量のみを指す。章名・順序・場面一覧は原本未定義、D08未決。')
add('endings.all', 'ending', [(9,), (135,)],
'全エンドを要求。個別エンドID・本数・到達条件は未定義。', 'D08', 'missing')
add('endings.bad', 'ending', [(135,)],
@@ -274,7 +288,8 @@ def expected(root):
add('encyclopedia.all', 'encyclopedia', [(9,)],
'図鑑コンプ。対象集合・項目ID・解放条件・必要項目数は未定義。', 'D08', 'missing')
add('dialogue.all', 'dialogue', [(155,), (230,), (256,)],
'会話/イベント用台詞とシナリオ。本文・話者・行数・場面単位は未定義。UI通知文を完成脚本に数えない。', 'P26-02')
'会話/イベント用台詞とシナリオ。本文・話者・行数・場面単位は未定義。UI通知文を完成脚本に数えない。', 'P26-02',
reason='欠損: 制作内容は欠損。undefinedは台詞の範囲・数量のみを指す。本文・話者・場面単位は原本未定義、D08未決。')
add('portraits.all', 'portrait', [(160,161), (230,), (235,), (242,)],
'メイン/サブ人物の表情・衣装・破損・汚れ・刻印・妊婦外見・ルート別描き分け。差分枚数未定義。', 'P26-03', 'missing')
add('voice.all', 'voice', [(252,), (257,)],
@@ -382,6 +397,10 @@ def expected(root):
row['evidence'] += support_pins(root, kind)
supported_ids = {a for claim in row['scoped_support'] for a in claim['atomic_requirement_ids']}
row['unsupported_atomic_requirement_ids'] = sorted(set(matches) - supported_ids)
excluded = sorted(set(matches) & EXCLUDED_ATTRIBUTIONS.keys())
if excluded:
row['reason'] += ' ' + '; '.join(a + ': uncredited precursor, not required behaviour (' +
EXCLUDED_ATTRIBUTIONS[a] + ')' for a in excluded) + '。関連基盤コードは存在するが当該ARの証拠には帰属させない。'
if row['scoped_support']:
row['status'] = 'partial'
row['support_scope'] = '; '.join(c['scope'] for c in row['scoped_support'])
@@ -434,6 +453,9 @@ def expected(root):
def verify_authority(candidate, root):
"""Non-canonical coverage/ownership/citation checks, callable on their own."""
for policy in SUPPORT_POLICY.values():
require(not (set(policy['ars']) & EXCLUDED_ATTRIBUTIONS.keys()),
'excluded attribution in SUPPORT_POLICY')
lines, required, atoms, relevant, packages = authorities(root)
seen_lines, seen_atoms = set(), set()
row_ids = {r['id'] for r in candidate['rows']}
@@ -477,6 +499,8 @@ def verify_authority(candidate, root):
policy = SUPPORT_POLICY[kind]
require(support_family(row), 'support incompatible with requirement family')
targets = claim['atomic_requirement_ids']
require(not (set(targets) & EXCLUDED_ATTRIBUTIONS.keys()),
'excluded attribution in row claim')
require(type(targets) is list and targets and len(targets) == len(set(targets)) and
set(targets) <= set(ids) & policy['ars'], 'support incompatible with AR')
require(claim['scope'] == policy['scope'] and claim['content_status'] == 'missing',
@@ -182,12 +182,23 @@ class LedgerTests(unittest.TestCase):
rows = {r['id']: r for r in self.submitted['rows']}
audit.verify_authority(self.submitted, ROOT)
for identity, kind in [('route.anri.love', 'relationship-container'),
('original.line.138', 'relationship-container'),
('original.line.140', 'relationship-container'),
('original.line.65', 'night-input'),
('original.line.53', 'peeping-container')]:
('original.line.53', 'peeping-container'),
('original.line.34', 'peeping-container'),
('original.line.72', 'bankruptcy-bookkeeping')]:
with self.subTest(control=identity):
self.assertEqual(rows[identity]['status'], 'partial')
self.assertEqual(rows[identity]['content_status'], 'missing')
self.assertIn(kind, {c['kind'] for c in rows[identity]['scoped_support']})
allowed_controls = {
'AR.relationship.three_emotions', 'AR.relationship.affection_shield_max',
'AR.underground.observation', 'AR.observation.recorder',
'AR.guest.need_sexual_night_peak', 'AR.progression.three_deficits_gameover',
} | {'AR.heroine.' + p + '.route.' + r for p, _ in audit.PEOPLE for r in audit.ROUTES}
self.assertEqual({a for row in rows.values() for c in row['scoped_support']
for a in c['atomic_requirement_ids']}, allowed_controls)
for identity in ('voice.all', 'portraits.all', 'endings.all', 'encyclopedia.all'):
self.assertEqual(rows[identity]['status'], 'missing')
self.assertEqual(rows[identity]['evidence'], [])
@@ -197,13 +208,16 @@ class LedgerTests(unittest.TestCase):
row.update(status='partial', support_scope='backend only',
evidence=copy.deepcopy(rows['original.line.53']['evidence']))
self.independent_reject(inject, 'unqualified partial support')
# Even a well-formed observation claim linked on the SAME source line
# cannot be attached to a voice summary.
# Preserve the same-line voice attack: the old observation schedule AR
# shares L257 with voice, even though it is now independently excluded.
def voice_claim(d):
voice = next(r for r in d['rows'] if r['id'] == 'voice.all')
mixed = rows['original.line.257']
mixed = rows['original.line.53']
for key in ('status', 'support_scope', 'scoped_support', 'evidence'):
voice[key] = copy.deepcopy(mixed[key])
atom = 'AR.schedule.B-14.3.observation'
self.assertIn(atom, voice['atomic_requirement_ids'])
voice['scoped_support'][0]['atomic_requirement_ids'] = [atom]
self.independent_reject(voice_claim, 'support incompatible with requirement family')
# An original-clause row is an eligible family, but its debt-settlement
# ARs still cannot receive a peeping-container claim.
@@ -226,6 +240,11 @@ class LedgerTests(unittest.TestCase):
self.assertIn(atom, rows[identity]['unsupported_atomic_requirement_ids'])
def expand(d):
row = next(r for r in d['rows'] if r['id'] == identity)
if not row['scoped_support']:
donor = rows['original.line.53']
for key in ('status', 'support_scope', 'scoped_support', 'evidence'):
row[key] = copy.deepcopy(donor[key])
row['scoped_support'][0]['atomic_requirement_ids'] = []
row['scoped_support'][0]['atomic_requirement_ids'].append(atom)
row['unsupported_atomic_requirement_ids'].remove(atom)
self.independent_reject(expand, 'support incompatible with AR')
@@ -234,6 +253,57 @@ class LedgerTests(unittest.TestCase):
['evidence'].extend(copy.deepcopy(rows['original.line.53']['evidence'])),
'unrelated or unscoped support evidence')
def excluded_attribution_rejected(self, atom, line, kind, control_atom, control_line):
# Fixed cases below are independent of both policy and exclusion table.
audit.verify_authority(self.submitted, ROOT)
rows = {r['id']: r for r in self.submitted['rows']}
control = rows['original.line.' + str(control_line)]
self.assertTrue(any(c['kind'] == kind and control_atom in c['atomic_requirement_ids']
for c in control['scoped_support']))
target = rows['original.line.' + str(line)]
self.assertIn(atom, target['unsupported_atomic_requirement_ids'])
def inject(d):
row = next(r for r in d['rows'] if r['id'] == target['id'])
claim = {'kind': kind, 'atomic_requirement_ids': [atom],
'scope': audit.SUPPORT_POLICY[kind]['scope'], 'content_status': 'missing'}
row.update(status='partial', content_status='missing', scoped_support=[claim],
support_scope=claim['scope'], evidence=audit.support_pins(ROOT, kind),
unsupported_atomic_requirement_ids=sorted(set(row['atomic_requirement_ids']) - {atom}))
self.independent_reject(inject, 'excluded attribution in row claim')
policy = copy.deepcopy(audit.SUPPORT_POLICY)
policy[kind]['ars'] = policy[kind]['ars'] | {atom}
with patch.object(audit, 'SUPPORT_POLICY', policy):
with self.assertRaisesRegex(ValueError, 'excluded attribution in SUPPORT_POLICY'):
audit.verify_authority(self.submitted, ROOT)
# Even regeneration under a corrupted policy cannot legitimize it.
with self.assertRaisesRegex(ValueError, 'excluded attribution in SUPPORT_POLICY'):
audit.verify_authority(audit.expected(ROOT), ROOT)
audit.verify_authority(self.submitted, ROOT)
def test_excluded_camera_entry(self):
self.excluded_attribution_rejected('AR.ui.observation_camera_entry', 221,
'peeping-container', 'AR.underground.observation', 34)
def test_excluded_screenshot_capture(self):
self.excluded_attribution_rejected('AR.ui.observation_capture', 222,
'peeping-container', 'AR.observation.recorder', 53)
def test_excluded_blackmail(self):
self.excluded_attribution_rejected('AR.underground.blackmail', 21,
'peeping-container', 'AR.observation.recorder', 53)
def test_excluded_observation_route_progress(self):
self.excluded_attribution_rejected('AR.route_action.observation_progress', 156,
'peeping-container', 'AR.underground.observation', 34)
def test_excluded_dedicated_observation_mode(self):
self.excluded_attribution_rejected('AR.schedule.B-14.3.observation', 257,
'peeping-container', 'AR.observation.recorder', 53)
def test_excluded_ntr_event_night_peak(self):
self.excluded_attribution_rejected('AR.events.ntr_night_peak', 65,
'night-input', 'AR.guest.need_sexual_night_peak', 65)
if __name__ == '__main__':
parser = argparse.ArgumentParser()