Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Implements #70: fabric drift reports card-vs-source edge divergence as a fourth finding class

Đang mở
#72 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
35/100
Loại issue
Tính năng
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python, shell
Lĩnh vực
cli, tooling

Hướng nghiên cứu

Read the fw fabric drift implementation and enrich.py, especially compute_forward_edges, detect_raw_edges() and report_divergence(). Run the drift and divergence tests, including the direct --report-divergence count cross-check. Done means drift reports divergent edges with the specified truncation and summary, handles detector failures as UNKNOWN, and does not gate on findings.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Context

  • Framework version: 1.6.258
  • Project: 050-email-archive (shared-tooling mode)
  • Reported: 2026-09-25T08:39:47Z

Description

Follow-up to #70, which this implements. Also depends on the detector fix in #71.

The blindness

fw fabric drift has three finding sections and all three start from what the cards say:

  • unregistered — is there a file with no card?
  • orphaned — is there a card with no file?
  • stale — does an edge a card declares still resolve on disk?

None of them ever asks the converse: does the declared edge set still match what the source
actually imports?
So a card can name one edge out of ten and drift reports clean forever.

What that cost on the consumer project (#70): a commit moved four services into legacy/ as pure
renames and updated no require path. Three archive import entry points threw MODULE_NOT_FOUND
for 185 days. All three had cards with edges — none naming the importer that broke — and
every declared target still existed, so stale stayed 0 and drift stayed green the whole time.

The fix — a fourth section, Divergent cards (card vs source)

Divergent cards (card vs source):
  ! scripts/some-script.js → missing: src/database/models/index.js
  … 160 more (full list: bin/fw fabric drift --divergence-full)
  (informational: 14 card edge(s) the detectors cannot see; 37 detected import(s) whose target has no card)

Summary: unregistered: 0, orphaned: 0, stale: 0, divergent: 180 (193 edge(s))

Three design choices worth stating, since #70 left them open:

  1. Direction is split. The headline divergent count is only the dangerous direction —
    the source imports a target the card does not declare. The reverse (a card declares an edge
    the detectors did not find) is usually a legitimately hand-authored edge, so it is reported as
    an informational count and deliberately not folded into the headline number. Edge types the
    detectors cannot emit (writes, writes_data, reads of a runtime artifact) are excluded
    entirely rather than counted as noise.
  2. It reports, it does not gate. do_drift still returns 0 on findings, exactly as the
    existing three sections do. On a mature project this section opens at 180 findings, and a gate
    that starts red is a gate people learn to ignore. Whether it should later become a ratchet on a
    coverage percentage is left as a policy decision, not baked in here.
  3. The per-card list is truncated to 20 with --divergence-full to un-truncate. The counts are
    always exact; only the enumeration is capped, and it says so. At 180 findings an unabridged list
    buries sections 1-3.

Detection is delegated, not duplicated

enrich.py gained --report-divergence (read-only) and report_divergence(). The per-filetype
detector dispatch was extracted out of compute_forward_edges into detect_raw_edges(), so the
write path (enrich) and the read path (drift) now share one definition of "what counts as an
import."
Two copies would be free to disagree, and a drift report that disagrees with the
enricher is worse than no report — it sends readers to fix edges the enricher then refuses to
write, or stays silent on edges the enricher would add.

--report-divergence returns before any filtering or write path, so "this flag cannot write" is a
property of the control flow rather than a promise in the help text.

Two failure modes that were easy to get wrong

Both of these were found by negative-controlling the change rather than by review:

  1. A failing detector must not read as a clean one. First version used a bare
    _div_raw=$(python3 ... ). Under set -e a failing command substitution in an assignment
    aborts the function — drift printed the section header and then simply stopped, mid-report.
    Worse, without capturing rc, "the detector could not run" is indistinguishable from "the
    detector found nothing", and divergent: 0 on a broken reader is precisely the failure this
    section exists to abolish. Now:
    _div_raw=$(PROJECT_ROOT="$PROJECT_ROOT" python3 "$LIB_DIR/enrich.py" \
        --report-divergence 2>/dev/null) || _div_rc=$?
    if [ "$_div_rc" -ne 0 ] || ! grep -q '^##DIVERGENT_CARDS=' <<< "$_div_raw"; then
        echo "  ? UNKNOWN — the divergence detector did not run ..."
        # ... Summary prints "divergent: UNKNOWN (detector failed)"
  1. The shape tests were satisfiable by a broken wiring. Asserting only that the section and
    the divergent: term exist passes when the count is a wrong 0. The guard therefore also
    cross-checks drift's count against enrich.py --report-divergence invoked directly, and
    asserts the oracle is non-zero so the cross-check cannot pass vacuously.

Compatibility

The existing Summary: line is extended, not restructured — unregistered: N, orphaned: N, stale: N survive verbatim, with , divergent: N (M edge(s)) appended. --summary gains
divergent: and divergent_edges: lines. The consumer's existing drift-determinism suite
(which parses the Unregistered section and stops at the first blank line) passes unchanged.

Cost: drift goes from ~7s to ~8s on 724 cards — one extra pass reading each card's source.


Reported via fw upstream report from field installation

Ngôn ngữ chính
Shell
Star
16
Fork
6
Merge trung bình
6 giờ 24 phút
Pull request đã merge (30 ngày)
5

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của DimitriGeelen/agentic-engineering-framework

Tất cả issue của DimitriGeelen/agentic-engineering-framework

Issue tương tự

Thêm issue về Shell/Bash

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.