Skip to content

Make the acts legal text is about into nodes - #41

Merged
tamnd merged 1 commit into
mainfrom
feat/m16-events
Aug 4, 2026
Merged

Make the acts legal text is about into nodes#41
tamnd merged 1 commit into
mainfrom
feat/m16-events

Conversation

@tamnd

@tamnd tamnd commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Closes #36.

The norm layer carries the act a provision is about in a slot, and the slot is a string that points at nothing. This puts the acts themselves into the graph, connects them to the concepts that take part in them, and connects them to each other, so a consequence can be walked instead of read.

What is here

An act is a class from a closed registry of eighteen and a short Vietnamese label, and the identifier is built from both, so the same act named in a law and in the decree that guides it is one node without anybody matching strings afterwards. Four chain types: one act triggers another, comes before it, is a precondition of it, or rules it out.

The provision level read returns the acts a clause names, their parties drawn from the concepts already linked to that provision, the chains the clause itself states, and which act each trusted norm is about. Nothing is invented from a label match: the norm links are written while one provision is in view, which is what stops trả lương in a labour code from being joined to trả lương in a tax decree.

Every chain is read a second time by a model that sees the two acts and the sentence and never sees which way the first pass pointed the arrow. The verdict is stored beside the chain instead of replacing it.

Three new competency questions, 24 to 26, in both the layer and the projection, with fixture tests: what follows from an act, which acts carry a penalty and which provision attaches it, and which acts more than one instrument names.

What the run produced

195 provisions over 5 documents in the labour campaign, 427 sightings folded into 362 acts, 100 chains and 247 norm links. The blind reading agreed with 88 of the 90 chains it would commit to and flipped 2.

Sixty provisions were annotated by hand before the pass ran over them. Against them the pass scores 0.35 precision and 0.47 recall on acts, 0.65 on the class of a matched act, and 0.55 precision and 0.60 recall on saying a provision names no act. Chains score one match against 21 missed. Acts are matched on the label alone and that ruler is strict: 23 of the 53 misses have an act on the same provision whose label contains the annotated one or is contained by it. The ruler was written and shipped before the run, and it stays as it is.

What did not work

The extractor demanded byte offsets into the provision text. Both real documents failed on their first provision, twice each, and the pass produced nothing until the offsets were computed from the text instead. The quote still has to appear word for word, which is the check that matters.

The ablation is negative and it is the result the issue asked for. No act in this campaign is named in more than one instrument, so corpus wide identity merged nothing and changed no answer. The scope produced no sanction link at all, so the penalty join has nothing to join. Both are real numbers about two instruments on two different subjects.

Participants are zero because the concept layer has no mention report for either instrument, so the pass was offered no concepts. The role edges are built and tested in the projection and unmeasured on this campaign.

191 of the 362 acts carry a class the registry does not hold. They are in the candidates queue with their evidence, which is where the design said they would go.

Gate

gofmt, go vet, golangci-lint at 0 issues, go test -race across the tree. Event package coverage 90.2 percent.

The norm layer puts the act a provision is about into a slot and that slot
is a string, so the graph cannot walk from an act to what follows from it.
This adds the act layer: a closed class registry, a provision level read
that returns the acts a clause names with their parties and the chains
between them, a corpus wide fold, a blind second reading of every chain,
and three competency questions that walk consequences.

The quote offsets are computed from the provision text instead of being
demanded from the model. The first real run lost two whole documents to
that demand and every quote it refused was in the paragraph it came from.

The gold slice was annotated before the pass ran, and the numbers it
produced are in the README with what they do not cover.
@tamnd
tamnd merged commit 176ec4b into main Aug 4, 2026
5 checks passed
@tamnd
tamnd deleted the feat/m16-events branch August 4, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

M16: Events as first class, entity to event and event to event

1 participant