روی لپتاپ توسعهدهنده ۷۲ Check از ۷۲ Check سبز است. همان Commit با Tag ظاهراً یکسان در محیط تست اجرا میشود؛ هر شش Container هم «Running» هستند، اما Callback سفارش تکراری میشود. کدام طرف درست میگوید؟ پاسخ حرفهای «ماشین من» یا «محیط شما» نیست. باید دو اجرای مشخص را با Build و Artifact ثابت، Environment Fingerprint قابلمقایسه، Deltaهای رتبهبندیشده و آزمایش کنترلشده بررسی کرد.
این راهنما برای جستوجوی «روی ماشین من کار میکند» یک خروجی عملی میدهد: Environment Delta Reproduction Protocol. این پروتکل Observation را از تفسیر جدا میکند، تفاوت محیط را به فرضیهی علّی تبدیل نمیکند، یک متغیر را در هر آزمایش تغییر میدهد و نتیجه را با Evidence Manifest به تصمیم بعدی میرساند.
پاسخ کوتاه: «روی ماشین من کار میکند» یعنی چه؟
این جمله فقط یک Observation محدود به یک Run است: یک Subject مشخص، با یک Build مشخص، در یک Environment و State مشخص، در زمانی مشخص، نتیجهی مورد انتظار را داده است. این مشاهده نه Failure محیط دیگر را باطل میکند، نه اثبات میکند دو طرف همان Artifact را اجرا کردهاند، نه علت اختلاف را نشان میدهد.
| عبارت | آنچه واقعاً میدانیم | آنچه هنوز نمیدانیم |
|---|---|---|
| «اینجا Pass شد» | یک Attempt در Context گزارششده Pass شده | تکرارپذیری، Artifact یکسان و نمایندگی Context |
| «آنجا Fail شد» | یک Failure در Target مشاهده شده | Defect محصول، محیط، Testware یا Expected variance |
| «نسخه یکی است» | احتمالاً Label یا Commit برابر است | بایتهای Artifact، Build provenance و Runtime inputs |
| «Containerها بالا هستند» | Processها احتمالاً Running هستند | Readiness، Dependency، Data، Oracle و رفتار درست |
مالکیت این مقاله و مرز با راهنماهای نزدیک
اگر هدف شما طراحی Cloud/Container/IaC و Fidelity است، معماری محیط تست مدرن را بخوانید. برای تحویل و Readyکردن یک محیط، چکلیست راهاندازی Test Environment مالک موضوع است. برای عیبیابی فرمانهای Compose، لَب Docker Compose برای تسترها و برای ساخت خود Report، گزارش باگ قابل بازتولید را ببینید. این صفحه فقط فاصلهی بین دو Run ناسازگار را مدیریت میکند.
| مسئله | مالک | خروجی |
|---|---|---|
| چه محیطی بسازیم؟ | Environment Architecture/Setup | Environment Contract و Readiness |
| چگونه Failure را گزارش کنیم؟ | Bug Report | Reproduction Contract و Evidence |
| چرا دو Run فرق دارند؟ | همین مقاله | Fingerprint، Delta، Experiment و Disposition |
| چگونه Pipeline را پیاده کنیم؟ | CI/CD Guide | Pipeline، Artifact و Run Manifest |
اصل اول: Run را مقایسه کنید، نه آدمها و ماشینها را
«ماشین توسعهدهنده» یک هویت فنی نیست. لپتاپ ممکن است میان دو Attempt آپدیت شود، Cache بماند، Flag تغییر کند یا Dependency بیرونی پاسخ دیگری بدهد. واحد مقایسه باید Source Run و Target Run باشد؛ هرکدام با شناسه، زمان، Build، Artifact، Test، Data و Environment Snapshot.
- Source Run لزوماً «درست» یا Baseline معتبر نیست؛ فقط Control پیشنهادی است.
- Target Run لزوماً «خراب» نیست؛ فقط Witness Failure است.
- Developer، Tester و Ops نقش Evidence Producer دارند، نه متهم.
- نتیجهی یک Attempt را به همهی Buildها، دادهها یا کاربران تعمیم ندهید.
- Clock، Locale و Feature Flag بخشی از Context هستند، نه حاشیهی گزارش.
Observation، Interpretation، Hypothesis و Cause را جدا کنید
| نوع | نمونهی سالم | خطای رایج |
|---|---|---|
| Observation | در RUN-T-۲۹، Event دوم HTTP ۲۰۰ گرفت و دو Ledger entry دیده شد | «محیط تست مشکل دارد» |
| Interpretation | Oracle ثبت دو Entry را خلاف قاعدهی Idempotency میداند | تبدیل برداشت به واقعیت خام |
| Hypothesis | Flag متفاوت ممکن است مسیر Dedup را غیرفعال کرده باشد | اعلام Root cause پیش از آزمایش |
| Cause claim | فقط پس از Intervention و Controlهای کافی | نسبتدادن هر Delta به Failure |
زنجیرهی هویت را پیش از Debug ثابت کنید
مقایسهی دو Environment بدون Identity Chain به حدس تبدیل میشود. نام نسخه برای انسان مفید است، اما شناسهی کافی نیست. Repository/Commit باید به Build، Build به Artifact digest، Artifact به Release/Deployment و هر Deployment به Environment/Run متصل شود.
Program/Product → Repository/Commit → Build/Provenance → Artifact/Digest → Release/Deployment → Environment/Fingerprint → Test/Data/Oracle → Run/Attempt → Observation/Evidence
در OCI، Digest یک Content identifier مبتنی بر Hash برای بایتهای محتوا است؛ مرجع فنی: OCI Image Descriptor. این ویژگی برای تشخیص Artifact بسیار مهم است، اما برابری Digest بهتنهایی Config، Secret reference، Data، DNS، Kernel، Clock یا Dependency خارجی را برابر نمیکند.
Commit، Version، Tag و Digest یک چیز نیستند
| شناسه | چه چیزی را نام میدهد؟ | محدودیت |
|---|---|---|
| Commit ID | Snapshot کد در Repository | Build inputهای بیرونی یا بایت خروجی را کامل نمیگوید |
| Version/Release label | نام قراردادی برای انسان و فرایند | ممکن است بازاستفاده یا اشتباه برچسبگذاری شود |
| Image tag | Reference قابلخواندن | میتواند به Manifest دیگری حرکت کند |
| Artifact digest | هویت محتوایی Artifact | رفتار Runtime و ورودیهای بیرونی را تضمین نمیکند |
| Deployment ID | عمل استقرار مشخص | بدون Manifest نمیگوید چه چیز مستقر شد |
Docker نیز Pinکردن Base image با digest را برای Build reproducible توصیه میکند؛ نمونهی Policy رسمی در Docker Build Policies آمده است. «Reproducible build» در این Context را با «رفتار یکسان در هر Environment» یکی نگیرید.
Build Provenance چه چیزی میدهد و چه چیزی نمیدهد؟
Provenance میتواند Builder، ورودیها، پارامترها و فرایند تولید Artifact را قابلردیابی کند. SLSA آن را اطلاعات قابلتأیید دربارهی محل، زمان و چگونگی تولید Artifact تعریف میکند؛ مرجع: SLSA Provenance. Provenance قوی، سؤال «این Artifact از کجا آمد؟» را بهتر پاسخ میدهد؛ سؤال «چرا این Run Fail شد؟» همچنان به Runtime Fingerprint و Evidence نیاز دارد.
Build Identity buildId: BUILD-SYN-29 commitId: abc1234 builderId: BUILDER-SYN-29 artifactDigest: sha256:synthetic29 baseImageDigest: sha256:base-synthetic29 dependencyLockDigest: sha256:lock-synthetic29 provenanceRef: PROV-SYN-29
Environment Fingerprint چیست؟
Fingerprint یک Snapshot نسخهدار و کمینه از ویژگیهایی است که ممکن است برای Quality Question حاضر معنا داشته باشند. هدف آن Dumpکردن کل سیستم نیست. هر Field باید نام، نوع، روش جمعآوری، زمان، حساسیت، Redaction و نسخهی Collector داشته باشد. مقدار Secret را ثبت نکنید؛ فقط Reference/version یا Digest ایمن را، اگر Policy اجازه میدهد، نگه دارید.
EnvironmentFingerprint {
environmentId, capturedAt, collectorVersion,
os, kernel, architecture, runtime,
imageDigest, entrypoint, dependencyLockDigest,
configSchemaVersion, configKeySetDigest, featureFlagSnapshot,
locale, timezone, clockSource,
networkPolicy, dnsView, dependencyEndpointSet,
dataSnapshotId, schemaVersion,
redactionPolicy, digest
}
ابعاد Fingerprint را بر اساس سؤال انتخاب کنید
| بُعد | نمونه Field | چه Failureهایی را توضیح نمیدهد؟ |
|---|---|---|
| Artifact | image/artifact digest، entrypoint | Data و Dependency بیرونی |
| Platform | OS، Kernel، Arch، Runtime | Feature behavior ناشی از Config |
| Config | Schema، Key-set digest، Flag snapshot | State پنهان در DB/Cache |
| Time/Locale | Timezone، Clock source، Locale | Network partition |
| Network | DNS view، Proxy policy، endpoint set | محتوای پاسخ Dependency |
| Data/State | Snapshot ID، Schema، Seed lineage | Race غیرقطعی |
| Observability | Trace sampling، log schema، metric version | رفتار واقعی اگر Instrumentation ناقص باشد |
Config را بدون افشای Secret مقایسه کنید
Copyکردن `.env` یا الصاق کامل Configuration به Ticket ممکن است Credential، Token یا دادهی حساس را منتشر کند. برای مقایسه، ابتدا Schema و Set کلیدها، منبع Resolution، Version و Presence را بسنجید؛ مقدارهای حساس باید با سیاست مشخص Redact شوند. Equality یک Hash هم فقط Equality ورودی Canonicalشده را نشان میدهد، نه مناسببودن مقدار.
| Field | قابل ثبت | نباید ثبت شود |
|---|---|---|
| DB credential | secretRef + version + resolved/present | Password یا Connection string کامل |
| Feature flag | نام غیرحساس، Variant، snapshot ID | Rule حاوی شناسهی کاربر واقعی |
| Endpoint | Service alias و Contract version | Token یا Query حساس |
| Config set | Canonical key-set digest | Dump بیمرز همهی Environment variables |
Data و State معمولاً Delta پنهاناند
Database schema برابر، State برابر نیست. Seed، Migration history، Cache، Queue backlog، Object storage، Search index، Session و Clock-dependent record میتوانند رفتار را تغییر دهند. برای طراحی Data امن و نماینده، راهنمای دادهی تست واقعی یا مصنوعی را ببینید. Production data پیشفرض یا شرط بازتولید نیست.
- Data snapshot را با ID، Schema، Seed و زمان Freeze معرفی کنید.
- State reset را بخشی از Procedure بدانید، نه کار شفاهی قبل از تست.
- Queue و Cache را بدون ثبت Evidence پاک نکنید؛ ممکن است Witness را نابود کند.
- برای Race، Attemptهای متعدد و Timeline لازم است.
- کمینهسازی داده باید Invariantهای لازم برای Failure را حفظ کند.
Time، Timezone، Locale و Encoding را جدی بگیرید
در نرمافزار فارسی، UTC instant، نمایش Asia/Tehran، تاریخ جلالی نمایشی، ارقام فارسی/عربی/لاتین، جداکنندهی هزارگان، IRR در برابر نمایش تومان، Unicode normalization و RTL/LTR میتوانند مسیرهای متفاوتی بسازند. تاریخ جلالی را Source of truth زمانی نکنید؛ Instant و Offset را جدا ذخیره کنید. تومان را Currency code جا نزنید؛ اگر فقط نمایش است، صریح برچسب بزنید.
Canonical test value (fictional) instant: 2026-08-13T03:30:00Z viewTimezone: Asia/Tehran presentationCalendar: jalali-only currency: IRR displayUnit: toman-labelled-view digitsUnderTest: Persian | Arabic | Latin unicodeNormalization: NFC
Network فقط «وصل/قطع» نیست
DNS answer، Proxy، TLS trust، MTU، Latency، Packet loss، Retry، Connection pooling، IPv4/IPv6، Service discovery و Endpoint contract ممکن است فرق کنند. Reachableبودن یک Port رفتار Dependency را ثابت نمیکند. برای هر Dependency، Endpoint identity، Contract/version، Stub یا real-service بودن، Failure mode و Observation point را ثبت کنید.
| Check سطحی | نتیجهی محدود | Check رفتاری |
|---|---|---|
| TCP connect شد | یک مسیر شبکه باز است | Request/response contract + timeout/retry |
| DNS resolve شد | یک Answer دریافت شد | Answer set/TTL/route در دو Run |
| Health ۲۰۰ است | Health handler پاسخ داده | Dependency readiness و مسیر واقعی سؤال |
| Service version برابر است | Label برابر گزارش شده | Artifact/Config/behavior Evidence |
Running، Ready، Healthy و Correct را قاطی نکنید
Process Running میتواند هنوز Migration را اجرا نکرده، Dependency را پیدا نکرده یا Cache را گرم نکرده باشد. Readiness هم فقط شرط تعریفشده برای پذیرش Traffic است. Healthyبودن یک Probe و Correctبودن Business behavior Claims جدا هستند. Pipeline باید هر Claim را با Oracle و Evidence خودش ثبت کند.
Environment Parity هدف مطلق نیست
یکسانکردن کامل Development، Test و Production ممکن نیست و همیشه مطلوب هم نیست. Production ممکن است Scale، داده، Identity، Policy و Dependencyهایی داشته باشد که بازتولیدشان در لپتاپ ناامن یا پرهزینه است. هدف، Fidelity کافی برای Claim حاضر و Deltaهای شناختهشده با Compensation است؛ نه کپی بیمرز Production.
| Delta | ممکن است پذیرفتنی باشد وقتی… | Compensation نمونه |
|---|---|---|
| Scale کوچکتر | سؤال Functionality محدود است | Performance evidence در بستر دیگر |
| Dependency Stub | Contract و Failure mode کافی است | Contract test + محدودیت Claim |
| Synthetic data | Invariantهای سؤال حفظ شدهاند | Data profile evidence |
| Architecture متفاوت | Binary/behavior وابسته نیست | Target-arch smoke check |
از Fingerprint به Environment Delta برسید
Delta خروجی Diff خام نیست. باید Field path، مقدار Source/Target یا Reference امن، طبقهبندی، ارتباط احتمالی با Question، Confidence، دلیل، Owner و آزمایش بعدی داشته باشد. نبودن Delta در Collector هم اثبات برابری نیست؛ ممکن است مدل Fingerprint ناقص باشد.
EnvironmentDelta {
deltaId, comparisonId, algorithmVersion,
leftFingerprintDigest, rightFingerprintDigest,
dimension, path, sourceValueRef, targetValueRef,
classification, relevance, rationale, confidence,
ownerCapability, nextExperiment, state,
supersedes, createdAt, digest
}
Taxonomy پیشنهادی Delta
| کلاس | معنا | اقدام اولیه |
|---|---|---|
| ARTIFACT_MISMATCH | بایت یا ورودی Build متفاوت | Freeze و بازاجرای همان Artifact |
| PLATFORM_VARIANCE | OS/Kernel/Arch/Runtime فرق دارد | Compatibility experiment |
| CONFIG_DRIFT | Schema/key/flag فرق دارد | یک Flag/Key در هر بار |
| DATA_STATE_VARIANCE | Seed/Schema/Cache/Queue فرق دارد | Reset و Snapshot کنترلشده |
| DEPENDENCY_VARIANCE | Endpoint/Contract/behavior فرق دارد | Stub/recorded response/control |
| TIME_LOCALE_VARIANCE | Clock/Timezone/Locale/Encoding فرق دارد | Freeze clock و canonical inputs |
| OBSERVABILITY_VARIANCE | فقط دید ما فرق دارد | همترازکردن Instrumentation |
| UNKNOWN_UNCOLLECTED | مدل فعلی توضیح نمیدهد | Collector را نسخهدار گسترش دهید |
Reproduction Contract برای دو محیط
Reproduction باید Witness Run معیوب و Control Run غیرمعیوب را با Build، Artifact، Procedure و Oracle ثابت جفت کند. اگر چند متغیر را همزمان تغییر دهید، نتیجه برای Isolation ضعیف میشود. Control هم تضمین Cause نیست؛ فقط Contrast میسازد.
EnvironmentReproduction {
reproductionId, frozenBuildId, frozenArtifactDigest,
sourceControlRun, targetWitnessRun,
procedureVersion, preconditions, trigger,
attemptIds, attemptCount, failureCount, controlCount,
isolationOrder, oneVariableRule, resetProcedure,
oracleId, evidenceManifestId, result,
unknowns, limitations, digest
}
Witness Run و Control Run چگونه طراحی شوند؟
| عنصر | Witness | Control |
|---|---|---|
| Artifact | همان digest ثابت | همان digest ثابت |
| Trigger | همان Event/Request canonical | همان Event/Request canonical |
| Oracle | همان version | همان version |
| State | Snapshot شناختهشده | Snapshot همارز یا Delta ثبتشده |
| Observation | Failure قابل زمانبندی | عدم Failure در Attempt مشخص |
| Evidence | Manifest و Timeline | Manifest و Timeline همساختار |
Isolation Order: از کمخطر و پرقدرت شروع کنید
- ابتدا Artifact identity و Procedure/Oracle را ثابت کنید.
- تفاوت Instrumentation را برطرف کنید تا دو Run قابلدیدن شوند.
- Config/Flag و Clock را با Change قابلبازگشت بررسی کنید.
- Data/Cache/Queue را با Snapshot و Reset آزمون کنید.
- Dependency response و Network conditions را کنترل کنید.
- Platform/Architecture را وقتی سؤال یا Evidence آن را محتمل میکند تغییر دهید.
- بعد از هر Intervention، Witness و Control تازه با Attempt ID بسازید.
این ترتیب Universal نیست؛ Risk و هزینهی تغییر مهماند. Secret، دادهی واقعی، Policy تولید یا سرویس بیرونی را برای سرعت آزمایش دور نزنید. اگر Intervention پرریسک است، به Environment امنتر یا Simulation منتقل شوید.
Minimal Reproduction و Delta Debugging
Minimal یعنی کوچکترین مجموعهی فعلاً شناختهشده برای حفظ Observation، نه «علت نهایی». هر بار یک Input، State یا Delta را حذف/جایگزین کنید و نتیجه را ثبت کنید. اگر Failure ناپدید شد، آن عامل Candidate میشود؛ Interaction، Order effect و Flakiness هنوز باید بررسی شوند.
| Experiment | Intervention | نتیجه | برداشت مجاز |
|---|---|---|---|
| E1 | فقط Timezone همتراز | Failure باقی ماند | Timezone تنها توضیح کافی نیست |
| E2 | Timezone Reset، فقط Flag همتراز | Failure حذف شد | Flag Candidate مرتبط است |
| E3 | Flag قبلی، مسیر Dedup مستقیم | Failure بازگشت | رابطه تقویت شد، Cause کامل هنوز Claim نمیشود |
| E4 | Attemptهای تکراری با Seed تازه | ۴/۵ Failure | نرخ و Unknown ثبت شود |
Evidence Manifest؛ بهجای انبوه Log
Evidence باید Subject و Run را پیدا کند، نه اینکه صرفاً حجم زیادی Attachment بسازد. Manifest بگوید هر شاهد برای کدام Build/Run/Environment/Delta است، چه زمانی و با کدام Collector گرفته شده، چه Redaction و Retention دارد و Digest آن چیست. Log کامل ممکن است Secret یا دادهی شخصی داشته باشد؛ کمینهسازی و دسترسی کنترلشده لازم است.
EvidenceManifest {
manifestId, subjectId, buildId,
sourceEnvironmentId, targetEnvironmentId,
sourceRunId, targetRunId,
fingerprintDigests[], deltaIds[],
timelineRef, traceRef, metricRef, logExcerptRef,
redactionPolicy, retention, access,
collectedAt, digest
}
Timeline و Clock uncertainty
برابر بودن Timestamp متن Log ترتیب قطعی رخدادها را ثابت نمیکند. Clock drift، buffering، async export و timezone conversion میتوانند Timeline را جابهجا نشان دهند. Event ID، parent/causal link، monotonic clock محلی، ingestion time و uncertainty را هرجا لازم است جدا کنید. Trace نیز ممکن است Sampling شده یا ناقص باشد.
Disposition: اختلاف را به چه تصمیمی ببریم؟
| Disposition | معنا | شرط خروج |
|---|---|---|
| PRODUCT_DEFECT | رفتار محصول خلاف Basis در Context معتبر | Fix/verification جداگانه |
| ENVIRONMENT_DEFECT | Environment Contract یا Readiness نقض شده | Repair + revalidation |
| TESTWARE_DEFECT | Test/Oracle/Harness مشکل دارد | اصلاح versioned + rerun |
| EXPECTED_VARIANCE | تفاوت مستند و پذیرفتهشده است | Rationale + claim limit |
| NEEDS_INFO | Evidence/Experiment کافی نیست | Missing item + owner + due |
| DEFER_WITH_EXPIRY | فعلاً اقدام نمیشود | Risk owner + expiry + resume trigger |
«Environment issue» مترادف «Not a bug» نیست. ممکن است Environment config خودش بخشی از Product delivery باشد. Authority تصمیم را از فردی که Evidence جمع کرده جدا و براساس Capability/Policy تعریف کنید.
Correction بهجای پاککردن نتیجهی قبلی
اگر بعداً معلوم شد Source Run Artifact دیگری داشته یا Collector یک Field را اشتباه خوانده، Record قبلی را بیصدا ویرایش نکنید. Correction با شناسهی تازه، رکورد Superseded، دلیل، Evidence تازه و Query تصمیمهای متاثر بسازید. این الگو با Freshness و Drift مستندات تست همراستا است.
CorrectionRecord {
correctionId, supersededRecordId,
reason, changedFields, newEvidenceRefs,
affectedDecisionQuery, ownerCapability,
publishedAt, acknowledgedBy,
priorDigest, newDigest
}
آزمایشگاه فارسی: Callback تکراری در Checkout خیالی
این Lab کاملاً ساختگی و از هر شرکت، PSP، بانک، کاربر، پرداخت یا سامانهی واقعی جداست. هیچ Network یا Production واقعی ندارد و توصیهی بانکی، مالی، حقوقی، مالیاتی، امنیتی یا حریم خصوصی ایران نیست. Entityهای خیالی شامل Order، PaymentAttempt، PSP Stub، Callback Event، Ledger Entry و Reconciliation Job هستند.
| شناسه | Control (DEV-SYN-29) | Witness (TEST-SYN-29) |
|---|---|---|
| Build/Artifact | BUILD-SYN-29 / sha256:synthetic29 | همان |
| Flag snapshot | FLAGSET-SYN-۲۹-A؛ reconciliation on | FLAGSET-SYN-۲۹-B؛ reconciliation off |
| Timezone | UTC | Asia/Tehran |
| Input | Callback تکراری EVT-SYN-۲۹ | همان canonical Event |
| Oracle | یک Ledger effect برای Event ID | همان ORACLE-IDEMP-SYN-۲۹ |
| Result | یک effect | دو effect در Witness اولیه |
داده فقط شناسههای ساختگی، IRR خیالی و نمای تومانِ صریحاً برچسبخورده دارد. ارقام فارسی/عربی/لاتین و Unicode NFC آزمایش میشوند؛ UTC منبع Instant است و Asia/Tehran/Jalali فقط View هستند. هیچ نام، موبایل، ایمیل، IP، حساب، PAN، CVV2، OTP، Cookie، Token، Credential، Log یا Screenshot واقعی استفاده نمیشود.
Fixture قابلتکرار: سبزی سطحی در برابر ۱۹۱ Finding
Fixture مستقل `SYN-ENVIRONMENT-DELTA-REPRO-۰۱` با Node.js و بدون Dependency بیرونی اجرا شد. داشبورد سطحی Commit `abc1234`، Tag `checkout:latest`، ۷۲/۷۲ Check توسعه و ۶/۶ Container در حال اجرا را دید و `PARITY_PASS` اعلام کرد. ممیزی ۱۹۲قاعدهای، ۱۵۸ Field الزامی، ۳۴ ادعای ممنوع و هشت رابطه را سنجید و همان ورودی را با دقیقاً ۱۹۱ Finding به HOLD برد.
| گروه | قاعده | نمونه |
|---|---|---|
| Identity | 16 | Build/Artifact/Run/Environment |
| Observation | 16 | Question/Actual/Impact/Unknown |
| Source + Target Fingerprint | 44 | Platform/Config/Time/Network/Data |
| Delta | 18 | Path/Relevance/Experiment/State |
| Reproduction | 20 | Witness/Control/Attempt/Reset/Oracle |
| Evidence | 18 | Manifest/Timeline/Trace/Access |
| Governance | 18 | Disposition/Authority/Correction/Limit |
| Forbidden + Relation | 42 | مطلقگویی و سازگاری بین Fieldها |
نسخهی اصلاحشده `BUILD-SYN-۲۹` و `sha256:synthetic29` را Freeze کرد، Fingerprintهای `FP-DEV-SYN-۲۹` و `FP-TEST-SYN-۲۹` را ساخت، Delta زمان/Flag را Candidate دانست، سه Attempt شامل دو Failure و یک Control را با حساب درست ثبت کرد و به `READY_FOR_ENVIRONMENT_DELTA_REVIEW` با صفر Finding رسید. این خروجی فقط کاملبودن ساختاری را نشان میدهد؛ نه Cause، درستی Evidence، نبود Defect، Parity، کیفیت محصول یا آمادگی Release.
Automation چه چیزی را جمع کند؟
- Build/Artifact/Deployment identity و Provenance reference؛
- Fingerprint با Schema و Collector version ثابت؛
- Canonical diff با Ignore ruleهای بازبینیشده؛
- Run/Attempt manifest، Exit semantics و Oracle version؛
- Evidence index با Redaction، Retention و Access؛
- Drift alert با Baseline دقیق، نه «محیط فرق کرد»؛
- Correction link برای تصمیمها و Resultهای متاثر.
در CI، Artifact، Cache، Report و Log را جدا نگه دارید؛ برای الگوی عملی، تست خودکار در GitLab CI را ببینید. یکپارچهسازی Collectorها نیز به Data Contract، Retry و Trace نیاز دارد؛ موضوعی که در یکپارچهسازی ابزارهای تست پوشش داده شده است.
AI در تحلیل Environment Delta
AI میتواند Deltaها را خوشهبندی، Fieldهای مشکوک را پیشنهاد، Log excerpt را Redact یا Experiment draft تولید کند. اما نباید Secret دریافت کند، Root cause را خودکار قطعی بداند، Evidence جعلی بسازد، Disposition یا Risk acceptance را بدون Authority صادر کند یا Record قبلی را بیردپا بازنویسی کند. Prompt/model/version/input references و Human review را ثبت کنید.
معیارهای سالم و Countermetricها
| Metric | کاربرد | Countermetric |
|---|---|---|
| Time to first comparable pair | سرعت ساخت Witness/Control | Evidence completeness |
| Unknown Delta age | پیری تفاوتهای بیمالک | Deltaهای اشتباه حذفشده |
| Reproduction attempts | هزینه و نرخ مشاهده | State reset quality |
| Fingerprint coverage | ابعاد جمعآوریشده | Sensitive-data exposure |
| Correction latency | سرعت اصلاح Claim | Affected decisions reached |
| Environment-caused escapes | یادگیری از طبقهبندی | Misclassification/reopen rate |
هدف «صفر Delta» یا «کمترین زمان بستن Ticket» نیست؛ این هدفها Collector ناقص، پاککردن تفاوت یا Disposition عجولانه را تشویق میکنند. کیفیت تصمیم و Claim limit را کنار سرعت بسنجید.
۳۴ Anti-pattern که باید متوقف شوند
- Commit یکسان یعنی Executable یکسان.
- Version label یا latest tag را هویت Artifact دانستن.
- Container را تضمین رفتار یکسان دانستن.
- Running، Ready، Healthy و Correct را یکی گرفتن.
- Pass توسعه را ابطال Failure هدف دانستن.
- Failure هدف را اثبات خرابی محیط دانستن.
- Environment issue را خودکار Not a defect بستن.
- Cannot reproduce را نبود Defect دانستن.
- یک Retry موفق را Closure دانستن.
- Copyکردن Secret برای Parity.
- Production parity را همیشه الزامی دانستن.
- Production data را شرط بازتولید دانستن.
- Log بیشتر را علت قطعی دانستن.
- Log کامل را Evidence امن فرضکردن.
- Timestamp برابر را ترتیب قطعی دانستن.
- Timezone را فقط نمایش دانستن.
- Locale را فقط ترجمه دانستن.
- Network را Up/Down مدلکردن.
- Version سرویس را هویت رفتار دانستن.
- Schema برابر را State برابر دانستن.
- Cache را بعد از Restart بیاثر دانستن.
- Feature Flag را جزئیات Deployment دانستن.
- Architecture را همیشه بیربط دانستن.
- Package lock را اثبات بایت نصبشده دانستن.
- Fingerprint را اثبات Relevance علّی دانستن.
- حذف همهی Deltaها بدون توجه به Claim.
- صفر Delta را تضمین رفتار یکسان دانستن.
- چند متغیر را در یک Experiment تغییر دادن.
- Reset بیمدرک بین Attemptها.
- Control Run بدون همان Oracle.
- تغییر بیصدای Report یا Fingerprint.
- AI برای Root cause یا Disposition خودکار.
- مالکیت مبهم «همه بررسی کنند».
- سرزنش فرد بهجای مقایسهی دو Run.
چکلیست ۳۲نقطهای Owner
| حوزه | سؤالهای کنترل |
|---|---|
| Identity | Protocol/Product/Repo/Commit/Build/Artifact/Release/Deployment مشخص است؟ |
| Runs | Source/Target Environment و Run/Attempt جدا هستند؟ |
| Observation | Expected source، Actual، Trigger، Subject، Frequency، Unknown ثبت است؟ |
| Fingerprint | Schema/Collector/time/digest و ابعاد لازم ثبتاند؟ |
| Config | Secret حذف و Reference/version نگه داشته شده است؟ |
| Data | Snapshot/Seed/Schema/Cache/Queue state شناخته شده است؟ |
| Delta | Path/class/relevance/confidence/owner/next experiment دارد؟ |
| Experiment | Artifact/Procedure/Oracle ثابت و یک متغیر تغییر میکند؟ |
| Attempts | ID، Reset، numerator/denominator و Timeline روشن است؟ |
| Evidence | Manifest/subject/run/digest/redaction/access/retention دارد؟ |
| Decision | Vocabulary، Authority، rationale، due/expiry/reopen روشن است؟ |
| Correction | Supersedes و Affected-decision query وجود دارد؟ |
| Claim | آنچه نتیجه ثابت نمیکند صریح نوشته شده است؟ |
Pilot سیروزه برای تیم کوچک
| بازه | کار | خروجی/Guardrail |
|---|---|---|
| روز ۱–۵ | انتخاب یک Failure پرتکرار و تعریف Identity chain | بدون دسترسی Production یا Secret |
| روز ۶–۱۰ | Fingerprint کمینه برای دو Environment | Schema v1 + redaction review |
| روز ۱۱–۱۵ | ساخت Witness/Control و Delta registry | Artifact/Oracle ثابت |
| روز ۱۶–۲۰ | سه Experiment یکمتغیره | Attempt IDs + reset evidence |
| روز ۲۱–۲۵ | Disposition و Correction drill | Authority/expiry/reopen |
| روز ۲۶–۳۰ | بازبینی Metric و تصمیم Scale/Adapt/Stop | Countermetric و claim limits |
قالب نهایی Environment Delta Packet
Environment Delta Packet 1) Question + Expected Source + Observation + Unknowns 2) Repository/Commit/Build/Artifact/Release/Deployment IDs 3) Source and Target Environment/Run/Attempt IDs 4) Fingerprint schema/version/digests + redaction policy 5) Ranked Delta records + relevance/confidence/rationale 6) Frozen Reproduction + Witness/Control + Reset + Oracle 7) Evidence Manifest + Timeline/Trace/Metric/Excerpt refs 8) Experiment log: one change → observed result 9) Disposition + Authority + Owner + due/expiry/reopen 10) Claim limit + Correction/Affected-decision path
جمعبندی
«روی ماشین من کار میکند» را رد یا قبول نکنید؛ آن را به Source Run قابلردیابی تبدیل کنید. سپس Target Witness را با همان Artifact، Procedure و Oracle جفت کنید، دو Fingerprint کمینه بسازید، Deltaها را بدون ادعای Cause رتبهبندی کنید و با Experimentهای یکمتغیره پیش بروید. Docker، IaC و CI ابزارهای مفیدی برای کاهش بخشی از Drift هستند، اما قرارداد هویت، Runtime inputs، State، Evidence و Correction را جایگزین نمیکنند.
سؤالات متداول
آیا Docker مشکل «روی ماشین من کار میکند» را حل میکند؟
Docker میتواند بخشی از Artifact و Runtime filesystem را قابلحملتر کند، اما Kernel/Architecture، Config، Secret reference، Clock، Network، Data، Dependency و Orchestration همچنان ممکن است فرق کنند. Image digest را ثابت و Deltaهای بیرون Image را جدا ثبت کنید.
بهترین راه مقایسه دو محیط چیست؟
دو Run مشخص را انتخاب کنید، Build/Artifact/Procedure/Oracle را ثابت کنید، Fingerprintهای همSchema بگیرید، Delta Registry بسازید و هر Candidate را با یک Intervention قابلبازگشت آزمایش کنید. Diff خام Config بهتنهایی کافی نیست.
اگر باگ فقط در محیط تست رخ دهد، Product Defect نیست؟
نمیتوان از محل وقوع چنین نتیجهای گرفت. Failure ممکن است Product، Environment، Testware، Data/State، Dependency یا Expected variance باشد؛ حتی Config محیط میتواند بخشی از محصول تحویلی باشد. Disposition به Basis و Evidence نیاز دارد.
چه اطلاعاتی را از Environment ثبت نکنیم؟
Secret، Token، Password، دادهی شخصی و Dump بیمرز Log/Environment variables را ثبت نکنید. با Policy و حداقل دسترسی، از Reference/version، Schema، presence و Digest امن استفاده کنید؛ Retention و Redaction را در Manifest بنویسید.
صفرشدن Environment Delta یعنی رفتار حتماً یکسان است؟
خیر. صفر Delta فقط میگوید Collector فعلی در Fieldهای مدلشده تفاوتی ندیده است. ورودی اندازهگیرینشده، State، Timing، Dependency یا نقص Collector ممکن است باقی بماند. Claim را به Schema، زمان و Runهای مقایسهشده محدود کنید.

