Evidence-Gated Allocator
0.11.1공개일 2026-08-25>=0.4.0Evidence-Gated Allocator
<sub><a href="README.md">English</a></sub>
기계 신호 하나만으로는 아무것도 사지 않는다. 적어둔 논거, 그 논거에 반하는 논거, 그리고 이 종류의 판단이 실제로 통했다는 기록이 있어야 크게 잡는다.
한 문단 요약
화면에서 기회처럼 보이는 것의 대부분은 그냥 화면이다. 이 매니저는 스캐너 점수를 무언가를 조사할 이유로 다루지, 살 이유로는 절대 다루지 않는다. 새 포지션을 제안하기 전에 이것들을 요구한다: 틀렸음이 증명될 수 있는 주장, 왜 싼지에 대한 설명, 그냥 지수를 사는 것보다 낫다는 논증, 그리고 그 논거를 무너뜨리려고 시도한 적대적 검토. 그리고 확신이 아니라 산식으로 크기를 정한다: 포지션은 후보 자신의 기대·하방 수익률 위의 quarter Kelly이고, 선언된 maxDrawdown에서 유도한 리스크 예산 아래 있으며, 선언된 maxPositionWeight는 그 위의 천장이다 — ⛔ 기본값이 아니다. 산식이 그 거래소에서 열 만한 최소 규모보다 작은 답을 내면 그 최소치로 올림하지 않고 거절한다. 올리면 그 크기가 재는 것은 아이디어가 아니라 반올림이기 때문이다. ⚠️ 별도의 축소된 «실험 레인»은 2026-09-08 투자자 지시로 없앴다(#226): 이 매니저는 실제 브로커에 붙어 있고 모든 주문이 사람의 승인을 거치며 모든 판단이 전방수익률과 함께 append-only 원장에 남으므로 실제 매수 자체가 이미 측정 장치다. 대신 논거 없이 사지는 않는다 — 검사된 variant view가 없는 후보는 아예 제안되지 않는다. 한국과 미국을 한 매니저에서 다루고, 실행당 정확히 하나의 제안을 낸다.
이것은 morethanmin/trading-harness의 방법론과 검증 루프를 옮긴 이식본이다 — 그 하네스의 개인 데이터나 주문 스택이 아니라. 증권사 연동, 수량, 주문 유형, 지정가, 승인, 체결은 전부 Aumos에 남는다. 이 패키지에는 주문 코드가 없다.
방법론
포트폴리오의 무엇이든 바뀌기 전에, 이 순서로 던지는 두 질문:
- 반증 가능한 논지와, 반대 증거와, 그냥 벤치마크를 사는 것보다 나은 논거가 있는가?
- 이 종류의 판단이 그 크기를 받을 만큼 독립적인 포워드 증거를 쌓았는가?
이 페이지가 쓰는 용어를 쉬운 말로:
| 논지(thesis) | 미래에 대해 적어둔 주장과, 그것이 틀렸음을 증명할 조건 |
| 렌즈(lens) | 후보를 읽는 셋업의 종류 — 싼 것이 되튀는 경우, 강한 것이 눌리는 경우 등. 렌즈마다 자기 트랙레코드를 따로 갖는다 |
| 낙하하는 칼 | 아직 떨어지는 중인 것. 권고가 아니라 코드에서 차단된다 |
| basing | 신저가를 더는 만들지 않고 평평해진 가격 — 하락이 끝났다는 증거 |
| 벤치마크 대안 | 정직한 비교: 이 모든 수고 없이 지수만 샀어도 비슷했는가? |
| maturity(성숙도) | 렌즈가 쌓은 닫힌 포워드 증거의 양. 낮은 maturity는 크기를 제한하지, 확신을 제한하지 않는다 |
| 슬리브(sleeve) | 장부에서 한 시장이 차지하는 조각. 이 매니저는 한국 슬리브와 미국 슬리브를 굴린다 |
| 페이퍼 콜 | 돈을 걸지 않은 채 기록되고 채점되는 리서치 콜 |
스캐너 점수는 발견이지 엣지가 아니고, 렌즈마다 자기 측정치로 순서를 정한다. 발견 점수는 코드에서 mean-reversion-depth-only로 라벨링된다. 그것이 실제로 재는 것이기 때문이다 — 얼마나 깊이 빠졌는가. 매수 신호가 아니고, 다른 렌즈들의 순위도 아니다: 강한 종목이 눌린 경우는 이 점수가 0이다. 렌즈마다 무엇으로 순서를 정하는지 스스로 선언하고 일부러 서로 다른 척도를 쓰므로, 세 렌즈를 조용히 한 줄로 세우는 일이 생기지 않는다.
렌즈 넷을 따로 판단한다. 평균회귀, 추세 눌림, quality pullback, basing은 서로 다른 질문이고 서로 다른 기록을 갖는다. quality pullback은 200일 이동평균 위에서 고점 대비 15~35% 조정된 구간으로, 다른 둘이 그 사이에 떨어뜨리는 밴드다 — 좋은 종목이 싸질수록 오히려 커버리지에서 사라지는 자리.
진입 품질은 서술이 아니라 코드가 거절한다. 낙하하는 칼은 차단된다. 홀로 선 평균회귀 후보는 확인된 basing이나 눌림 상태를 요구받는다. 산문으로 적힌 요구사항은 지친 독자가 면제해주는 요구사항이다.
리스크는 비중 네 축 — 종목·섹터·테마·팩터 — 그리고 모든 손절이 동시에 발동했을 때의 총손실에 상한이 걸린다. 마지막 것은 어떤 비중 축도 재지 않는다. 총 리스크 노출 상한과, 신규 단일종목이 너무 빠르게 늘 때의 경고도 있다.
충족되지 않은 조건은 기계가 평가할 수 있는 WATCH 항목이 된다 — 가격, 날짜 또는 공시 트리거와 만료를 달고. 사라지는 산문이 아니라.
크기는 확신이 아니라 증거를 따른다. 닫힌 성과가 각 렌즈의 maturity와 보정을 인스턴스 자기 사설 폴더에서 갱신한다. ⛔ #226부터 maturity는 크기를 정하지 않는다 — 그것은 귀속 라벨이고, 학습 기질은 페이퍼 코호트가 아니라 Aumos 결정 원장과 Forward Track Record가 진다. 자신 있는 크기를 허가하는 일은 여전히 절대 없다: 허가하는 것은 산식이다. 그리고 보정이 스스로 방법론을 승격하거나 다시 쓸 수는 없다 — 그건 검토된 패키지나 config 변경의 몫이다.
세 플로우, 한 매니저
역할들은 이 한 매니저의 서브에이전트이고, 순서대로 호출된다.
| 플로우 | 무엇을 소유하는가 |
|---|---|
kr-sleeve | 한국 리서치와, 기록된 예산 안에서의 한국 슬리브 BUY/SELL/RESIZE |
us-sleeve | 미국 리서치와 미국 슬리브. 정책상 지정된 유동성 포함 |
allocate | 원/달러 슬리브 목표, FX, 장부 전체의 현금과 집중도, 그리고 시장 간 REBALANCE |
대부분의 실행은 셋 중 하나만 돌린다. 각 플로우는 자기가 맡은 시장에 맞춰 자기 웨이크를 갖는다:
| 웨이크 | KST | 그 직전에 무슨 일이 있었나 |
|---|---|---|
us-sleeve | 05:45–06:45 | 미장이 닫히고 그날 봉이 완성됐다 |
allocate | 08:00 | 두 시장이 다 닫혀 있고 국장은 아직 안 열렸다 — 그날 슬리브 예산을 여기서 정한다 |
kr-sleeve | 16:00 | 국장이 닫히고 그날 봉이 완성됐다 |
실행은 자기를 깨운 플로우가 무엇인지 읽고 그것만 디스패치한다. 둘 이상이 도는 경우 — 수동 실행, 사건 검토, 또는 어떤 슬리브의 결론이 그 시장의 마지막 종가보다 오래됐음을 allocate 웨이크가 발견한 경우 — 에는 순서대로 돌고 절대 병렬이 아니다: allocate는 두 슬리브를 서로에 대고 값매기는데, 아직 판단 중인 슬리브를 상대로는 그럴 수 없다.
단일 슬리브 실행은 자기 슬리브에 기록된 예산 안에서 움직일 수 있다. 시장 간 REBALANCE는 낼 수 없다. 다른 슬리브를 보지 못한 슬리브가 장부 전체의 모양을 주장할 수는 없다.
⛔ 오케스트레이터만, 정확히 한 번 제출한다. 한 실행은 판단 하나를 봉인하고 두 번째 제출은 거절되므로, 플로우가 제출하면 나머지 둘이 보지도 않은 판단을 봉인하면서 오케스트레이터 자신의 제출까지 함께 무너뜨린다. 프롬프트와 스킬 넷이 그렇게 적고, 페이로드가 서브에이전트를 이름 대면 호출을 거절하는 훅이 강제한다.
⚠️ 2026-08-27까지 이것은 패키지 셋이었다(evidence-gated-kr·-us·-global). 나눠 둔 값이 얻는 것보다 컸다: 셋은 바이트로 똑같은 코드와 스킬을 싣고 프롬프트 네 줄과 매니페스트만 달랐다 — 한 방법론의 사본 셋이 갈라질 자유를 갖고 있었고, 투자자는 그것을 세 번 찾아 세 번 설치해야 했다. 진짜로 잃은 것은 슬리브별 채점과 슬리브별 승인이다: 트랙레코드의 행도 승인 게이트도 이제 한 매니저이고 한 바구니다.
⚠️ **슬리브별 디스패치도 같이 잃었고, 그건 의도가 아니었다.** 통합 전에는 각 시장의 웨이크가 서로 다른 매니저의 것이었으므로 한국 웨이크는 한국 패키지를 돌렸다. 통합 뒤 세 웨이크가 전부 같은 매니저에 도착했고, 매니저는 그때마다 세 플로우를 전부 돌렸다 — 세 배의 일, 그리고 각 슬리브가 하루에 두 번, 한 번은 아직 닫히지도 않은 봉으로 판단됐다. 스케줄러는 그 구분을 계속 유지하고 있었고, 읽는 쪽이 없었다. #87에서 고쳤다.
실행 흐름
한 번의 실행에 하나의 제안. 아래 어느 것도 주문을 내지 않는다.
flowchart TB
classDef reads fill:#1e2a44,stroke:#6f9bf0,color:#cfe0ff
classDef judges fill:#2f2f38,stroke:#9aa0b4,color:#e8eaf2
classDef proposes fill:#1b4332,stroke:#40916c,color:#d8f3dc
classDef person fill:#5c4813,stroke:#f6a609,color:#ffe8b0
WAKE["포트폴리오 · 자산 · 논지 · 사건 검토로<br/>Aumos가 깨운다"]:::reads
subgraph IN["1 · 범위와 상태"]
direction TB
BOOK["장부, 현금, 체결"]:::reads
SRC["벤더 데이터 — 한국·미국 가격,<br/>공시, 뉴스, 기업행위"]:::reads
MEM["이 인스턴스가 배운 것:<br/>렌즈 maturity, 보정, 반복 실패"]:::reads
PRE["거래를 계획하기 전 사전 점검"]:::judges
end
WHICH{"2 · 이 웨이크는 어느 플로우의 것인가?"}:::judges
subgraph FLOWS["세 플로우 — 웨이크당 하나, 여럿 돌 때는 순서대로"]
direction TB
KR["kr-sleeve · 16:00 KST<br/>한국 리서치와 슬리브"]:::judges
US["us-sleeve · 05:45 KST<br/>미국 리서치와 슬리브"]:::judges
AL["allocate · 08:00 KST<br/>두 슬리브를 서로에 대고 값매긴다"]:::judges
end
HOLD["2b · 이미 보유한 것을 감시<br/>가격과 펀더멘털을 병행,<br/>매도 방향 전용"]:::judges
LENS["3 · 렌즈를 지목<br/>평균회귀 · 추세 눌림 ·<br/>quality pullback · basing"]:::judges
GATE{"진입 게이트 — 코드가 거절한다<br/>낙하하는 칼 · basing 확인 ·<br/>why-cheap · variant view ·<br/>벤치마크 대안 · 챌린지"}:::judges
SIZE["4 · 크기와 일정<br/>비중 네 상한, 총손절 상한,<br/>그리고 그 렌즈 자신의 maturity"]:::judges
WATCH["WATCH / plan<br/>충족되지 않은 조건을 가격 ·<br/>날짜 · 공시 트리거와 함께"]:::proposes
ACT["BUY / SELL / RESIZE / REBALANCE<br/>오케스트레이터만 내는 하나의 제안"]:::proposes
LEARN["5 · 지속 상태를 아껴서 갱신<br/>6 · 다음 검토를 다시 건다"]:::proposes
subgraph HUMAN["사람이 결정하는 자리"]
direction TB
MAND["Aumos가 당신의 Mandate에 비추어 판정"]:::person
YOU["당신이 승인하거나, 하지 않는다"]:::person
ORD["그때에야 주문이 존재한다"]:::person
end
WAKE --> IN --> PRE --> WHICH
WHICH -- "kr-sleeve" --> KR
WHICH -- "us-sleeve" --> US
WHICH -- "allocate" --> AL
WHICH -- "플로우 없음: 수동 · 사건 — 셋 전부, 순서대로" --> FLOWS
KR --> HOLD
US --> HOLD
AL --> HOLD
HOLD --> LENS --> GATE
GATE -- "게이트 미충족" --> WATCH
GATE -- "모든 게이트 통과" --> SIZE --> ACT
WATCH --> LEARN
ACT --> LEARN
LEARN --> MAND --> YOU --> ORD
범례 — 🟦 읽는 것 · ⬜ 스스로 계산하는 것 · 🟩 돌려주는 것 · 🟧 사람이 결정하는 자리.
주기. 달력이 아니라 검토나 사건으로 깨어난다. 다시 데려오는 것은 스스로 걸어둔 WATCH — 가격, 날짜 또는 공시를 트리거로 — 그리고 앞을 내다보기 위해 유지하는 리서치 일정이다.
산술은 모델의 것이 아니다. 스캐닝, 사이징, 커버리지, 증거 채택, 보정, 귀속, 시점 고정 파싱, 스케줄 계산은 전부 산문이 아니라 패키지 자신의 결정론 코어를 통해 돈다. 그 코어에는 파일시스템 원장도, 자격증명도, 네트워크도, DB도, 주문 접근도 없다.
필요한 것
| 시장 | 한국과 미국의 주식·ETF·현금. 롱온리 |
| 연결과 데이터 소스 | 미국 단일종목 레인은 Toss를 연결하고 sec-edgar를 설치한다. Alpaca가 뉴스·기업행위를 제공하며, 없으면 부여된 웹 조사로 대체한다. 완전한 한국 단일종목 펀더멘털 레인은 이 패키지와 함께 이 카탈로그에 게시된 open-dart를 추가로 요구한다. openbb-fmp는 선택이고 장기 가격 이력을 보충할 때만 쓴다 |
| 장부 | 실시간 포지션·현금·체결. 이 패키지가 아니라 Aumos와 증권사 커넥터가 계속 소유한다 |
| 설정 | 방법론이 비교하는 문턱값들. 기본 5%인 가격 충돌 허용치를 포함한다. 어느 것도 당신의 Mandate를 느슨하게 만들 수 없다 |
| 당신의 승인 | 제안할 뿐 거래하지 않는다. 수량·주문 유형·지정가·승인·체결은 Aumos의 것이고, 모든 주문은 사람이 승인한다 |
입력이 없을 때의 비용을, 실행이 발견하기 전에 말한다. 매니페스트가 Toss·Alpaca는 증권사 연결로, sec-edgar·open-dart는 데이터 소스로 이름 대므로 설치 화면이 이 펀드나 기계에 무엇이 없는지 말할 수 있다.
| 누락 | 계속 가능 | 차단 |
|---|---|---|
| Toss 연결 | 기존 증거·논지 검토 | 신규 가격 신호와 목표 계산 |
sec-edgar | 한국·ETF 레인 | 신규 미국 펀더멘털 BUY 또는 승격 |
| Alpaca 연결 | SEC·Toss 검토, 날짜와 URL을 남기는 웹 뉴스·기업행위 조사 | 웹도 없거나 관측을 확인하지 못한 뉴스·기업행위 주장 |
open-dart | 한국 ETF와 가격/비중 관리 | 신규 한국 단일종목 펀더멘털 BUY 또는 승격 |
| CLI web | 코어·청산·비중 관리 | theme radar, variant view, 컨센서스 차이, 정책·매크로 주장 |
필요한 연결이 없는 펀드나 필요한 소스를 설치하지 않은 기계는 이름 댄 입력이 없는 것이다 — 아무도 갖지 못한 기능이 아니다. 레인이 막힌 곳에서 답은 어느 것 때문인지 말하는 판단 불가 WAIT다.
약한 지점
- 빠른 것. 모든 게이트는 새 포지션을 늦추려고 존재하고, 대부분의 실행은 거래가 아니라 WATCH로 끝난다. 그게 우유부단으로 읽힌다면 잘못 고른 패키지다.
- variant view 없이 선언한 크기로 개별종목을 사는 것. ⚠️ 설치 전에 읽어라. 가장 놀라기 쉬운 지점이다. 레인은 둘이고 사이징이 완전히 다르다. variant view가 확인된 후보 — 시장과 어디서 다르게 보는지를 적은 완전한 thesis, 시장의 관점이 무엇인지에 대한 날짜·출처가 붙은 인용 최소 1건, 그리고 통과한 적대적 챌린지 — 는 당신이 선언한
maxPositionWeight까지 실릴 수 있다(섹터·테마·팩터 상한은 그대로 지배한다). 그것이 없는 후보는 기계적 대조군 진입이다 — 자산의 1% 안팎, 최대 3%, 레인 전체로 6%. 이 숫자들은 원본 방법론이 승인한 값 그대로이고, 그것이 인코딩한 거래는 명시적이다: 대조군은 엣지를 논증할 필요가 없는 대신 클 수 없다. ⚠️ 대부분의 후보는 대조군에 떨어지고, 그것이 정상 상태다. 스캐너가 찾는 것은 가격 패턴이고 가격 패턴은 공개 정보이므로 variant view가 아니다. "확인되지 않음"이 "확인됨"으로 취급되는 경로는 없다 — 인용 누락, 미완 thesis, 조건부 챌린지 판정은 전부 대조군행이며 (variant_view_required_for_position), 매니저는 모든 실행에서 어느 상한이 작동 중이고 왜인지를 말한다(position_cap_reduced_below_declared). ⚠️ #226부터 그 게이트는 줄이지 않고 거절한다. 전에는 그런 후보를 20배 작게 실어 제출했다 — 크기 다이얼을 겸하는 증거 게이트는 증거에 대해서도 크기에 대해서도 정직하지 않다. 승격은 여전히 주 단위가 아니라 연 단위이고, 이제 어떤 크기도 게이트하지 않는다. 렌즈는 닫힌 결과 30건, 독립 날짜 클러스터 10개, 서로 다른 시장 레짐 3개로 승격된다. 앞의 둘은 후보를 더 많이 찾으면 빨라지지만 셋째는 아니다 — 레짐은 달력이 지나야 바뀌므로 활동량으로 줄일 수 없는 수년짜리 대기다. 그 바를 넘긴 것 없이 이번 분기에 확신 하나에 장부의 20%를 실어 줄 매니저를 원한다면 이 매니저가 아니다. - 원하는 만큼 오래 들고 있는 것. 모든 비코어 포지션은 진입 후 40거래일이면 성과와 무관하게 청산되고, 등록된 손절을 이탈하면 그보다 먼저 청산된다. 이것은 결함의 고백이 아니다 — 이 방법론은 닫힌 결과로 크기를 정하는데, 아무것도 닫지 않는 장부는 자기 게이트를 영원히 닫아둔다. 그것이 이 패키지가 실제로 있던 상태였다(청산 표본 0건). 여기서 손실은 유효한 산출물이다. 사는 것이 기록이기 때문이다. ⚠️ 손절과 리뷰 날짜를 등록하지 않는 진입은 거부되고, 도래한 스톱을 보고하면서 청산을 제안하지 않는 실행도 거부된다. thesis가 익을 때까지 2년을 들고 있어 줄 매니저를 원한다면 이것은 잘못 고른 매니저다.
- 공매도와 레버리지. 롱온리다.
- 자신의 가장 새로운 계층들. 선행 리서치와 매도 방향 계층은 이식됐지만 그 트랙레코드는 아니다: "팀의 콜이 지수와 기계 베이스라인을 둘 다 이기는가?"에 답하는 비교는 닫힌 관측 창이 수개월 쌓여야 무언가를 말한다. 그때까지 리서치 계층의 엣지는 베이스라인의 엣지와 똑같이 가설이다.
- **
open-dart없는 한국 펀더멘털.** 소스는 게시돼 있다. 그것이 없거나 API 키가 없는 기계는 그것을 판단할 수 없다. - 벤더가 틀린 모든 것. 벤더는 자기 응답 모양을 그대로 중계한다. 날짜와 신선도를 검사하는 것은 Aumos가 아니라 이 매니저다.
설치하지 마라 — 잦은 거래를 원한다면, 단일 시장 매니저를 원한다면, 또는 화면에 뜬 결과대로 움직여줄 무언가를 원한다면.
덧붙임
세부는 어디 있는가. ARCHITECTURE.ko.md (ARCHITECTURE.ko.md)가 이 패키지의 엔지니어링 절반이다 — 어떤 상태를 누가 소유하는지, 데이터·설치 계약, 메모리 계약, 스킬, 그리고 원본 Python 하네스와의 parity 검사. MIGRATION.md는 레거시 실행파일 65개와 그 처리를 기록하고, IMPLEMENTATION.md는 빌드 체크리스트를, CONFORMANCE.md는 이 저장소에서 도는 검사와 설치된 런타임이 필요한 릴리스 게이트를 분리한다. INCIDENTS.md는 PROMPT.md의 각 규칙이 무엇에 대고 측정됐는지 — 실패한 실행과 그것이 낸 숫자 — 를 담는다. 프롬프트 자체가 한 번에 읽히는 실행 계약으로 남을 수 있는 이유다.
이 방법론이 일하는 가격을 이제 말한다 — 0.6.0은 그것을 읽는 호스트를 요구한다. 이 패키지가 유도하는 손절 거리와 분할 진입의 각 rung은 언제나 계산된 숫자였고, 판단 계약에 그것을 담을 자리가 없었다: 가격을 말하는 유일한 방법이 감시를 무장하는 것이었고, price-below 하나는 보유 종목의 손절가이면서 아직 갖고 있지 않은 종목의 진입 대기가이기도 하다. DecisionProposal.priceLevels(Aumos 0.4.0)는 목적이 명시된 가격을 나른다 — entry · stop · take-profit — 통화와, 이 패키지 자신의 말로 쓴 근거와, 그것을 지켜보는 감시로의 선택적 연결까지. ⛔ 가격을 적는 것으로는 아무것도 무장되지 않고 아무 주문도 나가지 않는다. 승인 게이트가 여전히 거래소로 가는 유일한 길이다. ⚠️ 익절가는 내지 않는다: 적정가치 범위는 «평가»이고, 그 상단을 장부가 파는 자리로 바꾸는 것은 이 방법론이 선언한 적 없는 규칙이다. ⚠️ 그 필드를 읽지 못하는 호스트에서는 판단을 잃는 대신 필드를 빼고 그 사실을 말한다 — 버전 범위와 그 확인이 둘 다 필요한 이유는 HOST-FOLLOWUPS.md에 있다.
펀더멘털 발굴 분기는 이제 호스트 소스 저장소에서 먹는다 — 새로 생긴 것이다. source-cache:read / source-cache:write(Aumos 0.3.30)가 OpenDART·SEC 공시를 종목별로 보관하고 매 invocation의 asOf에서 잘라 준다. 그래서 이 패키지는 같은 재무제표를 매 실행 재조달하지 않으며, 더 중요하게는 한 번도 채운 적 없는 캐시와 갱신이 실패한 캐시를 구분할 수 있다. 이전에는 둘 다 빈 응답 하나였고, 그것을 읽는 분기는 어느 쪽이든 굶었다고만 보고했다. 그래서 engines.aumos는 >=0.3.30을 요구한다 — 더 낮은 빌드는 모르는 권한을 무시하는 대신 매니페스트 전체를 거부한다. ⛔ 사설 메모리는 캐시가 아니며 앞으로도 되지 않는다.
그리고 같은 굶주림의 반대편 — 20% 레인에 드디어 공급 경로가 생겼다. variantViewCheck는 요구 넷으로 메인 단일종목 레인을 열고, 그중 하나인 consensusRefs—날짜와 출처가 있는 컨센서스 관측—은 웹에서만 오는 입력이다. 증권사 추정치와 목표주가는 공시에도 거래소 피드에도 없고, 매니저의 WebSearch/WebFetch는 CLI의 것이라 Aumos를 지나지 않으므로 Evidence id를 만들지 않는다 — 그리고 evidenceIds는 그 말고는 아무것도 받지 않는다. 이 방법론은 공급 경로를 자기가 막은 입력을 요구하고 있었고, 그 계좌는 8개 실행 동안 단일 종목을 한 주도 사지 않았다(untilled/aumos#692). observation:file(Aumos 0.3.32, untilled/aumos#693)가 그 경로다: observation_file 도구가 URL과 발행일과 원문 그대로의 구절을 기록하고 해시를 덮어 Evidence id를 돌려준다. 그래서 engines.aumos는 >=0.3.32를 요구한다.
⚠️ 그 행은 이 매니저의 증언이고, 패키지는 그 사실을 조용하게 두지 않는다. Aumos는 아무것도 가져오지 않았고 아무것도 검증하지 않았다 — 행은 모든 단계에서 observation / manager:web-research로 등급된다. 그래서 variantViewCheck는 수립된 컨센서스 행 각각의 등급을 게시하고, 매니저가 직접 기록한 행 위에서 메인 레인이 열리면 effectivePositionCap이 disclosures에 main_lane_rests_on_manager_attestation을 실어 돌려주며, 제안은 그 코드를 rationale.risks 항목 하나에 출처 URL과 함께, 그리고 uncertainty 항목 하나에 그대로 실어야 한다 — risks인 이유는 승인 화면이 그것을 그리기 때문이다. 조립된 제안을 그 의무와 대조하는 것은 proposalDisclosure이고, 둘 중 하나라도 빠지면 거기서 main_lane_attestation_undisclosed / blocked다. ⛔ #212 ② 이후 산술 자체는 산문을 읽지 않는다 — 부분 문자열에서 올라온 blocked가 targetWeight에 닿아 문장을 고치면 비중이 움직였다. ⛔ 요구 넷도, 캐도, 대조군의 1% / 6%도 바뀌지 않는다 — 거부하는 것은 레인을 조용히 여는 것이다. 그리고 observationLedger가 반대 방향의 고리를 닫는다 — 웹에서 읽고 판단에 썼는데 제출된 어느 id도 받치지 않는 값은 claim_evidence_missing / blocked이며, 그것이 2026-09-06 BOK 금리 실패를 진단으로 만든 것이다. ⚠️ 등급도 그리로 따라가고, 따라가는 열쇠는 evidence id다 — 같은 호출에 넘긴 영수증이 그것을 인용한 claim을 등급하고, 그 호출이 기록하지 않은 id는 claim_grade_unstated로 이름을 댄다. «여기서는 말할 수 없다»와 «등급 없음»은 다른 답이고, 메인 레인의 공시는 그것이 어느 쪽인가 위에 세워져 있다.
그리고 그 레인의 요구 하나는 지금까지 정직하게 채울 수 없었다 — 진짜 반증 조건이 들어갈 자리가 없었다. 메인 레인의 첫 요구는 완결된 thesis이고, thesis가 완결되려면 invalidationTriggers가 있어야 한다 — 그 종목에 정들기 전에 미리 정해 두는, 무엇이 확인되면 접을 것인가다. 그런데 validateThesis는 kind: 'event'를 통째로 거부했다. 진단문은 "producer-less event is forbidden"이라고 적어 놓고, 발표 주체가 있든 없든 모든 event를 거부했다 — 문장이 걸고 있던 조건이 구현된 적이 없었다. 그래서 "자사주 매입 중단"과 "PF 손실 대규모 인식" 같은, 은행 thesis가 실제로 틀리는 조건들은 버려지거나 아무도 재지 않는 level을 붙인 metric으로 위장해야 했다 — 후자가 더 나쁘다, 기계가 검증하는 것처럼 읽히기 때문이다. 이제 event 무효화는 **producer: { publisher, document }와 checkBy를 함께 갖췄을 때** 수립된다: 누가, 어느 문서로 발표하며, 언제까지 읽는가. ⛔ 이것은 게이트를 넓히는 것이 아니라 좁히는 것이다 — 같은 트리거라도 producer가 없으면 여전히 blocked (invalidation_producer_missing), producer가 있어도 기한이 없으면 blocked (invalidation_event_undated — "아직 발표 안 됐다"는 영원히 참인 답이기 때문이다), 그리고 WATCH 어휘도 캡도 승격 게이트도 대조군 수치도 하나도 움직이지 않았다.
코어 트랜치 게이트가 이제 자기 형제가 거부하는 봉을 함께 거부한다. trendState는 코어 배치를 계속할지 정하는 게이트인데, 토스 캔들 200봉을 벤더 형태 그대로 — closePrice·highPrice, 값은 전부 문자열 — 받고서 status: ok, state: "DOWNTREND", trancheGuidance: "stop"을, 진단 0건과 ma20·ma50·ma200 전부 null인 채로 답했다. 이동평균을 하나도 계산하지 못한 것이다: 상태를 정하는 비교가 전부 undefined > null이라 거짓이고, 거짓이면 DOWNTREND이며, DOWNTREND는 코어 트랜치를 멈춘다. bars.length는 어느 형태에서든 200으로 읽히므로 이력 검사도 발동하지 않았다. 같은 계열을 {date, open, high, low, close, volume} 숫자형으로 넘기면 UPTREND / small_or_wait이고 ma200은 92,704.055 — 사흘 전 다른 봉 묶음으로 무장된 플랜의 트리거 레벨과 소수점까지 일치한다. ⛔ 검증기는 이미 이 패키지 안에 있었다: 형제 연산 indicators는 바이트가 같은 행에 대해 normalizeBars를 돌려 전부 bar_value_invalid로 거부한다. 이 게이트가 그것을 부르지 않았을 뿐이고, 이제 부른다. ⚠️ 여기서 거부된 행은 «버려진 행»이 아니다 — indicators는 답 자체가 행별 보고라 보고하고 넘어가지만, 자본 배치를 멈추는 게이트는 «읽을 수 있었던 부분집합»으로 평균을 내고 그것을 추세라고 부를 수 없다: 읽히지 않는 행이 하나라도 있으면 답은 state: "insufficient_data"이고 진단이 어느 행인지 말한다. 그 뒤에 두 번째 벨트가 선다 — ma200이 계산되지 않았으면 어떤 경로로 그렇게 됐든 state도 trancheGuidance도 반환하지 않는다 — 그리고 inputContracts.nested.trendState가 행 형태를 게시한다. 게시된 계약이 bars: "array" 하나여서 벤더 페이로드가 그것을 만족시켰기 때문이다.
그리고 그 표가 내던 답은 이제 코드에서 읽지 않고 «센다» (#212 ④). mandateExecution은 «이 북이 왜 단일 종목을 하나도 들고 있지 않은가»를 형제 연산들이 돌려준 진단과 lib/diagnostic-codes.mjs의 레인의 교집합으로 답했고, 그중 긍정적인 답 — no-candidate-cleared-the-gates, 게이트가 자기 입력 위에서 돌았고 가질 만한 것이 없었다 — 은 gate-ran 코드 하나의 존재로 얻어졌다. ⚠️ 그 표의 어떤 입력도 아무것도 세지 않았다. active_return_below_gate는 게이트가 한 종목을 거절했다는 말이고, 나머지 일흔셋이 준비되기라도 했는지에 대해서는 아무 말도 하지 않는다 — 그래서 아무도 가격 계열을 수집하지 않은 로스터에서 게이트 하나가 후보 하나를 거절하면 방법론이 작동 중이 돌아왔다. 그것이 untilled/aumos-catalogue#209가 이름 댄 그 실수 — 눈이 먼 것을 기회의 부재로 보고하는 것 — 이고, #171이 다른 실수를 막으려고 세운 검사를 통해 도달됐다.
untilled/aumos#724와 #730이 호스트에 세는 조사 job과 result를 줬으므로 executionRecord가 그것을 읽어 세 사실을 답한다: dataPreparation · candidateEvaluation · eligibleCount. ⚠️ **그다음 untilled/aumos#743이 그 세는 일의 절반을 가져갔고, 가져간 쪽이 옳았다.** research_result_get은 없어졌고 — 스윕은 이제 task_start/task_get/task_cancel이며 recipe 답 하나하나가 실행이 files_read로 되읽는 파일이다 — 봉인된 summary와 함께 그 sourced와 unprepared도 갔다. 그 둘이 말하던 것은 이 펀드가 이 이름에 대해 읽을 수 있는 문서를 들고 있었다 이고, 그것은 문서를 읽는 도메인만 하는 판단이다. 공용 실행기가 그 판단을 하는 것은 앱이 투자 견해를 드는 것이고, 그것을 들어야 하는 쪽은 이 패키지다. 그래서 각 절반을 아는 자리에서 센다: 호스트는 항목이 몇이고 몇이 남았고 몇이 답했고 몇이 못 했는지를 말하고(task_get의 total · pending · done · failed), recipe는 답마다 sourced — 나는 문서를 하나라도 받았나 — 를 쓰고, executionRecord가 그 실행이 실제로 읽은 답들에서 sourced/unprepared/evaluated를 유도한다. ⛔ 여전히 세 보고이고 절대 합쳐지지 않는다, 호스트의 규칙을 그대로 들고 왔다. eligibleCount는 그대로 이 패키지의 것으로 eligibleSymbols — 그 런의 자기 폴드가 도달한 이름들 — 에서 유도된다. 런이 타이핑할 수 있는 숫자는 런이 지어낼 수 있는 숫자이기 때문이다. ⛔ **부재는 null이고 []는 0이다** — basis가 지키는 것과 같은 3분할이고 거기서 none은 0이 아니며, 그 세 낱말도 도구와 함께 움직였다(rows · run · none, rows는 이 실행이 자기 답을 되읽었다) — 그리고 이 연산이 만들지 않은 record는 읽지 않고 execution_record_unreadable로 거절한다. dataPreparation: 'prepared'를 주장하는 객체는 같은 추론이 새 필드의 이름을 입은 것이기 때문이다. ⚠️ **끝난 task run인데 그 답 파일을 아무도 읽지 않았으면 prepared가 아니라 unsettled다**: 끝났다는 것은 호스트의 사실이고 준비됐다는 것은 이 패키지의 사실이며, 답에서 유도한 카운트는 읽은 답만큼만 완전하다.
지운 것과 각각을 대체한 것:
| 지운 것 | 대체한 것 |
|---|---|
CAUSE_CODE_REGISTRY의 gate-ran 레인과 CAUSE_GATE_RAN_CODES (행 4개: active_return_below_gate · challenge_not_cleared · thesis_incomplete · valuation_gap_has_no_source_for_this_instrument) | record의 dataPreparation === 'prepared' 그리고 candidateEvaluation === 'evaluated' 그리고 eligibleCount === 0 |
tools/verify-evidence-gated-diagnostic-codes.mjs ⑴의 그 네 행에 대한 emission 검사 | ⛔ 없음 — 코드는 그대로 발행되고 후보가 왜 거절됐는지 그대로 설명한다. 아무것도 부여하지 않으며, 그 자리에는 «어느 레인도 이들을 들지 않는다»는 단언이 선다 |
응답의 gateRanCodes / gateRanCodeVocabulary | dataPreparation · candidateEvaluation · eligibleCount · executionRecordRead · executionBasis |
모르는 코드가 긍정적 답에 닿는 것을 막던 !recognisedCodes.length (#171) | ⛔ 구조 — 그 답은 이제 센 record를 요구하므로 어떤 코드도 그것을 부여할 수 없다. 관측은 mandate_execution_codes_unrecognised / info로 남는다: 말해지고, 조용하지 않다 |
⚠️ 진단이 여전히 하는 일은 그 답을 «철회»하는 것이고, 그것이 안전한 방향이다. input-path 코드는 task run이 볼 수 없는 단계가 입력을 잃었다고 이름 대고 — 기업코드 조인은 가격 스윕이 아니다 — record를 이긴다. unresolved 코드는 배선을 탓하지 않으면서 긍정적 답을 금지한다. 주장을 거절할 이유를 읽는 것은 부여할 이유를 읽는 것의 반대다. ⛔ 그리고 부재 셋은 절대 합쳐지지 않는다: 'unevaluated'는 «record 없음», 'unprepared'는 «기계가 봤고 이 핀에 읽을 것이 없었다», 0은 측정이다. 다섯째 원인 candidates-cleared-not-proposed가 있는 이유는 record가 코드 레인이 할 수 없던 말을 할 수 있기 때문이다 — 이름들이 실제로 통과했고 북은 그중 하나도 들고 있지 않다. ⛔ 아무것도 막지 않고, 아무 매수도 요구하지 않으며, 어떤 비중도 움직이지 않았다.
진단 코드의 뜻을 정하는 표가 하나가 됐다 — 두 곳에 적혀 있었기 때문이다. mandateExecution은 «이 북이 빈 것은 방법론이 작동한 결과인가, 게이트가 입력을 받은 적이 없어서인가»를 그 런이 보고한 코드와 어휘의 교집합으로 답하는데, 어휘는 읽는 쪽 옆에 손으로 적혀 있었고 코드는 다른 모듈 다섯이 낸다. 둘은 조용히 어긋났다 — 아무것도 매칭하지 못하는 코드는 그냥 매칭하지 않기 때문이다. corp_code_unmapped_symbols(레지스트리를 읽었고 로스터 이름을 놓쳤다) · radar_lane_starved(레이더 자신의 낱말로 «비어 있는 것이 아니라 먹이지 않은 것») · lane_query_failed(리서치 레인을 질의했고 쓸 수 있는 답이 없었다)를 보고한 런이 그 목록과 0건 교차했고, 배선이 세 단계에서 입력을 잃은 북에 대고 no-candidate-cleared-the-gates / info — 방법론이 작동 중 — 을 답했다. 목록이 찾고 있던 것은 corp_code_mapping_pending과 radar_feed_produced_nothing이었다: 실재하는 코드이지만 다른 연산이 다른 모듈에서 내는 것이다. ⛔ **어휘는 이제 목록이 아니라 lib/diagnostic-codes.mjs의 투영이다.** 행마다 코드 · 그것을 내는 연산 · 그것을 담고 있어야 하는 모듈 · 읽히는 레인을 이름 대고, tools/verify-evidence-gated-diagnostic-codes.mjs가 그 모듈들을 열어 «읽는 쪽만 아는 철자»에서 빌드를 빨갛게 만든 다음, mapCorporationCodes·upsideRadar·laneCoverage를 실제로 돌려 그 진단을 손대지 않고 mandateExecution에 넘긴다. ⚠️ **그리고 info는 더 이상 fall-through가 아니다. 매칭하지 못한 코드 집합이 전부 도달하던 갈래여서, 어긋난 어휘는 실패하지 않고 안심시켰다**. 이제는 «실제로 돌아서 거절한 게이트»의 코드가 하나는 있어야 얻고, 이 연산이 아예 읽을 수 없는 코드만 보고한 런은 아무것도 보고하지 않은 런과 같은 답 — unreported — 을 받는다. ⛔ 원인 셋도, 그 severity도, «현금을 들고 있는 것은 절대 매수의 논거가 아니다»라는 규칙도 하나도 안 움직였다.
그리고 반증 조건이 등록된 다음에는, 센티널이 그것에 맞는 숫자를 읽어야 한다. 읽지 않고 있었다. thesisSentinel은 증거를 rule.evidenceId로 찾았는데, id가 없는 증거 행은 전부 그 없는 키 하나에 같이 담겼다 — 그래서 행을 이름 대지 않은 조건은 미판정으로 가지 않고 **id 없는 행 중 마지막 것**을 빌려서 그것과 비교됐다. 실측: 조건 넷과 관측 넷에서 "USDKRW > 1,543.40"이 주가 113,320에 대해 met으로 답했다 — 113,320은 실제로 1,543.40보다 크다. 가격 행을 빼면 같은 오답이 가격 조건으로 옮겨갔고, 그것이 조인을 하고 있던 것이 키가 아니라 자리였다는 증거다. ⛔ 오차의 방향은 언제나 하나였다 — 빌려온 숫자는 자기 것이 아닌 임계값을 가볍게 넘고, met은 threatened이며, 그것이 셋 쌓이면 escalationRequired가 서고 프롬프트가 그것을 빚진 리사이즈 또는 청산으로 바꾼다. 즉 이 결함은 발화한 적 없는 무효화 조건 위에 강제 매도를 제조할 수 있었다. 이제 증거는 키로 조인된다 — evidenceId, 증거 행의 invalidationId, 그리고 metric 조건의 경우 양쪽이 공유하는 metric이고, 셋 다 inputContracts가 게시한다 — 그리고 아무것에도 조인되지 않거나 두 행에 동시에 조인되는 조건은 unevaluated로 답한다. 그 결과 판정은 사람이 읽는 watch가 된다. ⛔ 절대 met이 아니고(없던 위반을 지어낸다) 절대 not-met도 아니다(아무도 증거를 대지 않은 무효화 조건을 검사했고 문제없다로 보고하는 것이다).
그리고 그 북을 재는 캡은 자기가 이름 댄 축에 실제로 닿아야 한다. 라벨 축 셋 중 둘만 지켜지고 있었다. concentration은 sector를 단수 문자열로, themes·factors를 배열로 읽는데, 단수 theme은 #147부터 거절됐고 복수 sectors는 읽는 곳도 거절하는 곳도 없었다. 그것을 넘긴 런은 exposures.sector: {}와 진단 0건, 그리고 status: ok를 받았다 — 선언된 섹터 캡이 아무 무게와도 대조되지 않은 것이다. 통제는 한 필드 폭이다: 그 철자 하나만 단수로 바꾸면 축이 채워진다. ⛔ 실측한 런은 라벨을 가진 코어 ETF 한 종목뿐이라 무해했고, 방향은 무해하지 않다 — 캡이 적용되지 않은 축은 브리치가 그대로 통과하는 축이고, 섹터 캡은 개별주가 여럿 들어온 북에서만 구속한다. 정규화가 아니라 거절을 골랐다: 틀린 철자를 쓴 호출자는 다른 자리에도 그렇게 썼고, 조용히 고쳐 읽으면 두 철자가 둘 다 살아 있으면서 어느 쪽이 뜻이었는지 말하는 것이 아무것도 없다. 같은 침묵의 나머지 절반: 투자자가 실제로 선언한 캡이 라벨 없는 행 위에 서면, 아무도 선언하지 않은 캡과 똑같은 빈 맵이 나왔다. 이제 그것은 concentration_labels_unstated / unevaluated이고 종목과 무게를 이름 댄다 — ⛔ blocked가 아니다: 이 패키지는 라벨을 스스로 하나도 선언하지 않으므로, 라벨의 부재로 북을 거절하는 것은 분류를 지어내는 일이다. 행 형태는 inputContracts.nested.concentration에 게시된다 — 전에는 caps만 말했다.
그리고 지불할 수 없는 예산은 「예산 내」가 아니다. specialistBudget은 포트폴리오 비중 둘을 비교해 withinBriefBudget을 답했고, 통화가 둘인 북에서 그것은 슬리브가 물은 질문이 아니다. 실측한 호출 — us-sleeve·XNYS·현재 0.11370454·브리프 예산 0.26488897 — 은 allowed: true, withinBriefBudget: true, 진단 0건으로 돌아왔는데, 그 예산 ≈ USD 3,979에 대해 이 북이 든 유휴 달러는 USD 294.02였다. 차액은 원화를 환전하거나 KR 자산을 팔아야만 존재한다. 가린 것은 집계값이다: portfolio_read의 cash가 USD 8,596.10이었고 그중 96.6%가 원화였으며, 서 있던 allocate 플랜은 존재하지 않는 "유휴 USD 8,514.73"에 대해 투자자에게 묻고 있었다. 통화는 예산이 아니라 현금에 붙였다: 비율로 표현된 한도에는 통화가 없다 — 하나의 FX가 분자와 분모를 같은 배율로 스케일하기 때문이고, 호스트가 바로 옆 질문에서 그것을 이미 정했다(aumos#689). 통화를 갖는 것은 레벨이고 조달은 레벨이다. 그래서 조달 통화는 시장에서 유도되고(XKRX → KRW, XNAS·XNYS → USD) 호출자가 선언하지 않으며, 현금은 portfolio.cashByCurrency에서 통화별로 읽고, 환율은 portfolio.fxRates이며 답이 그 출처를 이름 댄다 — 이 패키지는 환율을 스스로 소싱하지 않는다. ⚠️ 조달 불가는 경고다: 환전도 다른 슬리브 매도도 합법적 선택지이고, 둘 다 allocate의 판정이자 투자자의 승인 사항이다. ⛔ 허용되지 않는 것은 침묵이다 — 조달 입력이 없는 호출은 이제 기다리는 키를 이름 대는 sleeve_budget_fundability_unevaluated / unevaluated이고 budgetFundableInSleeveCurrency가 withinBriefBudget 옆에서 null이다. 전에는 status: ok와 빈 진단 배열이었다.
그리고 그 판정은 참이 될 수 없었다. (#250) 결함 둘이고, 각각 하나만으로도 조달 판정을 쓸모없게 만들기에 충분했다. sleeveCashByCurrency가 지불 재원의 유일한 분자였으므로, 자기 통화의 파킹 유동성으로 필요액을 전부 조달할 수 있는 슬리브 — 단기채·T-bill 보유, #141부터 집중도 축에서 이미 parkedLiquidity: true를 달고 있던 그 행들 — 이 매 런 budgetFundableInSleeveCurrency: false를 받았고, 그것이 네 런 연속이었다. 확정한 측정: 예산을 조달 가능액에 맞춰 내려 적고 다시 호출하면 「부족분」이 그 슬리브 자신의 파킹 시가와 센트까지 일치한다. 돈은 있었고 조달 경로는 환전이 아니라 한 통화 안에서 파킹을 파는 것이었다. 이제 sleeveParkedLiquidity를 통화별로 읽어 분자에 넣고, 답은 fundableFromCash와 fundableFromParking을 분리해서 싣는다 — 파킹을 파는 것은 제안이 필요한 행위이고 현금을 드는 것은 아니므로, 합산만 하면 앞의 것을 뒤의 것으로 값매기게 된다. fundingRoute가 넷 중 무엇인지 이름 댄다: cash · sell-parking-same-currency · fx-conversion · cross-market-sale. 뒤의 둘은 그대로 allocate와 투자자의 것이고, 둘째는 그 슬리브 자신의 것이다. 나머지 절반은 산술이었다. 비교가 비중 공간에서 1e-9 입실론에 대고 이뤄지는데 답은 센트로 인쇄됐고, 이 런들의 모든 비중은 소수 여덟 자리로 적히므로 그 관용의 다섯 배까지 반올림 오차를 나른다. 통제 1회: requiredAmount 294.02 · fundableAmount 294.02 · shortfallAmount 0, 그리고 budgetFundableInSleeveCurrency: false와 함께 코드 발화. 어떤 예산값도 이 코드를 조용히 통과할 수 없었고, 그래서 mandateExecution이 이 플로우의 매 런마다 미해소 코드 1건을 만들어 냈다. 판정은 이제 인쇄되는 부족분으로 정한다 — 답이 게시하는 그 숫자의 <= 0 — 그래서 둘이 어긋날 수 없고, 고침은 더 넓은 관용이 아니라 답이 말해지는 자리에서 하는 비교다.
형태가 유효하고 반대 질문에 답한 입력이 둘 있었다. (#251) 한 런에서 함정 넷을 밟았고, 둘은 정직하게 거부됐고 둘은 확신에 찬 반대 답으로 돌아왔다. concentration의 캡은 다섯이고 그중 둘만 Mandate의 것이므로, 한 런이 나머지 셋을 자기 설정이 그것을 선언하는 자리 — config — 에 넣고 concentration_cap_missing / unevaluated를 세 번 받았다. ⛔ unevaluated는 통과가 아닌데 그 답은 통과처럼 읽힌다: breaches는 비어 있고 exposures는 채워져 나오므로 측정되지 않은 축 셋이 측정되고 통과한 것으로 보인다. 이제 그것은 concentration_caps_misplaced / blocked이고 틀린 자리 둘을 함께 이름 댄다 — config의 최상위, 그리고 설정 블록을 그대로 넘긴 config.concentration — 그리고 unmeasuredAxes가 어느 축을 측정하지 않았는지를 답이 스스로 말한다. 그리고 specialistBudget의 요청 비중은 증분처럼 읽히는 이름 아래의 슬리브 총량이었다: 0.31471199에 서 있던 슬리브가 새 3% 종목을 담으려고 0.03을 넘겼고, 그것이 이 슬리브를 3%로 줄여라로 읽혀 increaseWeight: −0.28471199 · allowed: true · 진단 0건으로 돌아왔다 — 같은 런에서 슬리브 플로우와 allocate가 독립적으로 두 번 밟았다. 키는 requestedSleeveTotalWeight이고, 은퇴한 철자는 이름으로 거절되며 ⛔ 새 키로 읽지 않는다: 별칭으로 두면 같은 반대 질문에 계속 답하게 된다. executionRecord는 data의 non-null을 읽고 있었고 rows[].evaluated는 아무도 읽지 않았으며, 그것이 「적격 25종」 옆에 「아무것도 평가되지 않음」이라는 기록을 게시했다. 이제 두 필드 어느 쪽으로도 정해지고, 둘 다 말하지 않은 행은 아무것도 찾지 못한 답으로 세는 대신 이름으로 말해진다.
답처럼 보이는 오답 넷이 더 있었다. (#177) 이 패키지가 가장 자주 기록하는 패턴 — 틀린 입력이 거절되지 않고 통과처럼 돌아온다 — 을 한 런에서 넷 더 쟀고, 가장 비싼 것은 1,338.848배 틀린 NAV였다. sleeveNav는 포지션 행의 currency를 두 사실로 동시에 읽고 있었다: 이 이름이 어느 슬리브의 것인가, 그리고 marketValue가 어느 단위로 세어졌는가. 호스트의 portfolio_read는 모든 보유를 북의 기준통화로 마크하므로 USD 북의 KRW 종목은 옆에 valueCurrency: "USD"를 달고 달러 숫자로 도착한다 — 이 연산이 읽지 않던 키이고, named 모드의 미지 키 보고가 행 안은 보지 못하는 자리다. USD 4,717.16이 액면 그대로 원화 버킷에 들어갔다: krwSleeveNav가 참값 17,430,791.23에 대해 11,119,948.16, status: ok, 진단 0건. 이제 철자를 추측하는 대신 두 사실을 가른다 — currency는 자산이 호가되는 통화 그대로이고, valueCurrency가 마크의 단위를 말하며, 이 패키지가 건네받은 환율로 환산된다 (aumos#689, #174가 바로 옆에서 정한 같은 규칙). marketValueBasis가 어느 읽기였는지를, fxUsed/fxBasis가 환율의 출처를 말한다. ⛔ 자기 슬리브의 통화로 옮길 수 없는 행은 액면으로 더해지지 않고 빠지며 이름이 불린다. 나머지 셋은 한 모양이다 — 연산이 읽지 않는 필드에 판정으로 답한 것. validateMacro의 행은 metric이 아니라 **indicator**로 키가 잡히고, 그 kebab-case 열 개는 inputContracts.vocabulary가 게시하지 않던 유일한 닫힌 어휘였다. metric으로 쓰면 모든 행이 unusable이 되고 macroLaneAvailable이 false로 돌아오는데, 그것은 정책 레인이 비었다로 읽힌다. thesisSentinel은 level과 비교하고 value/availableAt을 읽는다 — threshold와 observed/observedAt으로 쓰면, 등록된 무효화 조건을 20% 뚫은 가격이 자기 증거와 조인되고도 "Rule and evidence are not comparable"로 돌아와 판정이 threatened가 아니라 watch가 됐다. 그리고 specialistBudget의 managerId는 리터럴 evidence-gated다 — 호스트의 다른 모든 면이 이 매니저를 부르는 그 id, 자기 inst_…를 넘긴 런은 managerId: "string"만 말하는 계약 앞에서 호출 전체를 거절당했다. 넷 다 이제 버려지지 않고 input_shape_invalid이며, 넷의 형태가 모두 게시된다.
권한의 이름과 도구의 이름은 두 어휘이고, 이 문단은 그 둘을 섞고 있었다. 여기에는 thesis:read와 evidence:read에 대해 "선언된 권한 둘은 현재 아무것도 서빙하지 않는다"라고 적혀 있었고, 그것이 참이 아니게 됐다: 둘은 서빙되며 이 패키지가 한 번도 쓴 적 없는 철자로 나온다 — thesis_list/thesis_get과 evidence_get/evidence_search. ⛔ 어느 빌드도 서빙한 적 없는 것은 thesis_read와 evidence_read이고, 그것은 권한이 아니라 이름이었다. 매니페스트가 원하는 도구를 optionalSkills에 적는 이유가 그것이며, 세션이 서빙된 짝을 쥐지 못한 곳에서 자산 주장은 invocation 페이로드와 장부의 공유 폴더로 실행에 닿는다 — 패키지는 하지 못하는 조회를 하는 척하는 대신 그렇게 말한다.
페이퍼 트랙은 이 인스턴스 자기 사설 폴더에 산다 — 담을 수 있는 곳이 그것뿐이기 때문이다. 페이퍼 콜은 주문도 체결도 없으므로 Decision이 아니다. 결과 둘이 따라오고 어느 쪽도 숨기지 않는다: 같은 장부의 다른 매니저는 이 증거를 볼 수 없고, 새 매니저 인스턴스는 트랙을 처음부터 다시 시작한다. 공유 기록이 옳은 집이지만, 런타임이 서빙하는 것은 이것이다. 처음부터 다시 시작하게 만들지 않는 것: 모델 교체, config 편집, 제자리 패키지 업데이트 — 폴더의 키가 매니저 인스턴스 하나라서 d60 창은 셋을 전부 넘겨 살아남고, 되돌리는 것은 매니저 삭제뿐이다.
이 매니저가 기억하는 것은 이제 폴더이고, 공짜로 받던 것 셋은 자기가 지켜야 한다. untilled/aumos#743이 memory_read/memory_write와 brief_read/brief_write를 지우고 폴더 둘로 바꿨다: files_list/files_read/files_write로 읽고 쓰는 이 인스턴스의 사설 폴더, 그리고 Brief였던 것 — 장부의 공유 폴더 — 를 fund_files_* 여섯으로. ⚠️ 투자자가 고른 것은 하나도 움직이지 않았다: 같은 이름의 같은 기록, 같은 격리, 같은 소유 구분, 그리고 거기에 숨은 포트폴리오 DB를 두지 않는다는 같은 거절. 움직인 것은 그 보장을 누가 지키느냐다. 쓰기는 revision을 덧붙였고 잃을 것이 없었다. 파일은 덮이므로, 앞의 값이 계속 읽혀야 하는 자리에서는 이 패키지가 현재 파일 옆에 날짜가 붙은 파일을 쓴다. 읽기는 그 실행의 asOf에 보이던 최신 revision을 답했다. 이제는 디스크에 있는 바이트를 답하므로 값 자신의 updatedAsOf가 시점을 말하는 유일한 신호이고, 과거 replay는 그 실행을 위해 얼려 둔 스냅샷만 읽을 수 있다. 그리고 두 필자를 갈라 두던 것이 append였는데, 이제는 읽은 해시에 대한 비교-교환이다. 그래서 engines.aumos는 >=0.4.0을 요구한다. ⚠️ 이 하한은 앞의 다섯과 다르다. 그것들은 더 낮은 빌드가 모르는 권한이 매니페스트를 통째로 거부하게 만들기 때문에 올랐고, 그때 이 패키지는 그 빌드의 카탈로그에서 아무도 모르게 빠진다. 여기서는 권한이 하나도 움직이지 않았다 — 이미 선언해 둔 권한 뒤의 도구가 개명된 것이다 — 그래서 더 낮은 빌드는 아무것도 거부하지 않는다: 아무도 부르지 않는 도구 이름으로 된 grant를 서빙하고, 실행은 그것들을 부재로 보고하며 피할 수 있었던 WAIT을 제출한다. 거부보다 조용하고, 그것이 이 하한을 운에 맡기지 않고 적어 두는 이유다. ⛔ 이 패키지는 자기 옛 기록을 스스로 옮기지 않는다 — 그것은 Aumos가 호스트 쪽에서 한 번 내보내는 일이고, 패키지까지 쓰면 자기 것이 아닌 경로를 놓고 첫 필자와 경주하는 두 번째 필자가 된다.
출처. 매니페스트에 기록된 커밋의 morethanmin/trading-harness에서 이식했다. 자격증명, 계좌나 포지션 데이터, 캐시, 백업, 개인 thesis 텍스트, 주문 구현, 과거 성과는 넘어오지 않았다. 원본 하네스의 과거 결과는 Aumos 포워드 트랙레코드가 아니고, 이 패키지는 그것을 트랙레코드로 주장하지 않는다. 저작자 표시는 NOTICE.md에 있다.
Aumos는 이 패키지가 실적을 쌓기 전까지 어떤 수익률도 보여주지 않는다. 포워드 트랙레코드는 연산이 아니라 달력 시간을 요구하고, 이 페이지의 어떤 것도 트랙레코드가 아니다.